当前位置:   article > 正文

Xilinx IDELAYE2应用笔记及仿真实操

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150

注:在进行仿真时需要将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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/614424
推荐阅读
相关标签
  

闽ICP备14008679号