FPGA project - AD7606

I use AD7606 to catch 8 ch sigals.

`timescale 1ns / 1ps

module ad7606(
    input                   clk                 ,       //clock input
    input                   rst_n               ,       //reset input, low active
    input                   ad_busy             ,       //ad7606 convert busy
    input                   first_data          ,       //ad7606 first data
    input                   sign                ,       //1:module active 0:module fail
    input   [15:0]          ad_data             ,       //ad7606 data input
    
    output                  ad_data_valid       ,       //ad7606 data finish convert sign
    output  [2:0]           ad_os               ,       //oversampling mode select
    
    output  reg             module_init         ,       //module init finish
    output  reg             ad_cs               ,       //ad7606 AD cs
    output  reg             ad_rd               ,       //ad7606 AD rd
    output  reg             ad_reset            ,       //ad7606 AD reset
    output  reg             ad_convstab         ,       //ad7606 AD convert start
    
    output  reg [15:0]      ad_ch1              ,       //ad7606 convert data ch1
    output  reg [15:0]      ad_ch2              ,       //ad7606 convert data ch2
    output  reg [15:0]      ad_ch3              ,       //ad7606 convert data ch3
    output  reg [15:0]      ad_ch4              ,       //ad7606 convert data ch4
    output  reg [15:0]      ad_ch5              ,       //ad7606 convert data ch5
    output  reg [15:0]      ad_ch6              ,       //ad7606 convert data ch6
    output  reg [15:0]      ad_ch7              ,       //ad7606 convert data ch7
    output  reg [15:0]      ad_ch8                      //ad7606 convert data ch8
);

//macro definition parameters
parameter                  cycle_time      =   2500    ;       //a convert cycle set

//state machine code
localparam                  IDLE            =   4'd0    ;      //init and wait state
localparam                  AD_CONV         =   4'd1    ;      //posedge edge start convert
localparam                  Wait_1          =   4'd2    ;      //wait finish convert
localparam                  Wait_busy       =   4'd3    ;      //check convert finish sign
localparam                  READ_CH1        =   4'd4    ;      //data ch1 read
localparam                  READ_CH2        =   4'd5    ;      //data ch2 read
localparam                  READ_CH3        =   4'd6    ;      //data ch3 read
localparam                  READ_CH4        =   4'd7    ;      //data ch4 read
localparam                  READ_CH5        =   4'd8    ;      //data ch5 read
localparam                  READ_CH6        =   4'd9    ;      //data ch6 read
localparam                  READ_CH7        =   4'd10   ;      //data ch7 read
localparam                  READ_CH8        =   4'd11   ;      //data ch8 read
localparam                  READ_DONE       =   4'd12   ;      //data deliver

//reg define
reg [3:0]                   state               ;       //current state reg
reg [5:0]                   i                   ;       //state change count
reg [15:0]                  cycle_cnt           ;       //convert data count
reg [7:0]                   rst_cnt             ;       //ad_reset time count

//assign define
assign  ad_os = 3'b000;                                 //oversampling mode select
//in the state of READ_DONE then set ad_data_valid high level
assign  ad_data_valid = (state == READ_DONE) ? 1'b1 : 1'b0;


//when the system reset then also reset the AD7606
//module_init means this module wether finish init
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        ad_reset <= 1'b0;
        rst_cnt <= 8'd0;
        module_init <= 1'b0;
    end
    else if(rst_cnt < 8'hff) begin
        rst_cnt <= rst_cnt + 1'b1;
        ad_reset <= 1'b1;
    end
    else begin
        ad_reset <= 1'b0;
        module_init <= 1'b1;
    end
end

//AD7606 convert process
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state <= IDLE;
        ad_cs <= 1'b1;
		ad_rd <= 1'b1;
		ad_convstab <= 1'b1;
		i <= 6'd0;
		ad_ch1 <= 16'd0;
		ad_ch2 <= 16'd0;
		ad_ch3 <= 16'd0;
		ad_ch4 <= 16'd0;
		ad_ch5 <= 16'd0;
		ad_ch6 <= 16'd0;
		ad_ch7 <= 16'd0;
		ad_ch8 <= 16'd0;
    end
    else begin
        case(state)
//in the state of IDLE ready to convst
            IDLE: begin
                ad_cs <= 1'b1;
				ad_rd <= 1'b1;
				ad_convstab <= 1'b1;
				if(ad_reset == 0 && cycle_cnt == 9) begin
				    state<=AD_CONV;
				end
            end
//convst start at posedge so pull down and then pull up the ad_convstab
            AD_CONV: begin
                if(cycle_cnt == 11) begin
                    state <= Wait_1;
                    ad_convstab <= 1'b1;
                end
                else begin
                    ad_convstab <= 1'b0;
                end
            end
//wait in order to aovid BUSY have not pull up            
            Wait_1: begin
                if(cycle_cnt == 16) begin
                    state<=Wait_busy;
                end
            end
//when BUSY pull down means convst finsih            
            Wait_busy: begin
                if(ad_busy == 1'b0) begin
                    state<=READ_CH1;
                end
            end
//in the state of READ_CH1 pull down ad_cs for whole data deviler
//get the channel1 data            
            READ_CH1: begin
                ad_cs <= 1'b0;
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch1<=ad_data;
                    state<=READ_CH2;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel2 data            
            READ_CH2: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch2<=ad_data;
                    state<=READ_CH3;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel3 data            
            READ_CH3: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch3<=ad_data;
                    state<=READ_CH4;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel4 data            
            READ_CH4: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch4<=ad_data;
                    state<=READ_CH5;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel5 data            
            READ_CH5: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch5<=ad_data;
                    state<=READ_CH6;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel6 data            
            READ_CH6: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch6<=ad_data;
                    state<=READ_CH7;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel7 data            
            READ_CH7: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch7<=ad_data;
                    state<=READ_CH8;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel8 data            
            READ_CH8: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch8<=ad_data;
                    state<=READ_DONE;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//in the state of READ_DONE pull up the ad_rd and ad_cs 
//finish a cycle then goto next cycle           
            READ_DONE: begin
                ad_rd <= 1'b1;
				ad_cs <= 1'b1;
				if(cycle_cnt == cycle_time - 1) begin
				    state<=IDLE;
				end
            end
//if any error happen state goto IDLE            
            default: begin
                state<=IDLE;
            end
        endcase
    end
end

//cycle_cnt count a cycle of convert
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cycle_cnt <= 16'd0;
    end
//only input sign is high then actie this convert module
//if cycle_cnt reach set num then empty cycle_cnt and into next cycle
    else if(sign) begin
        if(cycle_cnt == cycle_time - 1) begin
            cycle_cnt <= 16'd0;
        end
        else begin
            cycle_cnt <= cycle_cnt + 1'b1;
        end
    end
    else  begin
        cycle_cnt <= 16'd0;
    end
end

endmodule

AD7606 is a ADC IC and can collect 8  channels data in 16 bits at 200KSPS. 

First let us know some parameters.

1.ad_os: this is a control of oversample, it means use low rate to get a stable data.

2.cycle_time: this parameter is created by me to control a whole cycle. It means a whole cycle count. If set cycle_time 250, ad_os 3'b000 and input clk is 50MHz. The turly change rate is 50,000,000 / 250 = 200KSPS.

Now let see how to control AD7606 convst.

CONVST AB controls whether the convst starts. When put it from 0 to 1, the convst starts, and the the BUSY line will be high means the IC is convsting the data. When BUSY line change to 0 means the convest is finished, and you can use CS' and RD' to get the data. When CS' and RD' both change from 1 to 0, the convest will be storage on DATA lines.

So the cycle_cnt in the code is always add 1 to confirm the rate.

The process code is below.

//AD7606 convert process
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state <= IDLE;
        ad_cs <= 1'b1;
		ad_rd <= 1'b1;
		ad_convstab <= 1'b1;
		i <= 6'd0;
		ad_ch1 <= 16'd0;
		ad_ch2 <= 16'd0;
		ad_ch3 <= 16'd0;
		ad_ch4 <= 16'd0;
		ad_ch5 <= 16'd0;
		ad_ch6 <= 16'd0;
		ad_ch7 <= 16'd0;
		ad_ch8 <= 16'd0;
    end
    else begin
        case(state)
//in the state of IDLE ready to convst
            IDLE: begin
                ad_cs <= 1'b1;
				ad_rd <= 1'b1;
				ad_convstab <= 1'b1;
				if(ad_reset == 0 && cycle_cnt == 9) begin
				    state<=AD_CONV;
				end
            end
//convst start at posedge so pull down and then pull up the ad_convstab
            AD_CONV: begin
                if(cycle_cnt == 11) begin
                    state <= Wait_1;
                    ad_convstab <= 1'b1;
                end
                else begin
                    ad_convstab <= 1'b0;
                end
            end
//wait in order to aovid BUSY have not pull up            
            Wait_1: begin
                if(cycle_cnt == 16) begin
                    state<=Wait_busy;
                end
            end
//when BUSY pull down means convst finsih            
            Wait_busy: begin
                if(ad_busy == 1'b0) begin
                    state<=READ_CH1;
                end
            end
//in the state of READ_CH1 pull down ad_cs for whole data deviler
//get the channel1 data            
            READ_CH1: begin
                ad_cs <= 1'b0;
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch1<=ad_data;
                    state<=READ_CH2;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel2 data            
            READ_CH2: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch2<=ad_data;
                    state<=READ_CH3;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel3 data            
            READ_CH3: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch3<=ad_data;
                    state<=READ_CH4;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel4 data            
            READ_CH4: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch4<=ad_data;
                    state<=READ_CH5;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel5 data            
            READ_CH5: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch5<=ad_data;
                    state<=READ_CH6;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel6 data            
            READ_CH6: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch6<=ad_data;
                    state<=READ_CH7;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel7 data            
            READ_CH7: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch7<=ad_data;
                    state<=READ_CH8;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//get the channel8 data            
            READ_CH8: begin
                if(i == 3) begin
                    i <= 6'd0;
                    ad_rd <= 1'b1;
                    ad_ch8<=ad_data;
                    state<=READ_DONE;
                end
                else begin
                    i <= i + 6'd1;
                    ad_rd <= 1'b0;
                end
            end
//in the state of READ_DONE pull up the ad_rd and ad_cs 
//finish a cycle then goto next cycle           
            READ_DONE: begin
                ad_rd <= 1'b1;
				ad_cs <= 1'b1;
				if(cycle_cnt == cycle_time - 1) begin
				    state<=IDLE;
				end
            end
//if any error happen state goto IDLE            
            default: begin
                state<=IDLE;
            end
        endcase
    end
end

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值