11 ADC模块FEP-DAQ422X采集显示波形方案
软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA
登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!
1概述
本方案通过把DAQ422X采集到的数据,通过前面已经完成的示波器显示驱动进行在屏幕上显示ADC采集的波形数据。
2系统框图
3产品介绍
FEP-DAQ003- 12- 125M-250M-2数据采集模块采用一颗 TI 的ADS4225/ ADS4229低功耗高性能模数转换芯片,实现了 2 通道125/250MSPS 模数转换,并且支持 2 路数字 IO 输入/输出触发功能。
通过设置不同的通信模式,ADS4225/ADS4229 具有 LVDS DDR 接口模式和 LVCMOS SDR 接口两种模式。
3.1 硬件参数概述
FEP-DAQ003- 12- 125M-2/FEP-DAQ003- 12-250M-2 | ||
ADC 芯片 | AD4225/4229 | |
采样精度 | 12bit | |
-3db 带宽 | 320M(前置运放带宽决定) | |
IO 电平 | 1.8V 或者 3.3V 可选 | |
采样频率 | ADS4225 0~125M | ADS4229 0~250M |
模拟通道 | 2 个 | |
触发 IO | 2 个 | |
输入电平 | -5V~+5V | |
数据格式 | 二进制补码(~2048~+2047) | |
信噪比 170M(SNR) | 71.4dBFS | |
无杂散动态范围 170M(SFDR) | 88dBc | |
功耗 165M | 332mW | |
占用 IO 数量 | 40 个 GPIO |
3.2 引脚定义
3.2.1 SMA 引脚定义
引脚号 | 引脚名称 | 描述 |
PA | DAI | 模拟输入通道 1 |
PB | DBI | 模拟输入通道 2 |
TA | TriA | 双向触发输入/输出 1 |
TB | TriB | 双向触发输入/输出 2 |
3.2.2 ADS422X芯片功能引脚定义
3.2.2.1 LVDS 下接口定义
3.2.2.2 LVCMOS 下接口定义
LVDS 和CMOS 模式的数据输出时序
LVDS 的时序要求
CMOS 模式的时序要求
3.3 数据模式设置
设置 SEN 脚的工作电平,来设置 ADS4225/ADS4229 的工作模式
SEN 脚电平 | 模式 |
0V | 二进制补码和并行 CMOS 输出 |
0.375AVDD | 偏移二进制和并行 CMOS 输出 |
0.625AVDD | 偏移二进制和 DDR LVDS 输出 |
4硬件电路分析
硬件接口和子卡模块请阅读"附录 1"
配套工程的 FPGA PIN 脚定义路径为 fpga_prj/uisrc/04_pin/ fpga_pin.xdc。
5程序源码
关于HDMI输出IP的部分这里不再介绍,VTC时序设计部分这里也不详细介绍。如果读者这些基础知识不清楚的,请阅读前面的实验。
5.1ADS422X采集驱动
ADS422X 数据采集通过 IDELAY 模块调整数据相对时钟的延迟,用来设置最佳采样时刻。
`timescale 1 ns / 1 ns
module uiads422X_parallel# ( parameter FAMILY = "7SERIES", parameter integer DATA_WIDTH = 12, parameter integer DELAY_SETA = 12, parameter integer DELAY_SETB = 12 ) ( input I_refclk, input I_reset,
input I_ad_clk, input [DATA_WIDTH -1 :0]I_ad_da, input [DATA_WIDTH -1 :0]I_ad_db, output [DATA_WIDTH -1 :0]O_ad_da, output [DATA_WIDTH -1 :0]O_ad_db, output O_ad_reset, output O_ad_sen, output O_ad_sclk, output O_ad_card_en );
wire [DATA_WIDTH -1:0] da_buf,db_buf,da_buf_delay,db_buf_delay; wire idelayctrl_reset_sync; reg idelayctrl_reset; reg [3 :0]idelay_reset_cnt; reg [15:0] cnt = 0;
assign O_ad_card_en = cnt[15]; assign O_ad_reset = 1'b1; assign O_ad_sen = 1'b0; assign O_ad_sclk = 1'b0;
always @(posedge I_refclk)begin if(!cnt[15]) cnt <= cnt +1'b1; end
// Create a synchronous reset in the IDELAYCTRL refclk clock domain. reset_sync idelayctrl_reset_gen ( .clk (I_refclk), .enable (1'b1), .reset_in (I_reset), .reset_out (idelayctrl_reset_sync) );
// The IDELAYCTRL must experience a pulse which is at least 50 ns in // duration. This is ten clock cycles of the 200MHz refclk. Here we // drive the reset pulse for 12 clock cycles. always @(posedge I_refclk)begin if (idelayctrl_reset_sync == 1'b0) begin idelay_reset_cnt <= 4'b0000; idelayctrl_reset <= 1'b1; end else begin case (idelay_reset_cnt) 4'b0000 : idelay_reset_cnt <= 4'b0001; 4'b0001 : idelay_reset_cnt <= 4'b0010; 4'b0010 : idelay_reset_cnt <= 4'b0011; 4'b0011 : idelay_reset_cnt <= 4'b0100; 4'b0100 : idelay_reset_cnt <= 4'b0101; 4'b0101 : idelay_reset_cnt <= 4'b0110; 4'b0110 : idelay_reset_cnt <= 4'b0111; 4'b0111 : idelay_reset_cnt <= 4'b1000; 4'b1000 : idelay_reset_cnt <= 4'b1001; 4'b1001 : idelay_reset_cnt <= 4'b1010; 4'b1010 : idelay_reset_cnt <= 4'b1011; 4'b1011 : idelay_reset_cnt <= 4'b1100; default : idelay_reset_cnt <= 4'b1100; endcase if (idelay_reset_cnt == 4'b1100) begin idelayctrl_reset <= 1'b0; end else begin idelayctrl_reset <= 1'b1; end end end
genvar i; generate for (i = 0 ; i < DATA_WIDTH ; i = i+1) begin : DAQ_DATA IBUF #( .IBUF_LOW_PWR("TRUE"), // Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards .IOSTANDARD("DEFAULT") // Specify the input I/O standard )IBUF_da ( .O(da_buf[i]), // Buffer output .I(I_ad_da[i]) // Buffer input (connect directly to top-level port) );
IBUF #( .IBUF_LOW_PWR("TRUE"), // Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards .IOSTANDARD("DEFAULT") // Specify the input I/O standard )IBUF_db ( .O(db_buf[i]), // Buffer output .I(I_ad_db[i]) // Buffer input (connect directly to top-level port) );
end endgenerate
generate if(FAMILY == "ULTRASCALE" || FAMILY == "ULTRASCALE_PLUS")begin : ULTRASCALE_FAMILY
IDELAYCTRL #( .SIM_DEVICE ("ULTRASCALE") ) idelayctrl_inst( .RDY (idelayctrl_ready), .REFCLK (I_refclk), .RST (idelayctrl_reset) );
genvar k; for (k=0; k<DATA_WIDTH ; k=k+1) begin : rxdata_in_bus IDELAYE3 #( .DELAY_VALUE (DELAY_SETA), .DELAY_TYPE ("FIXED"), .REFCLK_FREQUENCY (300.000), .SIM_DEVICE (FAMILY) ) IDELAYE_A ( .IDATAIN (da_buf[k]), .DATAOUT (da_buf_delay[k]), .DATAIN (1'b0), .CLK (1'b0), .CE (1'b0), .INC (1'b0), .CNTVALUEIN (9'h0), .CNTVALUEOUT (), .LOAD (1'b0), .RST (1'b0), .CASC_IN (1'b0), .CASC_RETURN (1'b0), .CASC_OUT (), .EN_VTC (1'b1) ); IDELAYE3 #( .DELAY_VALUE (DELAY_SETB), .DELAY_TYPE ("FIXED"), .REFCLK_FREQUENCY (300.000), .SIM_DEVICE (FAMILY) ) IDELAYE_B ( .IDATAIN (db_buf[k]), .DATAOUT (db_buf_delay[k]), .DATAIN (1'b0), .CLK (1'b0), .CE (1'b0), .INC (1'b0), .CNTVALUEIN (9'h0), .CNTVALUEOUT (), .LOAD (1'b0), .RST (1'b0), .CASC_IN (1'b0), .CASC_RETURN (1'b0), .CASC_OUT (), .EN_VTC (1'b1) ); end end else if(FAMILY == "7SERIES") begin : SERIES7_FAMILY
IDELAYCTRL #( .SIM_DEVICE ("7SERIES") ) idelayctrl_inst( .RDY (idelayctrl_ready), .REFCLK (I_refclk), .RST (idelayctrl_reset) );
genvar k; for (k=0; k<DATA_WIDTH ; k=k+1) begin : rxdata_in_bus IDELAYE2 #( .HIGH_PERFORMANCE_MODE("TRUE"), .IDELAY_TYPE ("FIXED"), .IDELAY_VALUE (DELAY_SETA) ) IDELAYE_A ( .IDATAIN (da_buf[k]), .DATAOUT (da_buf_delay[k]), .DATAIN (1'b0), .C (1'b0), .CE (1'b0), .INC (1'b0), .CINVCTRL (1'b0), .CNTVALUEIN (5'h0), .CNTVALUEOUT (), .LD (1'b0), .LDPIPEEN (1'b0), .REGRST (1'b0) );
IDELAYE2 #( .HIGH_PERFORMANCE_MODE("TRUE"), .IDELAY_TYPE ("FIXED"), .IDELAY_VALUE (DELAY_SETB) ) IDELAYE_B ( .IDATAIN (db_buf[k]), .DATAOUT (db_buf_delay[k]), .DATAIN (1'b0), .C (1'b0), .CE (1'b0), .INC (1'b0), .CINVCTRL (1'b0), .CNTVALUEIN (5'h0), .CNTVALUEOUT (), .LD (1'b0), .LDPIPEEN (1'b0), .REGRST (1'b0) ); end end endgenerate
assign O_ad_da = da_buf_delay; assign O_ad_db = db_buf_delay;
endmodule |
5.2顶层模块调用程序
以下代码中,需要注意,通过 DELAY_SETA 和 DELAY_SETB 设置最佳的数据延迟。
对于有符号数据,通过设置 I_wave1_data(ads422x_da[11:4]+8'h80),加上 8'h80 让波形数据转为无符号,
在显示器上显示。
对于 ADS4225 修改 PLL 输出 125M 时钟
对于 ADS4229 修改 PLL 输出 250M 时钟
/**********************AD9248 ADC采集波形显示************************* *********************************************************************/
`timescale 1ns / 1ns//仿真时间刻度/精度
module ads422x_top ( input I_sysclk_p, //系统时钟输入 output O_ads422x_clk_p, output O_ads422x_clk_n, input I_ads422x_clk, input [11 :0] I_ads422x_da, input [11 :0] I_ads422x_db, output O_ads422x_reset, output O_ads422x_sen, output O_ads422x_sclk, output O_card_power_en, //子卡电源使能
output O_HDMI_CLK_P, //HDMI时钟输出 P端 output O_HDMI_CLK_N, //HDMI时钟输出 N端 output [2:0] O_HDMI_TX_P, //HDMI数据输出 P端 output [2:0] O_HDMI_TX_N //HDMI数据输出 N端 );
wire pclkx1,pclkx5,ref_clk,adc_clk,locked; //MMCM/PLL时钟信号
//ADS422X直流版需要提供差分时钟工作 OBUFDS ADC_DIFF_CLK_O_inst ( .O (O_ads422x_clk_p), // Diff_p output (connect directly to top-level port) .OB(O_ads422x_clk_n), // Diff_n output (connect directly to top-level port) .I (adc_clk) // Buffer input );
//例化MMCM/PLL IP clk_wiz_1 clk_hdmi_pll_inst ( .clk_in1 (I_sysclk_p), .reset (!rst_cnt[7]), .locked (locked), .clk_out1(ref_clk), .clk_out2(pclkx1),//像素时钟 .clk_out3(pclkx5),//HDMI输出5倍像素时钟 .clk_out4(adc_clk)//输出给ADC );
wire [11 :0] ads422x_da; wire [11 :0] ads422x_db;
uiads422X_parallel # ( .FAMILY ("7SERIES"), .DATA_WIDTH(12 ),//ADC数据位宽 .DELAY_SETA(25 ),//通道A的delay延迟 .DELAY_SETB(25 ) //通道B的delay延迟 ) uiads422X_parallel_inst ( .I_refclk (ref_clk), //IP内部的delay模块参考时钟,7系列200M KU KU+ 300M .I_reset (~locked), //IP内部复位模块 .I_ad_clk (I_ads422x_clk),//ADC同步时钟 .I_ad_da (I_ads422x_da), //ADC数据输入通道A .I_ad_db (I_ads422x_db), //ADC数据输入通道B .O_ad_da (ads422x_da ), //ADC数据输入数据经过延迟模块后输出,通道A .O_ad_db (ads422x_db ), //ADC数据输入数据经过延迟模块后输出,通道B .O_ad_reset(O_ads422x_reset), //ADC控制信号 .O_ad_sen (O_ads422x_sen), //ADC控制信号,设置ADC的工作模式 .O_ad_sclk (O_ads422x_sclk), //ADC控制信号,设置ADC的工作模式 .O_ad_card_en(O_card_power_en)//ADC模块的电源使能,当用到电源使能的时候需要用到 );
wire vtc_rstn,vtc_clk,vtc_vs,vtc_hs,vtc_de,vtc2_de; wire [23:0] wave_rgb; //RGB颜色寄存器 assign vtc_clk = pclkx1;//像素时钟 assign vtc_rstn = locked;//VTC复位信号
//上电延迟复位 reg [7:0] rst_cnt=0; //复位计数器 wire rstn = rst_cnt[7];//用高位复位
always @(posedge I_sysclk_p)begin if (rst_cnt[7]) rst_cnt <= rst_cnt; else rst_cnt <= rst_cnt+1'b1; end
//例化HDMI 输出IP uihdmitx # ( .FAMILY("7FAMILY") //选择芯片所支持的系列"7FAMILY" "UFAMILY" ) uihdmitx_inst ( .I_rstn (locked),//复位 .I_HS (vtc_hs),//hs信号 .I_VS (vtc_vs),//vs信号 .I_VDE (vtc_de),//de信号 .I_RGB (wave_rgb),//RGB数据 .I_PCLKX1 (pclkx1),//像素时钟 .I_PCLKX2_5 (1'b0),//2.5倍像素时钟,只有UFAMILY需要 .I_PCLKX5 (pclkx5),//5倍像素时钟 .O_TMDS_TX_CLK_P(O_HDMI_CLK_P),//HDMI时钟输出P端 .O_TMDS_TX_CLK_N(O_HDMI_CLK_N),//HDMI时钟输出N端 .O_TMDS_TX_P (O_HDMI_TX_P),//HDMI输出数据P端 .O_TMDS_TX_N (O_HDMI_TX_N)//HDMI输出数据N端 );
//此VTC IP 用于产生绘制波形的有效区域,波形绘制区域大小未1024*600 uivtc# ( .H_ActiveSize(1280), //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素 .H_SyncStart(1280+88), //视频时间参数,行同步开始,即多少时钟数后开始产生行同步信号 .H_SyncEnd(1280+88+44), //视频时间参数,行同步结束,即多少时钟数后停止产生行同步信号,之后就是行有效数据部分 .H_FrameSize(1280+88+44+239), //视频时间参数,行视频信号,一行视频信号总计占用的时钟数 .V_ActiveSize(720), //视频时间参数,场视频信号,一帧图像所占用的有效(需要显示的部分)行数量,通常说的视频分辨率即H_ActiveSize*V_ActiveSize .V_SyncStart(720+4), //视频时间参数,场同步开始,即多少行数后开始产生场同步信号 .V_SyncEnd (720+4+5), //视频时间参数,场同步结束,即多少场数后停止产生场同步信号,之后就是场有效数据部分 .V_FrameSize(720+4+5+28), //视频时间参数,场视频信号,一帧视频信号总计占用的行数量 .H2_ActiveSize(1024), //波形绘制区域行像素大小 .V2_ActiveSize(256) //波形绘制区域场像素大小 ) uivtc_inst ( .I_vtc_clk (vtc_clk), //系统时钟 .I_vtc_rstn (vtc_rstn), //系统复位 .I_vtc2_offset_x(128), //X坐标相对屏幕的原始坐标的偏移 .I_vtc2_offset_y(200), //Y坐标相对屏幕的原始坐标的偏移 .O_vtc_vs (vtc_vs), //场同步输出 .O_vtc_hs (vtc_hs), //行同步输出 .O_vtc_de (vtc_de), //视频数据有效 .O_vtc2_de (vtc2_de) //绘制波形显示区域的有效区域 );
ila_0 ila_dbg ( .clk(I_ads422x_clk), // input wire clk .probe0({ads422x_da,ads422x_db}) );
//测试数据产生,通过test_data产生测试数据,可以用于测试波形显示器的基本功能测试 //reg [7:0]test_data =0; //always @(posedge vtc_clk) // if(vtc2_de) // test_data[7:0] = test_data + 1'b1;
//例化波形显示器 IP,默认支持2个通道数据,可以扩展支持更多通道 uiwave uiwave_inst ( //波形1 .I_wave1_clk(I_ads422x_clk),//系统时钟输入 .I_wave1_data(ads422x_da[11:4]+8'h80),//ADC只显示高8bits 数据 .I_wave1_data_de(1'b1),//ADC数据有效信号
//波形2 .I_wave2_clk(I_ads422x_clk),//系统时钟输入 .I_wave2_data(ads422x_db[11:4]+8'h80),//ADC只显示高8bits 数据 .I_wave2_data_de(1'b1),//ADC数据有效信号
.I_vtc_rstn(vtc_rstn),//时序发生复位 .I_vtc_clk (vtc_clk), //像素时钟 .I_vtc_vs (vtc_vs), //场同步输出 .I_vtc_de (vtc2_de),//同步,绘制波形显示区域的有效区域 .O_vtc_rgb (wave_rgb)//同步RGB数据 绘制数据输出
);
endmodule |
6测试结果
6.1硬件接线
(该教程使用的是1.8V的422X子卡,测试前请确保您手上的核心板电压已调整为1.8V。)
请确保下载器和开发板已经正确连接,并且开发板已经上电(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)
6.2测试结果
逻辑分析仪采集的结果
本文来米联客(milianke),作者:米联客(milianke),转载请注明原文链接:https://www.cnblogs.com/milianke/p/17931283.html