米联客FEP-DAQ004-12-250M-2模数转换模块使用手册
1产品概述FEP-DAQ004-12-250M-2 数据采集模块采用一颗 TI 的 ADS4229低功耗高性能模数转换芯片,实现了 2 通道250MSPS 模数转换,并且支持 2 路数字 IO 输入/输出触发功能。模块采用自定义 FEP 扩展接口,具有成本低, 实用性强的特性,可以适配"米联客"所有具备 FEP 扩展接口的板卡。FEP-DAQ004-12-250M-2采用2个ETC1-1-13组成巴伦电路 ,ETC1-1-13是一款采用低成本表面贴装封装的 1:1 RF 传输线变压器。通过设置不同的通信模式, ADS4229具有LVDS DDR 接口模式和 LVCMOS SDR 接口两种模式。2硬件参数概述
FEP-DAQ004-12-250M-2
ADC芯片AD4229
采样精度12bit
-3db带宽320M(前置运放带宽决定)
IO电平1.8V
采样频率ADS4229 -250M带宽5M~125M
模拟通道2个
触发IO2个
输入电平2VPP
数据格式二进制补码(~2048~+2047)
信噪比170M(SNR)71.4dBFS
无杂散动态范围170M(SFDR)88dBc
功耗165M332mW
占用IO数量40个GPIO
3引脚定义3.1 SMA引脚定义
引脚号引脚名称描述
PADAI模拟输入通道1
PBDBI模拟输入通道2
TATriA双向触发输入/输出1
TBTriB双向触发输入/输出2
3.2 ADS422X芯片功能引脚定义3.2.1 LVDS下接口定义3.2.2 LVCMOS下接口定义
LVDS和CMOS模式的数据输出时序LVDS的时序要求CMOS模式的时序要求4 数据模式设置设置SEN 脚的工作电平,来设置ADS4225/ADS4229的工作模式
SEN 脚电平模式
0V二进制补码和并行CMOS 输出
0.375AVDD偏移二进制和并行CMOS 输出
0.625AVDD偏移二进制和DDR LVDS 输出
AVDD二进制补码和DDR LVDS 输出
5 ETC1-1-13变压器参数6 原理图6.1 4229输入设计
6.2 数字IO输入输出6.3 FEP模块IO电平保护电路设计FEP的接口电压可能不一致,可能导致FPGA IO或者FEP子卡的芯片IO损坏,因此设计如下电路,当工作于1.8V模式下,TPS79618可以正常上电,否则无法上电。6.4 FEP功能定义根据FEP功能定义,匹配开发板的FEP扩展接口原理图配置FPGA的IO约束6.6 FPGA PIN脚约束米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹01_rtl:放用户编写的rtl代码02_sim:仿真文件或者工程03_ip:放使用到的ip文件04_pin:放fpga的pin脚约束文件或者时序约束文件05_boot:放编译好的bit或者bin文件(一般为空)06_doc:放本一些相关文档(一般为空)7 系统框图本方案种,把前面测试程序中的数据改为从ADC采集的数据8 波形绘制关于HDMI输出IP的部分这里不再介绍,VTC时序设计部分这里也不详细介绍。如果读者这些基础知识不清楚的,可以参考米联客入门级教学课程的教学资料。8.1 ADS422X采集驱动ADS422X数据采集通过IDELAY模块调整数据相对时钟的延迟,用来设置最佳采样时刻。
timescale 1 ns / 1 ns
module uiads422X_parallel#(parameterFAMILY = "7SERIES",parameterintegerDATA_WIDTH = 12,parameterintegerDELAY_SETA = 12,parameterintegerDELAY_SETB = 12)(input I_refclk,input I_reset,
input I_ad_clk,input I_ad_da,input I_ad_db,output O_ad_da,output O_ad_db,output O_ad_reset,output O_ad_sen,output O_ad_sclk,output O_ad_card_en);
wire da_buf,db_buf,da_buf_delay,db_buf_delay;wire idelayctrl_reset_sync;reg idelayctrl_reset;reg idelay_reset_cnt;reg cnt = 0;
assign O_ad_card_en = cnt;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) 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 endend
genvar i;generatefor (i = 0 ; i < DATA_WIDTH ; i = i+1) begin : DAQ_DATAIBUF #(.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), // Buffer output.I(I_ad_da) // 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), // Buffer output.I(I_ad_db) // Buffer input (connect directly to top-level port));
endendgenerate
generateif(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), .DATAOUT (da_buf_delay), .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), .DATAOUT (db_buf_delay), .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) ); endendelse 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), .DATAOUT (da_buf_delay), .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), .DATAOUT (db_buf_delay), .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) ); endendendgenerate
assign O_ad_da = da_buf_delay;assign O_ad_db = db_buf_delay;
endmodule
8.2 顶层模块调用程序以下代码中,需要注意,通过DELAY_SETA和DELAY_SETB设置最佳的数据延迟。对于有符号数据,通过设置I_wave1_data(ads422x_da+8'h80),加上8'h80让波形数据转为无符号,在显示器上显示。对于ADS4225修改PLL输出125M时钟对于ADS4229修改PLL输出250M时钟
/**********************ADS422X 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,inputI_ads422x_da,inputI_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 O_HDMI_TX_P, //HDMI数据输出 P端output 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 IPclk_wiz_1 clk_hdmi_pll_inst(.clk_in1 (I_sysclk_p),.reset (!rst_cnt),.locked(locked),.clk_out1(ref_clk),.clk_out2(pclkx1),//像素时钟.clk_out3(pclkx5),//HDMI输出5倍像素时钟.clk_out4(adc_clk)//输出给ADC);
wireads422x_da;wireads422x_db;
uiads422X_parallel #(.FAMILY ("7SERIES"),.DATA_WIDTH(12 ),//ADC数据位宽.DELAY_SETA(22 ),//通道A的delay延迟.DELAY_SETB(22 ) //通道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 wave_rgb; //RGB颜色寄存器assign vtc_clk= pclkx1;//像素时钟assign vtc_rstn = locked;//VTC复位信号
//上电延迟复位reg rst_cnt=0; //复位计数器wirerstn = rst_cnt;//用高位复位
always @(posedge I_sysclk_p)begin if (rst_cnt) rst_cnt <=rst_cnt; else rst_cnt <= rst_cnt+1'b1;end
//例化HDMI 输出IPuihdmitx #(.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*600uivtc#(.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(adc_clk), // input wire clk.probe0({ads422x_da,ads422x_db}));
//测试数据产生,通过test_data产生测试数据,可以用于测试波形显示器的基本功能测试//reg test_data =0;//always @(posedge vtc_clk)//if(vtc2_de)// test_data = test_data + 1'b1;
//例化波形显示器 IP,默认支持2个通道数据,可以扩展支持更多通道uiwave uiwave_inst(//波形1.I_wave1_clk(I_ads422x_clk),//系统时钟输入.I_wave1_data(ads422x_da+8'h80),//ADC只显示高8bits 数据.I_wave1_data_de(1'b1),//ADC数据有效信号
//波形2.I_wave2_clk(I_ads422x_clk),//系统时钟输入.I_wave2_data(ads422x_db+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
8.3 设置画中画区域8.3.1 显示区域时序显示器上的图像,是从液晶屏的左上角,一个像素点一个像素点绘制,当一行所有绘制完成,进行下一行的绘制。利用肉眼的视觉暂留原理,一般1秒显示25帧以上,我们就能看到视频是动态的。本方案中,我们绘制的波形曲线只需要显示波形的数据点,比如对于1920*1080的显示区域,我们只要绘制1920点波形点,即可。为了方便我们理解,我们定义HS方向是X坐标,VS方向是Y坐标。比如我们这里设计的是显示1024个波形数据点,在绘制每一行图像的时候,比对每一个数据和VS的Y坐标是否相等,如果相等就绘制这个波形点。这样我们就能完成1024个波形点在整个屏幕的显示。8.3.2 画中画的vtc视频时序模块设计我们这里显示的波形数据点是1024,高度是256,因此我们需要实现一个画中画的功能。栅格绘制,以及波形数据点会以画中画的有效区域进行显示。支持画中画的uivtc.v源码
/*************uivtc(video timing controller)视频时序控制器*************--版本号1.1--以下是米联客设计的uivtc(video timing controller)视频时序控制器--1.代码简洁,占用极少逻辑资源,代码结构清晰,逻辑设计严谨--2.使用方便,只需要输入6个参数既可以实现对不同视频分辨率时序的控制--3.该视频时序控制,一个时钟对应一个像素--4.通常我们说的像素,比如1080P代表了1920*1080是指视频的有效显示区域,实际的视频还包含不能显示的区域,比如行同步,场同步时间--5.通常我们说的行视频信号,也称之为视频的水平像素信号;场视频信号,也称之为视频的垂直像素信号;--6.针对波形绘制,增加画中画绘制区域功能*********************************************************************/
`timescale 1ns / 1ns //仿真时间刻度/精度
module uivtc#(parameter H_ActiveSize = 1980, //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素parameter H_FrameSize = 1920+88+44+148, //视频时间参数,行视频信号,一行视频信号总计占用的时钟数parameter H_SyncStart = 1920+88, //视频时间参数,行同步开始,即多少时钟数后开始产生行同步信号parameter H_SyncEnd = 1920+88+44, //视频时间参数,行同步结束,即多少时钟数后停止产生行同步信号,之后就是行有效数据部分
parameter V_ActiveSize = 1080, //视频时间参数,场视频信号,一帧图像所占用的有效(需要显示的部分)行数量,通常说的视频分辨率即H_ActiveSize*V_ActiveSizeparameter V_FrameSize = 1080+4+5+36, //视频时间参数,场视频信号,一帧视频信号总计占用的行数量parameter V_SyncStart = 1080+4, //视频时间参数,场同步开始,即多少行数后开始产生场同步信号parameter V_SyncEnd = 1080+4+5, //视频时间参数,场同步结束,即多少场数后停止产生场同步信号,之后就是场有效数据部分
parameter H2_ActiveSize= 640,parameter V2_ActiveSize= 480)(input I_vtc_rstn,//系统复位input I_vtc_clk, //系统时钟outputreg O_vtc_vs,//场同步输出outputreg O_vtc_hs,//行同步输出outputreg O_vtc_de,//视频数据有效input I_vtc2_offset_x,//相对屏幕原点(左上角)X方向偏移input I_vtc2_offset_y,//相对屏幕原点(左上角)Y方向偏移outputreg O_vtc2_de //绘制有效的显示区域);
reg hcnt = 12'd0; //行像素计数器,寄存器reg vcnt = 12'd0; //场像素计数器,寄存器reg rst_cnt = 3'd0;//复位计数器,寄存器wire rst_sync = rst_cnt; //同步复位
always @(posedge I_vtc_clk or negedge I_vtc_rstn)begin //通过计数器产生同步复位 if(I_vtc_rstn == 1'b0) rst_cnt <= 3'd0; else if(rst_cnt == 1'b0) rst_cnt <= rst_cnt + 1'b1;end
//行像素计数器always @(posedge I_vtc_clk)begin if(rst_sync == 1'b0) //复位 hcnt <= 12'd0; else if(hcnt != (H_FrameSize - 1'b1))//计数范围从0 ~ H_FrameSize-1 hcnt <= hcnt + 1'b1; else hcnt <= 12'd0;end
//场计数器,用于计数已经完成的行视频信号always @(posedge I_vtc_clk)begin if(rst_sync == 1'b0) vcnt <= 12'd0; else if(hcnt == (H_ActiveSize- 1'b1)) begin//是否一行像素结束 vcnt <= (vcnt == (V_FrameSize - 1'b1)) ? 12'd0 : vcnt + 1'b1;//每一行计数,场计数器加1,计数范围0~V_FrameSize - 1 endend
wire hs_valid=hcnt < H_ActiveSize; //行信号有效像素部分wire vs_valid=vcnt < V_ActiveSize; //场信号有效像素部分wire vtc_hs =(hcnt >= H_SyncStart && hcnt < H_SyncEnd);//产生hs,行同步信号wire vtc_vs = (vcnt > V_SyncStart && vcnt <= V_SyncEnd);//产生vs,场同步信号 wire vtc_de =hs_valid && vs_valid;//只有当行像素有效和场像素同时有效,视频数据部分才是有效
//画中画,波形绘制区域wire hs2_valid=(hcnt>=I_vtc2_offset_x)&& (hcnt<(I_vtc2_offset_x+H2_ActiveSize)); //画中画,波形绘制区域HS有效信号wire vs2_valid=(vcnt>=I_vtc2_offset_y)&& (vcnt<(I_vtc2_offset_y+V2_ActiveSize)); //画中画,波形绘制区域VS有效信号wire vtc2_de =hs2_valid && vs2_valid; //画中画,数据有效绘制信号
//完一次寄存打拍输出,有利于改善时序,尤其对于高分辨率,高速的信号,打拍可以改善内部时序,以运行于更高速度always @(posedge I_vtc_clk)begin if(rst_sync == 1'b0)begin O_vtc_vs <= 1'b0; O_vtc_hs <= 1'b0; O_vtc_de <= 1'b0; O_vtc2_de <= 1'b0; end else begin O_vtc_vs <= vtc_vs; //场同步信号打拍输出 O_vtc_hs <= vtc_hs; //行同步信号打拍输出 O_vtc_de <= vtc_de; //视频有效信号打拍输出 O_vtc2_de <= vtc2_de; //画中画,数据有效绘制信号 endend
endmodule
8.3.3 栅格绘制波形绘制uiwave.v
`timescale 1ns / 1nsmodule uiwave(
//波形1input I_wave1_clk, //波形1时钟input I_wave1_data, //波形1数据input I_wave1_data_de,//波形1数据有效
//波形2input I_wave2_clk, //波形2时钟input I_wave2_data, //波形2数据input I_wave2_data_de,//波形2数据有效
//VTC时序输入input I_vtc_rstn, //时序复位输入input I_vtc_clk, //时序时钟输入input I_vtc_vs, //VS-帧同步,信号同步输入input I_vtc_de, //de有效区域,信号同步输入
//同步时序输出,以及像素输出output O_vtc_vs, //帧同步输出output O_vtc_de, //de信号同步后输出output reg O_vtc_rgb //同步输出显示颜色);
reg vtc_vs_r; //vs寄存器reg vtc_de_r; //de寄存器reg vcnt,hcnt;//vcnt计数有多少行,hcnt计数有多少列
reg grid_de; //栅格绘制使能
assign O_vtc_vs = vtc_vs_r; //同步后输出O_vtc_vsassign O_vtc_de = vtc_de_r; //同步后输出O_vtc_de
//寄存,同步always @(posedge I_vtc_clk)begin vtc_vs_r <= {vtc_vs_r,I_vtc_vs}; vtc_de_r <= {vtc_de_r,I_vtc_de};end
//以下hcnt用于计数列,vcnt用于计数行数
//hcnt像素计数器always @(posedge I_vtc_clk)begin if(hcnt == 1023) hcnt <= 12'd0; else if(vtc_de_r && (hcnt != 1023)) //hcnt计数列,共计1024个像素 hcnt <= hcnt + 1'b1;end
//vcnt计数有多少行always @(posedge I_vtc_clk)begin if(vtc_vs_r == 2'b01) vcnt <= 8'd0; else if((vtc_de_r == 2'b10) && (vcnt != 255)) //以de信号用于计数行,共计256行 vcnt <= vcnt + 1'b1;end
//栅格绘制always @(posedge I_vtc_clk)begin if((hcnt==7&&(vcnt==63||vcnt == 0))||((hcnt==63||hcnt==0)&&vcnt==7)||(vcnt == 0 && hcnt==0)) grid_de <= O_vtc_de; else grid_de <= 1'b0;end
//1--绘制波形曲线1,绿色点//2--绘制波形曲线2,黄色点//3--绘制栅格虚线,白色点//4--绘制背景色,黑色always @(posedge I_vtc_clk)begin casex({grid_de,wave2_pixel_en,wave1_pixel_en}) 3'bxx1: O_vtc_rgb <= {8'h00,8'hff,8'h00}; //wave1信号显示像素颜色 3'bx10: O_vtc_rgb <= {8'hff,8'hff,8'h00}; //wave2信号显示像素颜色 3'b100: O_vtc_rgb <= {8'h96,8'h96,8'h96}; //网格显示像素为白色点 default: O_vtc_rgb <= {8'h00,8'h00,8'h00}; //黑色背景 endcaseend
//波形缓存1,以及波形绘制像素点输出使能uiwave_buf uiwave1_buf_inst(.I_wave_clk (I_wave1_clk), //写数据输入时钟,和ADC采集时钟同步.I_wave_data (I_wave1_data), //写数据.I_wave_data_de(I_wave1_data_de), //写数据有效
.I_vtc_clk (I_vtc_clk), //VTC时序发生器时钟输入.I_vtc_rstn (I_vtc_rstn), //VTC时序发生器复位.I_vtc_de_r (vtc_de_r), //VTC时序发生器的de有效区域输入.I_vtc_vs (I_vtc_vs), //VTC时序发生器的VS同步信号输入.I_vtc_vcnt (vcnt), //vtc的数据偏移,主要对有符号数据进行调整.O_pixel_en (wave1_pixel_en)//输出输出使能);
//波形缓存2,以及波形绘制像素点输出使能uiwave_buf uiwave2_buf_inst(.I_wave_clk (I_wave2_clk), //写数据输入时钟,和ADC采集时钟同步.I_wave_data (I_wave2_data), //写数据.I_wave_data_de(I_wave2_data_de), //写数据有效
.I_vtc_clk (I_vtc_clk), //VTC时序发生器时钟输入.I_vtc_rstn (I_vtc_rstn), //VTC时序发生器复位.I_vtc_de_r (vtc_de_r), //VTC时序发生器的de有效区域输入.I_vtc_vs (I_vtc_vs), //VTC时序发生器的VS同步信号输入.I_vtc_vcnt (vcnt), //vtc的数据偏移,主要对有符号数据进行调整.O_pixel_en (wave2_pixel_en) //输出输出使能);
endmodule
8.3.4 波形点缓存uiwave_buf.v通过BRAM缓存ADC数据
/*************uiwave_buf简易波形绘制驱动******************************--版本号1.0--1.代码简洁,占用极少逻辑资源,代码结构清晰,逻辑设计严谨--2.使用方便,只需要输入ADC的值,就能完成波形绘制--3.占用资源少,波形输入8bits ADC值,存储到BLOCK RAM 只需要1048*8bit 大小的BRAM,即可完成1通道的波形存储--4.乒乓绘制,当绘制一个波形的时候,另外个波形存储到另外一段地址空间--5.绘制过程中,每一行数据都读出和Y坐标匹配,如果匹配成功,使能O_pixel_en绘制这个数据点*********************************************************************/
`timescale 1ns / 1ns //仿真时间刻度/精度
module uiwave_buf(input I_wave_clk, //写数据输入时钟,和ADC采集时钟同步input I_wave_data, //写数据input I_wave_data_de,//写数据有效
input I_vtc_clk, //VTC时序发生器时钟输入input I_vtc_rstn, //VTC时序发生器复位input I_vtc_vs, //VTC时序发生器的VS同步信号输入input I_vtc_de_r, //VTC时序发生器的de有效区域输入input I_vtc_vcnt, //vtc的数据偏移,主要对有符号数据进行调整output O_pixel_en //输出输出使能);
//BRAM 简单双口BRAMreg addra = 0;//BRAM 通道A地址 //reg ena = 0;//BRAM 通道A使能reg wea = 0;//BRAM 通道A写使能reg addrb = 0;//BRAM 通道B地址reg enb = 0;//BRAM 通道B读使能reg WR_S,RD_S;//写状态机,读状态机reg buf_flag;//buf_flag用于乒乓地址缓存切换reg addr0_en;//用于设置写第一个数据相对地址0
wire wave_data;//写波形数据到BRAMreg async_vtc_vs =0; //同步信号
always @(posedge I_wave_clk)begin //对异步I_vtc_vs采样 async_vtc_vs <= {async_vtc_vs,I_vtc_vs};end
//绘制波形数据点使能,绘制原理://当匹配到存储的ADC数据和正在扫描的Y坐标值一致就输出,每个X坐标方向绘制1个波形点assign O_pixel_en= I_vtc_de_r&(I_vtc_vcnt == wave_data);
//写BRAM 状态机always @(posedge I_wave_clk or negedge I_vtc_rstn)begin if(I_vtc_rstn == 1'b0)begin //复位重置所有寄存器 addra <= 10'd0; addr0_en <= 1'b1; wea <= 1'b0; buf_flag <= 1'b0; WR_S <= 1'd0; end else begin case(WR_S) //写状态机 0:begin if(I_wave_data_de)begin //有效波形数据点 if(addra == 1023)begin //1024个数据写完 wea <= 1'b0; //停止写 addra <= 0; //相对地址设置0 addr0_en <= 1'b1; WR_S <= 1'd1;//进入状态机1 end else begin //写入1024个数据 wea <= 1'b1; //写使能 addr0_en <= 1'b0; addra <= (addr0_en == 1'b0) ? (addra + 1'b1) : 0;//相对地址递增 end end else begin wea <= 1'b0; end end 1:begin //等待VTC时序同步 if(async_vtc_vs == 2'b10)begin//当数据同步后,准备下一次写 WR_S <= 1'd0; //回到状态0 buf_flag <= ~buf_flag;//乒乓地址切换 end end default:WR_S <= 2'd0; endcase endend
//读BRAM 状态机always @(posedge I_vtc_clk or negedge I_vtc_rstn)begin if(I_vtc_rstn == 1'b0)begin//复位重置所有寄存器 addrb <= 10'd0; RD_S <= 1'd0; end else begin case(RD_S) 0:begin if(I_vtc_de_r)begin //I_vtc_de_r代表了有效绘制区域 if(addrb == 1023)begin //1024个数据读完 addrb <= 0; //相对地址设置0 RD_S<= 1'd1; //进入状态1 end else //没一样都会扫描所有的ADC数据 addrb <= addrb + 1'b1;//相对地址递增 end end 1:begin if(I_vtc_de_r == 0) //等待de变为0 RD_S <= 0; //回到状态0重新扫描
end default:RD_S <= 1'd0; endcase endend
wave_ram buf_inst(.dina(I_wave_data), //写入波形数据.addra({buf_flag,addra}), //写地址,其中addra是相对地址,buf_flag是地址高位,用于读写的乒乓切换.wea(wea), //写使能.clka(I_wave_clk),//写时钟
.doutb(wave_data), //读出的波形数据.addrb({~buf_flag,addrb}), //写地址,其中addrb是相对地址,buf_flag是地址高位,用于读写的乒乓切换.clkb(I_vtc_clk)//读时钟);
endmodule
9.4 测试结果9.4.1 硬件接线以MLK-F6-7015为演示板卡,其他板卡类似设置波形发生器产生测试波形7.4.2 测试结果逻辑分析仪采集的结果
附录1:FEP卡命名规则(MLK-NV2023版本)1 FEP-DAQ模数转换类系列命名模拟数字采集,数模转换模块命名规则FEP:FEP系列DAQ:模数转换系列Num:编号Bit:采样位宽SPS:采样率Channels:支持的采样速率2 FEP-AUD音频类系列命名音频模块命名FEP:FEP系列AUD:音频系列Num:编号Bit:采样位宽SPS:采样率Channels:支持的采样速率3 FEP-COM通信类系列命名FEP:FEP系列COM:通用通信类模块或者IO模块Num:编号Class1:类型,预留Class2:类型,预留4 FEP-LAN通信类系列命名FEP:FEP系列LAN:以太网通信类Num:编号Class1:类型,预留Class2:类型,预留5 FEP-VID通信类系列命名FEP:FEP系列VID:视频类Num:编号Class1:类型,预留Class2:类型,预留6 FEP-CAM摄像头类FEP:FEP系列CAM:摄像头类Num:编号Class1:类型,预留Class2:类型,预留7 FEP-MEM存储类FEP:FEP系列MEM:存储类Num:编号Class1:类型,预留Class2:类型,预留
附录2:常见问题1 联系方式技术交流群网址: https://www.uisrc.com/f-380.html查看最新可以加入的QQ群
技术微信:18951232035技术电话:18951232035
官方微信公众号(新微信公众号):2 售后1、7天无理由退货(人为原因除外)2、质保期限:本司产品自快递签收之日起,提供一年质保服务(主芯片,比如FPGA 或者CPU等除外)。3、维修换货,需提供淘宝订单编号或合同编号,联系销售/技术支持安排退回事宜。售后维修请登录工单系统:https://www.uisrc.com/plugin.php?id=x7ree_service4、以下情形不属于质保范畴。A:由于用户使用不当造成板子的损坏:比如电压过高造成的开发板短路,自行焊接造成的焊盘脱落、铜线起皮 等B:用户日常维护不当造成板子的损坏:比如放置不当导致线路板腐蚀、基板出现裂纹等5、质保范畴外(上方第4条)及质保期限以外的产品,本司提供有偿维修服务。维修仅收取器件材料成本,往返运 费全部由客户承担。6、寄回地址,登录网页获取最新的售后地址:https://www.uisrc.com/t-1982.html3 销售天猫米联客旗舰店:https://milianke.tmall.com京东米联客旗舰店:https://milianke.jd.com/FPGA|SOC生态店:https://milianke.taobao.com
销售电话:18921033576
常州溧阳总部:常州溧阳市中关村吴潭渡路雅创高科制造谷 10-1幢楼4 在线视频https://www.uisrc.com/video.html5 资源下载https://www.uisrc.com/download.html6 软件或其他下载https://www.uisrc.com/f-download.html
页:
[1]