ad7606的八通道modelsim仿真

来源:互联网 发布:coc地狱塔升级数据 编辑:程序博客网 时间:2024/05/01 04:24

ad7606的八通道modelsim仿真

解决的疑问主要有一下几点:
(1)之前一直困惑于如何确定AD的采样频率,后来在朋友的提示下,在程序中加入了定时器,每50us读取一次数据,实现采样频率变为20K。
(2)对ad_reset信号,之前一直以为计数器记满之后,会自动复位,似的该信号会马上变为高电平,仿真后才发现并未如此,满量程的计数器将会一直保持在ff的状态,使得ad-reset信号保持为低,也就进入了循环采样的状态。cnt计数器只是对ad复位进行操作,这正决定采样频率的是cnt50us计数器。
(3)使用$random函数模拟采样信号,使得仿真结果更真实可观。

ad的采样程序如下:

`timescale 1ns / 1ns//////////////////////////////////////////////////////////////////////////////////// Module Name:    ad7606 //////////////////////////////////////////////////////////////////////////////////module ad7606(   input                clk,                  //50mhz    input               rst_n,    input [15:0]        ad_data,            //ad7606 采样数据    input               ad_busy,            //ad7606 忙标志位   input                first_data,         //ad7606 第一个数据标志位      output [2:0]        ad_os,              //ad7606 过采样倍率选择    output reg          ad_cs,              //ad7606 AD cs    output reg          ad_rd,              //ad7606 AD data read    output reg          ad_reset,           //ad7606 AD reset    output reg          ad_convstab,         //ad7606 AD convert start    output reg [15:0] ad_ch1,              //AD第1通道的数据    output reg [15:0] ad_ch2,              //AD第2通道的数据    output reg [15:0] ad_ch3,              //AD第3通道的数据    output reg [15:0] ad_ch4,              //AD第4通道的数据    output reg [15:0] ad_ch5,              //AD第5通道的数据    output reg [15:0] ad_ch6,              //AD第6通道的数据    output reg [15:0] ad_ch7,              //AD第7通道的数据    output reg [15:0] ad_ch8,              //AD第8通道的数据     output reg [3:0]  state    //output reg [3:0] cnt    );reg [7:0] cnt = 0 ;reg [15:0] cnt50us = 0;reg [5:0] i;//reg [3:0] state;parameter IDLE=4'd0;parameter AD_CONV=4'd1;parameter Wait_1=4'd2;parameter Wait_busy=4'd3;parameter READ_CH1=4'd4;parameter READ_CH2=4'd5;parameter READ_CH3=4'd6;parameter READ_CH4=4'd7;parameter READ_CH5=4'd8;parameter READ_CH6=4'd9;parameter READ_CH7=4'd10;parameter READ_CH8=4'd11;parameter READ_DONE=4'd12;//parameter display=4'd13;assign ad_os=3'b000;  //无过采样//ad复位always@(posedge clk) begin    if(cnt<8'hff) begin        cnt<=cnt+1;        ad_reset<=1'b1;      end      else        ad_reset<=1'b0;  //计数器达到ff后停止,ad_reset恒为零        end//使用定时器来设置采样频率always @(posedge clk or negedge rst_n) //每50us读取一次数据,ad的采样率为20K    begin        if(rst_n == 0)            cnt50us <= 0;        else begin             if(cnt50us < 16'd2499)                begin                    cnt50us <= cnt50us + 1;                end            else                cnt50us <= 0;            end    endalways @(posedge clk)  begin     if (ad_reset==1'b1) begin   //初始化ad             state<=IDLE;              ad_ch1<=0;             ad_ch2<=0;             ad_ch3<=0;             ad_ch4<=0;             ad_ch5<=0;             ad_ch6<=0;             ad_ch7<=0;             ad_ch8<=0;             ad_cs<=1'b1;             ad_rd<=1'b1;              ad_convstab<=1'b1;   //8通道同步采样             i<=0;     end              else begin          case(state)     //need time:(20+2+5+1+3*8+1)*20ns=1060ns, fmax=1/1060ns=1MHZ          IDLE: begin                 ad_cs<=1'b1;                 ad_rd<=1'b1;                  ad_convstab<=1'b1;                  if(i==20) begin        //延时20个时钟后开始转换                     i<=0;                                state<=AD_CONV;                 end                 else                      i<=i+1'b1;          end          AD_CONV: begin                        if(i==2) begin                        //等待2个lock,convstab的下降沿最少为25ns,故至少需要两个时钟                     i<=0;                                state<=Wait_1;                     ad_convstab<=1'b1;                                       end                 else begin                     i<=i+1'b1;                     ad_convstab<=1'b0;                     //启动AD转换                 end          end          Wait_1: begin                             if(i==5) begin                           //等待5个clock, 等待busy信号为高(tconv)                     i<=0;                     state<=Wait_busy;                 end                 else                      i<=i+1'b1;          end                  Wait_busy: begin                             if(ad_busy==1'b0) begin                    //等待busy为低电平  即转换之后读取模式                     i<=0;                                state<=READ_CH1;                 end          end          READ_CH1: begin                  ad_cs<=1'b0;                              //cs信号有效  直到读取8通道结束                 if(i==3) begin                            // 低电平持续3个时钟,完成通道1的读入                     ad_rd<=1'b1;                     i<=0;                     ad_ch1<=ad_data;                        //读CH1                     state<=READ_CH2;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH2: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch2<=ad_data;                        //读CH2                     state<=READ_CH3;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH3: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch3<=ad_data;                        //读CH3                     state<=READ_CH4;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH4: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch4<=ad_data;                        //读CH4                     state<=READ_CH5;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH5: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch5<=ad_data;                        //读CH5                     state<=READ_CH6;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH6: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch6<=ad_data;                        //读CH6                     state<=READ_CH7;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH7: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch7<=ad_data;                        //读CH7                     state<=READ_CH8;                                 end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_CH8: begin                  if(i==3) begin                     ad_rd<=1'b1;                     i<=0;                     ad_ch8<=ad_data;                        //读CH8                     state<=READ_DONE;                                end                 else begin                     ad_rd<=1'b0;                        i<=i+1'b1;                 end          end          READ_DONE:begin                                 //完成读,回到idle状态                     ad_rd<=1'b1;                         ad_cs<=1'b1;                     if(cnt50us == 16'd2499)                      //不加此条件,则ad完成一次读取需1280ns,采样频率781.25K,但需注意ad每通道的追高采样只能为200K                        state<=IDLE;                    else                        state<=READ_DONE;          end                 default:  state<=IDLE;          endcase       end    endendmodule

仿真测试程序如下:

`timescale 1 ns/ 1 nsmodule ad7606_vlg_tst();// constants                                           // general purpose registers// test vector input registersreg ad_busy;reg [15:0] ad_data;reg clk;reg first_data;reg rst_n;// wires                                               wire [15:0]  ad_ch1;wire [15:0]  ad_ch2;wire [15:0]  ad_ch3;wire [15:0]  ad_ch4;wire [15:0]  ad_ch5;wire [15:0]  ad_ch6;wire [15:0]  ad_ch7;wire [15:0]  ad_ch8;wire ad_convstab;wire ad_cs;wire [2:0]  ad_os;wire ad_rd;wire ad_reset;wire [3:0] state;// assign statements (if any)                          ad7606 i1 (// port map - connection between master ports and signals/registers       .ad_busy(ad_busy),    .ad_ch1(ad_ch1),    .ad_ch2(ad_ch2),    .ad_ch3(ad_ch3),    .ad_ch4(ad_ch4),    .ad_ch5(ad_ch5),    .ad_ch6(ad_ch6),    .ad_ch7(ad_ch7),    .ad_ch8(ad_ch8),    .ad_convstab(ad_convstab),    .ad_cs(ad_cs),    .ad_data(ad_data),    .ad_os(ad_os),    .ad_rd(ad_rd),    .ad_reset(ad_reset),    .clk(clk),    .first_data(first_data),    .rst_n(rst_n),    .state(state)    //.cnt(cnt));initial                                                    begin                                                          ad_busy = 0;        first_data = 0;        clk = 0;        forever             //50MHz        #10        clk = ~clk;                                                                                                                                                    $display("Running testbench");                          end  initial    begin      rst_n = 1;      #10;      rst_n = 0;      #20;      rst_n = 1;     endalways@(posedge clk)                            begin                                                        ad_data <= $random;      //使用随机数模拟采样信号            end  endmodule

仿真结果如下:
仿真结果,每5000ns读取一次数据

ad程序的状态图如下:这里写图片描述

0 0