在高速信号采集的过程中,经常会因为电路设计或者其他原因,原本设计好对应的data_clk与data经过线路传输之后在接收端时序上不能很好的对应,这可能会造成采样数据的错位。
如果用了各种物理电路上的办法都没法解决后,可以尝试使用idelay(针对xilinx,altera应该也有相应的原语)。
xilinx每个系列可能idelay的名字会有一些差异,但差异不大,在k7系列下,idelay的原语叫做idelay2。
idelay2原语示例:
(* iodelay_group = rx_frame *) // specifies group name for associated idelays/odelays and idelayctrl idelaye2 #( .cinvctrl_sel(false), // enable dynamic clock inversion (false, true) .delay_src(datain), // delay input (idatain, datain) .high_performance_mode(false), // reduced jitter (true), reduced power (false) .idelay_type(var_load), // fixed, variable, var_load, var_load_pipe .idelay_value(init_value), // input delay tap setting (0-31) .pipe_sel(false), // select pipelined mode, false, true .refclk_frequency(200.0), // idelayctrl clock input frequency in mhz (190.0-210.0, 290.0-310.0). .signal_pattern(data) // data, clock input signal ) idelaye2_inst ( .cntvalueout(cnt_value), // 5-bit output: counter value output .dataout(rx_frame_dly), // 1-bit output: delayed data output .c(sys_clk), // 1-bit input: clock input .ce(1'b0), // 1-bit input: active high enable increment/decrement input .cinvctrl(1'b0), // 1-bit input: dynamic clock inversion input .cntvaluein(tap_value), // 5-bit input: counter value input .datain(rx_frame), // 1-bit input: internal delay data input .idatain(1'b0), // 1-bit input: data input from the i/o .inc(1'b0), // 1-bit input: increment / decrement tap delay input .ld(1'b1), // 1-bit input: load idelay_value input .ldpipeen(1'b0), // 1-bit input: enable pipeline register to load data input .regrst(1'b0) // 1-bit input: active-high reset tap-delay input );针对其中经常用到的变量,功能如下:
delay_src常量,这个常量可以选datain或idatain,区别在于idatain的数据输入要求经过buf产生,常用于buf的输出信号,input端口信号;datain只要求fpga内部逻辑产生的信号就可以。idelay_type,设置idelay2的模式;fixed代表延时值固定,一般用在确定好参数后使用,varible,var_load,var_load_pipe都是动态改变延时值,varible可以自动增大减小,后两个是根据cinvaluein端口动态改变延时值,一般选用var_load。idelay_value,是初始化的值,在fixed模式下,就是固定的延时值refclk_frequency,指的idelay的参考时钟的频率,一般选用200m,这个后面会具体讲。signal_pattern,这个有data和clock两个选项,影响vivado对信号时序分析的路径。端口中,
cntvaluein是设置延时值,用于手动调试;cntvalueout输出当前延时值,便于调试观测;c是数据时钟,但ce不是时钟使能,而是延时值tap自动增加减少使能,所以我选择拉低;cinvctrl,inc,ldpipeein,regrst不怎么用,全拉低;在上面的delay_src选择了哪一个,就在对应的数据端口连接数据,另一个数据端口拉低,比如delay_src设定为datain,选择datain端口输入数据,idatain端口拉低;因为需要手动调节延时值,所以ld拉高,只有ld拉高才能动态载入cntvaluein的延时值前面说到参考时钟,idelay之所以延时,cinvaluein对应的延时值多少就跟这个地方有关系了,参考时钟不是随便设的,这跟另一个原语idelayctrl有关:
(* iodelay_group = rx_frame *) // specifies group name for associated idelays/odelays and idelayctrl idelayctrl idelayctrl_inst ( .rdy(idelay_rdy), // 1-bit output: ready output .refclk(ref_clk), // 1-bit input: reference clock input .rst(rst) // 1-bit input: active high reset input );这个原语端口很少,连接对应200m的参考时钟,复位信号,输出一个ready信号;
看起来这个原语并没有什么有用的输出;但其实它的作用是给idelay2提供了延时的依据;之所以可以精确延时并不是说我们在refclk_frequency填一个200就可以了,而是这个idelayctrl 的作用,通过(* iodelay_group = rx_frame *)将idelayctrl 和idelay2连接起来,rx_frame类似于组名,可以随意改,同一组的组名要一样。
200mhz 对应1个时钟周期5ns,idelay将其分为64tap,每个tap延时值大概是78ps,idelay可调的最大tap为31,也就是延时值控制在0-31tap;
同样,为了减小相同参考时钟下idelay2与idelayctrl 的fpga内部走线延时,必须使用iodelay_group将它们绑定在一起,使用方法参考上面的做法。
注意,idelayctrl 的refclk输入时钟一定要经过bufg输出再接入。
效果:
没加idelay
没有加idelay,并串转换中找不到帧头
加入idelay
加了idelay,找到帧头
总结:
使用方法都在上面,对于多bit信号可以使用generate for 生成块。调试这个的时候遇到过一个问题,c端口没有连接到正常的时钟,连接到一个根本没有定义的信号,vivado做好事不留名的直接帮我拉低到地,导致我在var_load模式下一直无法正常改变延时值,cntvalueout与cinvaluein不正确,最后打开schematic看rtl图才找到问题。
面板市场:各种显示技术展开对决
AGV小车在仓储搬运中快速高效的秘籍(一)
情人节惊喜,怎么少的了小米6的陪伴?2月14日春季发布会降临
农场养殖场远程视频监控系统的架构、工作原理及特点
为什么公司仍然需要专用核心网络
Idelay对时序的补救
倒装焊芯片(Flip-Chip)是什么意思
开关电源产生电磁干扰的原因分析
linux的ip命令是什么
如何实现经济高效地扩展5G毫米波段?
高新兴物联助力车企实现智能网联数智化升级
NVIDIA BlueField DPU加速UCloud裸金属物理云产品
科锐与采埃孚推进电驱动领域合作
电驱动关键技术分析 电驱动系统结构及原理
区块链游戏的切入点在哪里
基于ANSYS电磁兼容仿真平台的仿真EMI设计
我对“家电维修”看法与体会!
OPPO Find X2系列新品发布会:OPPO Watch亮相
多通道振弦传感器无线采集仪参数配置工具SETP简单介绍
伏打电池的利用与电磁学的发展