AD7606的RTL模块与VIVADO行为级仿真

以前写过一个AD7606数据采集的模块,支持最大8片AD,64路的AD数据采集,今天,对这个模块进行一下仿真,具体思路如下:

通过RTL模块控制AD采样,然后写FIFO,最后通过DMA发送到ZYNQ的DDR内存,本人时菜鸟级别,里面也许会存在很多问题,欢迎一起探讨,不喜勿喷

RTL模块程序如下(模块中有些语句不能综合,需要时改一下):

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/12/09 11:30:54
// Design Name: 
// Module Name: AD7606_CTRL
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module AD7606_CTRL(
input s_axis_aclk,//输入时钟
input s_axis_aresetn,//复位信号
input [31:0]frq_data0,//系统频率数据0
input [31:0]frq_data1,//系统频率数据1
input S_AXIS_tready,//FIFO接受就绪
output S_AXIS_tvalid,//发送数据有效
output S_AXIS_tlast,//数据发送结束
output [15:0]S_AXIS_tdata,//FIFO写数据
input  [7:0]adDataLine,//AD数据线
input  [7:0]adBusy,//AD忙信号
output adReset,//AD复位信号
output adConvst,//AD转换启动信号
output [7:0]adCs,//AD片选
output adRead//AD读使能信号
    );
reg    S_AXIS_tvalid;
reg    S_AXIS_tlast;
reg    [15:0]S_AXIS_tdata;

parameter  [1:0]DATATRANS_WAIT  = 2'b00;
parameter  [1:0]DATATRANS_START = 2'b01;
parameter  [1:0]DATATRANS_END   = 2'b10;
reg [1:0]currentState;
reg [1:0]nextState;
//时序逻辑
always @(posedge s_axis_aclk or negedge s_axis_aresetn)begin
    if(!s_axis_aresetn)begin
        currentState <= 2'b00;
    end
    else begin
        currentState <= nextState;
    end
end
//组合逻辑
always @(posedge s_axis_aclk  or negedge  s_axis_aresetn)begin
    if (!s_axis_aresetn)begin
      S_AXIS_tvalid <= 1'b0;
      S_AXIS_tlast <= 1'b0;
      S_AXIS_tdata <= 32'd0;
      nextState <= DATATRANS_WAIT;
    end
    else begin
        case(currentState)
        DATATRANS_WAIT:begin
            if(S_AXIS_tready)begin
                S_AXIS_tvalid <= 1'b1;
                nextState <= DATATRANS_START;
            end
            else begin
                S_AXIS_tvalid <= 1'b0;
                nextState <= DATATRANS_WAIT;
            end
        end
        DATATRANS_START:begin
            if(S_AXIS_tready)begin //FIFO可写
                if(smpRdIndex != smpIndex)begin
                    if(smpRdIndex >= AD_SUM*AD_CHN_SUM)begin
                        smpRdIndex <= 8'b0000_0000;
                        S_AXIS_tlast <= 1'b1;
                        nextState <= DATATRANS_END;
                    end
                    else begin
                        S_AXIS_tdata <= smpDataTmpBuf[smpRdIndex];
                        smpRdIndex <= smpRdIndex +1'b1;
                    end
                end
                else begin
                    S_AXIS_tlast <= 1'b0;
                    nextState <= DATATRANS_START;
                end
            end
            else begin //等待FIFO可写
               S_AXIS_tdata <= S_AXIS_tdata;
               nextState <= DATATRANS_START;
            end
        end
        DATATRANS_END:begin
            if(!S_AXIS_tready)begin //FIFO满则等待
                S_AXIS_tlast <= 1'b1;
                S_AXIS_tvalid <= 1'b1;
                S_AXIS_tdata <= S_AXIS_tdata;
                nextState <= DATATRANS_END;
            end
            else begin // 写入结束
                S_AXIS_tlast <= 1'b0;
                S_AXIS_tvalid <= 1'b0;
                nextState <= DATATRANS_WAIT;
            end
        end
        default:
            nextState <= DATATRANS_WAIT;
        endcase
    end
end
//由于输入时钟为100Mhz,所以对输入时钟进行2分频,得到AD采样需要的50MHZ时钟
reg clk_50M;
always @(posedge s_axis_aclk  or negedge  s_axis_aresetn)begin
    if(!s_axis_aresetn)begin
        clk_50M <= 1'b0;
    end
    else begin
        clk_50M <=~clk_50M;
    end
