基于Zynq的数据采集系统设计与调试(二) —— AD接口

来源:互联网 发布:vb for mac 编辑:程序博客网 时间:2024/04/29 23:42

前言:

    本设计中使用AD的是ADI的AD7989-1,AD7989-1是18-bit,逐次逼近型模数转换器。支持CS模式、链模式。本设计中采用3线CS模式,此模式常用于连接到SPI接口的数字主机,关于AD7989的详细信息请参考芯片手册:AD7989-1_7989-5.pdf

一. AD接口

    1)3线CS模式的时序图如下:

   

    2)时序规格如下:

    注:

        (1) 查看数据手册,知道3线CS模式,SPI接口数据传输时,MSB是在CNV信号下降压后0.5~1个clk(50MHz)有效,之后的数据位都是在SCLK的下降沿有效。

        (2) 因为SCLK下降沿数据变化(其它位数据有效),我们在上升沿读数据。因此在AD接口模块ad7989_dev_if.v中,sclk上升沿将sdo上的数据移入到serial_buffer中。

     

    3)时序设计: 参考之前写的一篇博客:http://blog.csdn.net/yang2011079080010/article/details/51541083


二. AD接口的实现

`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 2016/05/16 16:33:43// Design Name: // Module Name: ad7989_dev_if// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// 注:ADC采样率100KSPS//////////////////////////////////////////////////////////////////////////////////module   ad7989_dev_if (                           input    ad_clk,rst_n,ad_start,//ad_start: ad_start是由PS部分发送过来的ad采样控制信号                            input    ad_sdo,                      //ad转换串型数据                           output           ad_cnv,                           output           ad_sclk,                                                  output    [17:0] ad_data,                           output           ad_data_rdy   // data is available                        );                                              parameter    FPGA_CLOCK_FREQ    = 50; //50MHz    parameter    TCYC               = 10;    parameter    ADC_CYC_CNT        = FPGA_CLOCK_FREQ * TCYC - 1;        localparam    IDLE    = 3'b001;    localparam    READ    = 3'b010;    localparam    DONE    = 3'b100;        reg    [9:0]  adc_tcyc_cnt;    reg    [2:0]  main_state,next_state;    reg    [4:0]  sclk_cnt;    reg    [17:0] serial_buffer;    reg    serial_read_done;        reg    [17:0] ad_data_reg;        wire    tmsb_almost_valid;    wire    buffer_reset_s;//    wire    [17:0] ad_data;    assign    ad_cnv    =    (adc_tcyc_cnt > 25 && ad_start == 1) ? 1'b1 : 1'b0;  //adc_tcyc_cnt = 25时,cnv变为低电平    assign    tmsb_almost_valid     =     (adc_tcyc_cnt == 26 ) ? 1'b1 : 1'b0;     assign    ad_sclk     =    (adc_tcyc_cnt > 6 && adc_tcyc_cnt < 25) ? ad_clk : 1'b0; //adc_tcyc_cnt = 24时读MSB    assign    buffer_reset_s    =    (adc_tcyc_cnt == 26) ? 1'b1: 1'b0;    assign    ad_data_rdy = (serial_read_done == 1'b1 && adc_tcyc_cnt == 5) ? 1'b1:1'b0;    assign    ad_data    =    (ad_data_rdy == 1'b1) ? serial_buffer : ad_data_reg;  //ad_data修改成ad_data_reg        //ad_data_reg缓存输出数据    always @(posedge ad_clk) begin      if(!rst_n) ad_data_reg <= 18'd0;      else ad_data_reg <= ad_data;    end         //adc_tcyc_cnt控制AD采样率     always @(posedge ad_clk,negedge rst_n) begin      if(~rst_n) adc_tcyc_cnt <= ADC_CYC_CNT;      else if(adc_tcyc_cnt != 0 && ad_start == 1) adc_tcyc_cnt <= adc_tcyc_cnt - 1'b1;      else adc_tcyc_cnt <= ADC_CYC_CNT;    end        always @(posedge ad_clk,negedge rst_n) begin      if(~rst_n) main_state <= IDLE;      else main_state <= next_state;    end        always @(*)      begin        case(main_state)          IDLE: begin            if(tmsb_almost_valid) next_state = READ;            else next_state <= IDLE;          end          READ: begin            if(sclk_cnt == 0) next_state = DONE;            else next_state = READ;          end          DONE: next_state = READ;          default: next_state = IDLE;        endcase      end        always @(posedge ad_clk) begin      case(main_state)        IDLE: serial_read_done <= 1'b1;        READ: serial_read_done <= 1'b0;        DONE: serial_read_done <= 1'b1;        default: serial_read_done <= 1'b0;      endcase    end        always @(posedge ad_clk) begin      if(buffer_reset_s == 1'b1) begin        serial_buffer <= 18'd0;        sclk_cnt <= 5'd18;      end      else if(sclk_cnt > 5'd0) begin        sclk_cnt <= sclk_cnt - 5'd1;        serial_buffer <= {serial_buffer[16:0],ad_sdo};      end    endendmodule


1 0