Xilinx IDELAYE2应用笔记及仿真实操

文章目录


一、为什么要学习IDELAYE2

  两个器件进行通讯时,至少都需要一个数据线来传输数据,并且还需要满足一定的时序才能保证数据准确的传输。像UART、SPI、IIC等传输频率并不高,布线的传输延时可忽略不计,只要满足相应的协议就可实现数据的传输,当然这种情况只限外部干扰较小的情况,如果要确保传输的准确性,还需要进行校验。但在高速传输时,在硬件上通过差分传输来降低外界的干扰信号,但数据线的长短会影响传输的时长。如通过clk和data两对差分线进行传输,由于clk的布线与dara的布线存在长短上的差异,主机传输到从机后clk和data的延时各不相同。如果我们希望在时钟上升沿上采集数据,但由于线的延时,可能在时钟上升沿时数据处于变化状态,这将会导致采集的数据错误。通过IDELAYE2原语可将某根信号线进行延时操作,以达到在时钟上升沿数据处于稳定的操作。

  本文章是作者学习LVDS时的学习笔记,主要参考UG471和PG070。

二、IDELAYE2原语

  上图为IDELAYE2例化框图,首先对IDELAYE2做个系统的介绍。

  IDELAYE2是Xilinx内部的输入信号延时资源,它主要是把输入信号延时一段时间。IDELAYE2可以一共有四个工作模式:固定延迟模式(FIXED), 可变延迟模式(VARIABLE), 可加载可变延迟模式(VAR_LOAD或VAR_LOAD_PIPE),VAR_LOAD与VAR_LOAD_PIPE模式相识,只是加载的位置不同,下文会进行阐述。

1.IDELAYE2端口说明

2.IDELAYE2属性说明

3.IDELAYE2的延时计算

  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。

4.IDELAYE2模式

1.固定延迟模式(IDELAY_TPYE=FIXED)

  在该模式下数据延迟由属性IDELAY_VALUE设置,且延迟固定,不可更改。在该模式下,IDELAYCTRL原语必须例化。

2.可变延迟模式(IDELAY_TPYE=VARIABLE)

  在该模式下,延迟值可以在配置后通过CE和INC端口进行动态配置。同样,在该模式下,IDELAYCTRL原语也必须例化。该模式下的逻辑控制对应关系如下表所示。

3.可加载可变延迟模式(IDELAY_TYPE=VAR_LOAD)

  该模式下功能与VARIABLE模式下类似,只不过可以通过CNTVALUEIN加载延迟节拍数。多了一种延迟加载方法。当LD端口有效时可以加载新的延迟CNTVALUE值到控制模块。该模式下逻辑功能关系如下表所示。

5.IDELAYE2时序

1.可变延迟模式(IDELAY_TPYE=VARIABLE)

  下图为可变模式下的延迟时序图。

  参考前文可变延迟模式下的逻辑表,可见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;

2.可加载可变延迟模式(IDELAY_TYPE=VAR_LOAD)

  参考前文可加载可变延迟模式下的逻辑表,可见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原语

  上图为IDELAYCTRL例化框图。 如果IDELAYE2或ODELAYE2原语被实例化,那么IDELAYCTRL模块也必须被实例化。IDELAYCTRL模块在其区域内连续校准单个延迟点(iddelay /ODELAY),以减少过程、电压和温度变化的影响。IDELAYCTRL模块使用用户提供的REFCLK校准IDELAY和ODELAY。

1.IDELAYCTRL端口说明

2.IDELAYCTRL时序

  在IDELAYCTRL原语复位后要经过TIDELAYCTRLCO_RDY时间后RDY才被拉高,但若参考时钟在多个时钟周期内保持了不变,RDY就会拉低,此时IDELAYCTRL需要重新复位。

四、IDELAYE2工程代码

1.工程代码

`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

2.测试代码

`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修改为对应的模式。

五、IDELAYE2仿真

1.FIXED模式

  当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。

2.VARIABLE模式

延时大小为(600 + 78*13)ps = 3018ps。

可见延时的大小按照上述执行。

3.VAR_LOAD模式

延时大小为(600 + 78*15)ps = 1770ps。

可见延时的大小按照上述执行。

六、总结

  本文针对IDELAYE2原语进行详解,阐明了延时的最小分辨率与参考时钟有关,分辨率为delay_resolution = 1/(322f)*1000000(ps)。通过编写测试代码,对IDELAYE2的FIXED模式、VARIABLE模式及VAR_LOAD模式进行了仿真,结果与UG471一致。

七、附录

工程文件

https://download.csdn.net/download/weixin_45372778/66985301

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值