end
//测频跟踪信号,根据输入频率(2路测频输入信号)动态调整采样周期
reg [2:0]frqErrCnt;//系统频率出错计数
reg [21:0]smp_cnt;//采样周期计数
//系统测频数据是以100MHZ为基准时钟,所以当系统频率为50HZ时,测频计数值为100000000/50=2000000
//所以,当系统频率为44.98hz时,测频计数值为100000000/44.98=2223210,当系统频率为55.02hz时,测频计数值为100000000/55.02=1817520
parameter PARAM_4498HZ = 2223210;
parameter PARAM_5502HZ = 1817520;
//采样计算:采样为200点,采样频率10K,如果以50Mhz的时钟进行采样计数,采样计数值=2000000/400,在本程序中调用系统乘法器实现/400操作
//2000000/400 = (2000000*10)>>12
always @(posedge clk_50M or negedge s_axis_aresetn)begin
    if(!s_axis_aresetn)begin
        smp_cnt <= (24'd2000000*10)>>12; 
        frqErrCnt <= 3'd0;
    end
    else if(frq_data0 > PARAM_4498HZ || frq_data0 < PARAM_5502HZ)begin
        if(frq_data1 > PARAM_4498HZ || frq_data1 < PARAM_5502HZ)begin//两路测频均不在44.98至55.02的频率范围
            if(frqErrCnt == 3'd3)begin
                smp_cnt <= (24'd2000000*10)>>12; 
                frqErrCnt <= 3'd0;
            end
            else begin
                frqErrCnt <= frqErrCnt +1'b1;
            end
        end
        else begin
            smp_cnt <= (frq_data1*10)>>12;
            frqErrCnt <= 3'd0;
        end
    end
    else begin
        smp_cnt <= (frq_data0*10)>>12;
        frqErrCnt <= 3'd0;
    end
end
//AD采样模块调用,字节操作模式,每个通道为数据高8位+数据低8位
wire [0:0]ready;
wire [7:0]adSmpData;
AD7606_SMP AD7606_COMP(
    .rst_n(s_axis_aresetn),
    .clk_50m(clk_50M),
    .sampleCnt(smp_cnt),
    .inS_data(adDataLine),
    .buzy(adBusy),
    .rst(adReset),
    .convst(adConvst),
    .cs_n(adCs),
    .rd_n(adRead),
    .IsDataReady(ready),
    .DataOut(adSmpData)
);


//采样到的8位AD数据,组合成16位AD采样数据,然后发送到FIFO
always @(s_axis_aresetn)begin
    if(!s_axis_aresetn)begin
        smpCnt <= 2'b00;
        smpIndex <= 8'b0000_0000;
        smpRdIndex <= 8'b0000_0000;
    end
end
//
parameter AD_SUM = 6;
parameter AD_CHN_SUM = 8;
reg [15:0]smpDataTmpBuf[0:AD_SUM*AD_CHN_SUM-1];
reg [7:0]smpIndex;
reg [7:0]smpRdIndex;
reg [0:0]dataReady;
reg [15:0]dataTmp;
reg [1:0]smpCnt;
always @(posedge clk_50M)begin
     if(smpIndex >= AD_SUM*AD_CHN_SUM)begin
       smpIndex <= 8'b0000_0000;
   end
end
always @(posedge dataReady)begin
         smpIndex <= smpIndex +1'b1;
end
///
always @(posedge ready)begin
   if(smpCnt >= 2'b01)begin
    dataTmp = (dataTmp << 8)+adSmpData;//此处使用阻塞语句,否则不能使用最新的数据
    smpDataTmpBuf[smpIndex] <= dataTmp;
    smpCnt <= 2'b00;
    dataReady <= 1'b1;
   end
   else begin
    smpCnt <= smpCnt +1'b1;
    dataReady <= 1'b0;
    dataTmp <= adSmpData;
   end
end
endmodule

testbench 模块如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/12/09 11:32:39
// Design Name: 
// Module Name: AD7606_SM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module AD7606_SM();
//输入信号
reg clk_i;
reg clk_rst;
reg [31:0]freq_data1;
reg [31:0]freq_data2;
reg tready;
reg [7:0]ad_dataLine;
reg [7:0]adBusy;
//输出信号
wire tvalid;
wire tlast;
wire [15:0]tdata;
wire adReset;
wire adConvst;
wire [7:0]adCs;
wire adRead;
AD7606_CTRL uut(
    .s_axis_aclk(clk_i),
    .s_axis_aresetn(clk_rst),
    .frq_data0(freq_data1),
    .frq_data1(freq_data2),
    .S_AXIS_tready(tready),
    .S_AXIS_tvalid(tvalid),
    .S_AXIS_tlast(tlast),
    .S_AXIS_tdata(tdata),
    .adDataLine(ad_dataLine),
    .adBusy(adBusy),
    .adReset(adReset),
    .adConvst(adConvst),
    .adCs(adCs),
    .adRead(adRead)
);
//占空比50%的时钟
parameter CLOCK_PERIOD = 10;
initial
    begin
      clk_i = 0; 
      clk_rst = 0;
      tready = 0;
      freq_data1 = 32'd2000000;
      freq_data2 = 32'd2000000;
      ad_dataLine = 8'd0;
      #97;
      clk_rst =1;
    end
    always 
    begin
        #(CLOCK_PERIOD/2) clk_i = ~clk_i;
    end
reg clk_50m;
always @(posedge clk_i or clk_rst)begin
    if(!clk_rst)begin
        clk_50m <= 1'b0;
    end
    else begin 
        clk_50m <= ~clk_50m;
    end
end    
always @(posedge clk_50m or clk_rst) begin
    if(!clk_rst)begin
        adBusy = 8'b0000_0000;
        tready = 0;
    end
    else begin
        if(clk_rst == 1)begin
         #7;
         tready = 1;
        end
        if(adConvst == 1)begin
        #2;
        adBusy = 8'b0011_1111;
        end
        if(adBusy == 8'b0011_1111)begin
        #4000;//AD转化时间为4us
        adBusy = 8'b0000_0000;
        end
       
    end
end
always @(negedge adRead)begin
     ad_dataLine <= $random%127;
end
endmodule

 仿真波形如下:

 

 watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTU2MDA4OQ==,size_16,color_FFFFFF,t_70

 

上图中,仿真功能主要模拟AD7606读写时序,当adread信号为低时,采样AD总线数据,合成16位数据后,通过reg [15:0]smpDataTmpBuf[0:AD_SUM*AD_CHN_SUM-1]缓存,最后经过S_AXIS_tdata数据输出到FIFO,仿真结果可以看出数据输出正常,实现了当初的想法。

 

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值