ad7606的八通道modelsim仿真

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
    end

always @(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   

 end

endmodule

仿真测试程序如下:

`timescale 1 ns/ 1 ns
module ad7606_vlg_tst();
// constants                                           
// general purpose registers

// test vector input registers
reg 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; 
    end

always@(posedge clk)                        
    begin                                                  

      ad_data <= $random;      //使用随机数模拟采样信号        

    end  

endmodule

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

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

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
您好!对于ad7606Verilog驱动仿真,您可以按照以下步骤进行操作: 1. 首先,您需要编写一个ad7606Verilog模块,该模块应该包含对ad7606芯片的驱动和控制逻辑。这个模块应该能够与仿真环境进行交互,例如通过输入输出端口与仿真器进行通信。 2. 接下来,您可以使用一种Verilog仿真器,如ModelSim、VCS等,来运行您的仿真。安装并配置好仿真器后,您可以创建一个仿真测试台,并将ad7606模块实例化为其中的一个组件。 3. 在仿真测试台中,您可以为ad7606模块提供输入信号,例如时钟、复位信号、数据输入等。您还可以在仿真过程中读取ad7606模块的输出信号,例如数据输出、状态信号等。 4. 编写仿真测试案例,通过向ad7606模块提供合适的输入信号,并验证模块的输出信号是否符合预期。您可以根据ad7606的规格书和datasheet来编写测试案例,覆盖模块的各种工作模式和边界条件。 5. 运行仿真,并观察模块的行为是否符合预期。您可以使用仿真器提供的波形查看工具来查看信号的波形,以及调试模块的功能和性能。 需要注意的是,ad7606是一个具体的芯片,其驱动逻辑和仿真方法可能因具体的设计需求而异。上述步骤仅供参考,您可能需要根据具体情况进行适当的调整和修改。 希望对您有所帮助!如果您还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值