赞
踩
两个器件进行通讯时,至少都需要一个数据线来传输数据,并且还需要满足一定的时序才能保证数据准确的传输。像UART、SPI、IIC等传输频率并不高,布线的传输延时可忽略不计,只要满足相应的协议就可实现数据的传输,当然这种情况只限外部干扰较小的情况,如果要确保传输的准确性,还需要进行校验。但在高速传输时,在硬件上通过差分传输来降低外界的干扰信号,但数据线的长短会影响传输的时长。如通过clk和data两对差分线进行传输,由于clk的布线与dara的布线存在长短上的差异,主机传输到从机后clk和data的延时各不相同。如果我们希望在时钟上升沿上采集数据,但由于线的延时,可能在时钟上升沿时数据处于变化状态,这将会导致采集的数据错误。通过IDELAYE2原语可将某根信号线进行延时操作,以达到在时钟上升沿数据处于稳定的操作。
本文章是作者学习LVDS时的学习笔记,主要参考UG471和PG070。
上图为IDELAYE2例化框图,首先对IDELAYE2做个系统的介绍。
IDELAYE2是Xilinx内部的输入信号延时资源,它主要是把输入信号延时一段时间。IDELAYE2可以一共有四个工作模式:固定延迟模式(FIXED), 可变延迟模式(VARIABLE), 可加载可变延迟模式(VAR_LOAD或VAR_LOAD_PIPE),VAR_LOAD与VAR_LOAD_PIPE模式相识,只是加载的位置不同,下文会进行阐述。
IDELAY2是一个可编程的31阶延迟原语,通过改变tap的值可以改变数据线的延时大小,其延时的分辨率与参考时钟频率f有关,延时的分辨率delay_resolution计算公式如下:
delay_resolution = 1/(32 * 2 * f)*1000000(ps)
其中f单位为Mhz。
当f=200Mhz时,delay_resolution=78ps(注:计算出来为78.125ps,但会取整,为78ps);
同样,当f=300Mhz时,delay_resolution=52ps。
延时的具体大小计算如下:
1.当tap=0时,我们要弄清一个误区,tap=0时并不是延时就是0,此时delay_time=600ps;
2.当tap!=0时,delay_time=600ps + tap * delay_resolution。
在该模式下数据延迟由属性IDELAY_VALUE设置,且延迟固定,不可更改。在该模式下,IDELAYCTRL原语必须例化。
在该模式下,延迟值可以在配置后通过CE和INC端口进行动态配置。同样,在该模式下,IDELAYCTRL原语也必须例化。该模式下的逻辑控制对应关系如下表所示。
该模式下功能与VARIABLE模式下类似,只不过可以通过CNTVALUEIN加载延迟节拍数。多了一种延迟加载方法。当LD端口有效时可以加载新的延迟CNTVALUE值到控制模块。该模式下逻辑功能关系如下表所示。
下图为可变模式下的延迟时序图。
参考前文可变延迟模式下的逻辑表,可见1时刻C=1,LD=1,CE=0,INC=0,则会加载IDELAY_VALUE的值到tap上,即此时tap0=IDELAY_VALUE;在时刻2时,C=1,LD=0,CE=1,INC=1,tap的值会自动累加1,即tap1=IDELAY_VALUE + 1;在时刻3时,C=1,LD=0,CE=0,INC=0,tap的值不变,即tap1=IDELAY_VALUE + 1;
参考前文可加载可变延迟模式下的逻辑表,可见1时刻C=1,LD=1,INC=0,CE=0,CNTVALUEIN=5’b00010,则会加载CNTVALUEIN的值到tap上,即tap=5‘b00010;在2时刻C=1,LD=0,INC=1,CE=1,CNTVALUEIN=5’b01010,则此时tap的值会自动加1,即tap=5‘b00010 + 1’b1 = 5‘b00011;在3时刻,C=1,LD=1,INC=0,CE=0,CNTVALUEIN=5’b01010,则会加载CNTVALUEIN的值到tap上,即tap=5‘b01010;
上图为IDELAYCTRL例化框图。 如果IDELAYE2或ODELAYE2原语被实例化,那么IDELAYCTRL模块也必须被实例化。IDELAYCTRL模块在其区域内连续校准单个延迟点(iddelay /ODELAY),以减少过程、电压和温度变化的影响。IDELAYCTRL模块使用用户提供的REFCLK校准IDELAY和ODELAY。
在IDELAYCTRL原语复位后要经过TIDELAYCTRLCO_RDY时间后RDY才被拉高,但若参考时钟在多个时钟周期内保持了不变,RDY就会拉低,此时IDELAYCTRL需要重新复位。
`timescale 1ns /1ps module idelay_test( input clk_in_50, input reset, input[4:0] in_delay_tap_in_int, input in_delay_ce, input data_in_from_pins_int, input in_delay_inc_dec, input LD, output delay_locked, output[4:0] in_delay_tap_out_int, output data_in_from_pins_delay ); wire ref_clock_bufg; wire ref_clock; wire io_reset; wire clk_200 ; wire clk_100 ; wire clk_50 ; wire clk_25 ; wire locked ; assign ref_clock = clk_200; assign io_reset = locked ? reset:1'b1; assign clk_div_in = clk_50; clk_wiz_0 clk_wiz_0_inst( .clk_200m (clk_200 ), .clk_100m (clk_100 ), .clk_50m (clk_50 ), .clk_25m (clk_25 ), .reset (reset ), .locked (locked), .clk_in1 (clk_in_50)); // (* IODELAY_GROUP = <iodelay_group_test> *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYE2 #(.CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE).DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN).HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE").IDELAY_TYPE("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE.IDELAY_VALUE(0), // 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(in_delay_tap_out_int), // 5-bit output: Counter value output.DATAOUT(data_in_from_pins_delay),// 1-bit output: Delayed data output.C(clk_div_in), // 1-bit input: Clock input.CE(in_delay_ce), // 1-bit input: Active high enable increment/decrement input.CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input.CNTVALUEIN(in_delay_tap_in_int), // 5-bit input: Counter value input.DATAIN(1'b0), // 1-bit input: Internal delay data input.IDATAIN(data_in_from_pins_int), // 1-bit input: Data input from the I/O.INC(in_delay_inc_dec), // 1-bit input: Increment / Decrement tap delay input.LD(LD), // 1-bit input: Load IDELAY_VALUE input.LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input.REGRST(io_reset) // 1-bit input: Active-high reset tap-delay input); // (* IODELAY_GROUP = <iodelay_group_test> *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYCTRL IDELAYCTRL_inst(.RDY(delay_locked), // 1-bit output: Ready output.REFCLK(ref_clock_bufg), // 1-bit input: Reference clock input.RST(io_reset) // 1-bit input: Active high reset input); BUFG ref_clk_bufg(.I(ref_clock),.O(ref_clock_bufg)); endmodule 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
`timescale 1ns /1ps module idelay_test_tb(); reg clk_in_50 ; reg reset ; reg LD ; reg in_delay_ce ; reg in_delay_inc_dec ; wire delay_locked ; reg[4:0] in_delay_tap_in_int ; wire[4:0] in_delay_tap_out_int ; reg data_in_from_pins_int ; wire data_in_from_pins_delay ; `define clk_period 20 `define clk_div_in_period 20 idelay_test idelay_test_utt( .clk_in_50 (clk_in_50 ), .reset(reset ), .in_delay_tap_in_int(in_delay_tap_in_int ), .in_delay_ce(in_delay_ce ), .data_in_from_pins_int(data_in_from_pins_int ), .in_delay_inc_dec(in_delay_inc_dec ), .LD(LD ), .delay_locked(delay_locked ), .in_delay_tap_out_int(in_delay_tap_out_int ), .data_in_from_pins_delay(data_in_from_pins_delay )); initial begin clk_in_50 =0; end always #(`clk_period/2) clk_in_50=~clk_in_50; initial begin // FIXED_task; // VARIABLE_task; VAR_LOAD_task; $stop; end task init; begin reset =1; in_delay_tap_in_int =0; in_delay_ce =0; data_in_from_pins_int =0; in_delay_inc_dec =0; LD =0; #(`clk_div_in_period*10+1); reset =0; @(posedge idelay_test_utt.locked); #(`clk_div_in_period*5); end endtask task FIXED_task; begin init; data_in_from_pins_int =1; #(`clk_div_in_period*10); end endtask task VARIABLE_task; begin init; repeat(3)begin /*******tap自加1********/ in_delay_ce =1; in_delay_inc_dec =1; #(`clk_div_in_period*1); in_delay_ce =0; in_delay_inc_dec =0; data_in_from_pins_int =~data_in_from_pins_int; /*********END************/ #(`clk_div_in_period*1000); end /**加载CNTVALUEIN到tap中*/ LD =1; #(`clk_div_in_period*1); LD =0; data_in_from_pins_int =~data_in_from_pins_int; #(`clk_div_in_period*1000); /*********END************/ repeat(3)begin /*******tap自减1********/ in_delay_ce =1; in_delay_inc_dec =0; #(`clk_div_in_period*1); in_delay_ce =0; in_delay_inc_dec =0; data_in_from_pins_int =~data_in_from_pins_int; /*********END************/ #(`clk_div_in_period*1000); end /**加载CNTVALUEIN到tap中*/ LD =1; #(`clk_div_in_period*1); LD =0; data_in_from_pins_int =~data_in_from_pins_int; #(`clk_div_in_period*1000); /*********END************/ end endtask task VAR_LOAD_task; begin init; /*******CNTVALUEIN task********/ in_delay_tap_in_int =10; #(`clk_div_in_period*5); LD =1; #(`clk_div_in_period*1); LD =0; data_in_from_pins_int =~data_in_from_pins_int; #(`clk_div_in_period*1000); /*********END************/ repeat(3)begin /*******tap自加1********/ in_delay_ce =1; in_delay_inc_dec =1; #(`clk_div_in_period*1); in_delay_ce =0; in_delay_inc_dec =0; data_in_from_pins_int =~data_in_from_pins_int; /*********END************/ #(`clk_div_in_period*1000); end /*******CNTVALUEIN task********/ in_delay_tap_in_int =15; #(`clk_div_in_period*5); LD =1; #(`clk_div_in_period*1); LD =0; data_in_from_pins_int =~data_in_from_pins_int; #(`clk_div_in_period*1000); /*********END************/ end endtask endmodule 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
注:在进行仿真时需要将IDELAY_TYPE修改为对应的模式。
当IDELAY_TYPE = FIXED为FIXED模式,线的延时时间由IDELAY_VALUE来确定。
首先当IDELAY_VALUE = 0时,仿真结果如下:
可见,线延时了600ps。
当IDELAY_VALUE = 1时,仿真结果如下:
可见,线延时了(600 + 78)ps = 678ps。
当IDELAY_VALUE = 31时,仿真结果如下:
可见,线延时了(600 + 78*31)ps = 3018ps。
延时大小为(600 + 78*13)ps = 3018ps。
可见延时的大小按照上述执行。
延时大小为(600 + 78*15)ps = 1770ps。
可见延时的大小按照上述执行。
本文针对IDELAYE2原语进行详解,阐明了延时的最小分辨率与参考时钟有关,分辨率为delay_resolution = 1/(322f)*1000000(ps)。通过编写测试代码,对IDELAYE2的FIXED模式、VARIABLE模式及VAR_LOAD模式进行了仿真,结果与UG471一致。
工程文件
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。