当前位置:   article > 正文

UltraScale 架构 SelectIO 资源之IODELAY与IOSERDES仿真与使用_iodelay仿真

iodelay仿真

平台:vivado2018.3
具体内容见ug571-ultrascale-selectio


IDELAYE3 


在调试超高速信号的时候,需要使用iodelay+iserdes来调试校准输入信号。例如外部某ADC采样率为5GHZ,外部ADC使用2.5GHZ的时钟去采集输入信号。为了实现采集,adc芯片使用了4个1.25ghz采样率的小ADC来采集。但是由于FPGA的工艺,在FPGA内部无法处理高达1.25ghz的信号。外部信号采用并行数据输入,在双边沿采集信号。输入随路时钟为625mhz的双边沿数据。但是对于一般的工程,内部时钟跑到625mhz对于FPGA的时序要求太高。所以我们将625mhz的时钟通过idelay+iserdes的结构。将625mhz的ddr数据转换为312.5mhz的4路单边沿数据。由于芯片采用的并行数据输入,在pcb布局,fpga引脚这些问题上,导致并行输入信号在进入FPGA内部的时间不一致,导致我们采集的输入数据就会出现亚稳态,可能提前也可能延后。这时候我们就需要使用iodelay来对数据进行校准,保证时钟每次采集的数据都是数据的正中心。以确保数据不会出错。
感兴趣的可以看我的另外一篇关于iodelay的文章。

IDELAY输入延迟分析-CSDN博客

那么625mhz的ddr数据如何转换为312.5mhz的呢?在FPGA中拥有serdes可以将输入的串行数据转换为并行数据。今天我们就来通过仿真简单介绍一下iodelay和iserdes。
关于IODELAY3
可以使用 IDELAYE3 原语延迟除时钟以外的任何输入信号,然后将其直接转发到器件逻辑,或者使用输入/输出互联 (IOI) 内部的单数据速率 (SDR) 时钟或双倍数据速率 (DDR) 时钟将其寄存到简单的触发器、IDDDR 或 ISERDESE3 中。不 应使用 IDELAYE3 来延迟时钟,因为 IDELAY 无法直接布线到全局时钟缓存。如必须延迟时钟,请使用 MMCM 或 PLL 生成时钟,并使用精细相移功能来延迟时钟。
需要注意的是,IDELAY3原语包含512抽头系数。仿真实测每个taps实际为5ps。仿真测试接入IDELAY3产生的固有延迟为160ps。
IDELAY3拥有两种模式。
COUNT模式和TIME模式。
COUNT模式不需要IDELAYCTRL,无校准,只是记数tap的个数(最多512个taps)
TIME模式需要IDELAYCTRL,有校准。
端口介绍

关于ISERDESE3


UltraScale器件中的ISERDESE3是具有特定时控和逻辑功能的串并转换器,便于实现高速源同步应用。
ISERDESE3可在SDR数据捕获中将传入信号按2或4位进行解串,而在DDR数据捕获模式中则可以按4或8位进行解串。当用于SDR数据捕获时,每隔一个数据输出管脚即为有效输出。例如,当使用SDR时钟作为1:4解串器时,数据宽度应设置为8,接收到的数据取自 Q0、Q2、Q4和Q6。
ISERDES还包含一个较浅的八元素FIFO。可用于跨时钟域传输。
ISERDES可以定义串并转换器宽度。为4位和8位。

ISERDES的端口介绍

ISERDES的属性

下面我们在逻辑中做仿真。模拟外部输入的625mhz的DDR数据,通过调节idelay和使用iserdes将输入的串行信号转换位并行数据。

代码仿真

使用idelay,设置idelay时钟位312.5mhz。输入625mhz的串行ddr数据。

  1. // *********************************************************************************/
  2. // Project Name :
  3. // Author : i_huyi
  4. // Email : i_huyi@qq.com
  5. // Creat Time : 2024/4/1 16:22:39
  6. // File Name : .v
  7. // Module Name :
  8. // Called By :
  9. // Abstract :
  10. //
  11. // CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
  12. // All Rights Reserved
  13. //
  14. // *********************************************************************************/
  15. // Modification History:
  16. // 1. initial
  17. // *********************************************************************************/
  18. // *************************
  19. // MODULE DEFINITION
  20. // *************************
  21. `timescale 1 ns / 1 ps
  22. module io_delay3#(
  23. parameter U_DLY = 1
  24. )
  25. (
  26. //serdes data in and Parallel data out
  27. input wire data_in ,
  28. output wire data_delay_out ,
  29. //iodelay
  30. input wire[8:0] delay_data ,//延迟值
  31. input wire delay_valid ,//延迟值有效
  32. //system signal
  33. input wire clk_312_5 ,//312.5
  34. input wire rst
  35. );
  36. //--------------------------------------
  37. // localparam
  38. //--------------------------------------
  39. //--------------------------------------
  40. // register
  41. //--------------------------------------
  42. //--------------------------------------
  43. // wire
  44. //--------------------------------------
  45. //--------------------------------------
  46. // assign
  47. //--------------------------------------
  48. //------------------------------------------------------------
  49. //------------------------------------------------------------
  50. //------------------------------------------------------------
  51. //------------------------------------------------------------
  52. IDELAYCTRL #(
  53. .SIM_DEVICE ("ULTRASCALE" )// Must be set to "ULTRASCALE"
  54. )
  55. IDELAYCTRL_inst (
  56. .RDY (RDY ),// 1-bit output: Ready output
  57. .REFCLK (clk_312_5 ),// 1-bit input: Reference clock input
  58. .RST (rst )// 1-bit input: Active high reset input. Asynchronous assert, synchronous deassert to
  59. // REFCLK.
  60. );
  61. //------------------------------------------------------------
  62. //------------------------------------------------------------
  63. IDELAYE3 #(
  64. .CASCADE ("NONE" ),// Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE)
  65. .DELAY_FORMAT ("TIME" ),// Units of the DELAY_VALUE (COUNT, TIME)
  66. .DELAY_SRC ("IDATAIN" ),// Delay input (DATAIN, IDATAIN)
  67. .DELAY_TYPE ("VAR_LOAD" ),// Set the type of tap delay line (FIXED, VARIABLE, VAR_LOAD)
  68. .DELAY_VALUE (0 ),// Input delay value setting
  69. .IS_CLK_INVERTED (1'b0 ),// Optional inversion for CLK
  70. .IS_RST_INVERTED (1'b0 ),// Optional inversion for RST
  71. .REFCLK_FREQUENCY (312.5 ),// IDELAYCTRL clock input frequency in MHz (200.0-2667.0)
  72. .SIM_DEVICE ("ULTRASCALE" ),// Set the device version (ULTRASCALE, ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1,// ULTRASCALE_PLUS_ES2)
  73. .UPDATE_MODE ("ASYNC" )// Determines when updates to the delay will take effect (ASYNC, MANUAL, SYNC)
  74. )
  75. IDELAYE3_inst (
  76. .CASC_OUT ( ),// 1-bit output: Cascade delay output to ODELAY input cascade
  77. .CNTVALUEOUT ( ),// 9-bit output: Counter value output
  78. .DATAOUT (data_delay_out ),// 1-bit output: Delayed data output
  79. .CASC_IN (1'b0 ),// 1-bit input: Cascade delay input from slave ODELAY CASCADE_OUT
  80. .CASC_RETURN (1'b0 ),// 1-bit input: Cascade delay returning from slave ODELAY DATAOUT
  81. .CE (1'b0 ),// 1-bit input: Active high enable increment/decrement input
  82. .CLK (clk_312_5 ),// 1-bit input: Clock input
  83. .CNTVALUEIN (delay_data ),// 9-bit input: Counter value input
  84. .DATAIN (1'b0 ),// 1-bit input: Data input from the logic
  85. .EN_VTC (~delay_valid ),// 1-bit input: Keep delay constant over VT
  86. .IDATAIN (data_in ),// 1-bit input: Data input from the IOBUF
  87. .INC (1'b1 ),// 1-bit input: Increment / Decrement tap delay input
  88. .LOAD (delay_valid ),// 1-bit input: Load DELAY_VALUE input
  89. .RST (rst )// 1-bit input: Asynchronous Reset to the DELAY_VALUE
  90. );
  91. //------------------------------------------------------------
  92. //------------------------------------------------------------
  93. //------------------------------------------------------------
  94. //------------------------------------------------------------
  95. endmodule

使用iserdes,ddr数据输入。输出比例为1:4。

  1. // *********************************************************************************/
  2. // Project Name :
  3. // Author : i_huyi
  4. // Email : i_huyi@qq.com
  5. // Creat Time : 2024/4/1 16:32:49
  6. // File Name : .v
  7. // Module Name :
  8. // Called By :
  9. // Abstract :
  10. //
  11. // CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
  12. // All Rights Reserved
  13. //
  14. // *********************************************************************************/
  15. // Modification History:
  16. // 1. initial
  17. // *********************************************************************************/
  18. // *************************
  19. // MODULE DEFINITION
  20. // *************************
  21. `timescale 1 ns / 1 ps
  22. module iserdes3#(
  23. parameter U_DLY = 1
  24. )
  25. (
  26. //serdes data in and Parallel data out
  27. input wire data_in ,
  28. output wire[3:0] data_out ,
  29. //system signal
  30. input wire clk_312_5 ,//625
  31. input wire clk_625_p ,//625mhz
  32. input wire clk_625_n ,
  33. input wire rst
  34. );
  35. //--------------------------------------
  36. // localparam
  37. //--------------------------------------
  38. //--------------------------------------
  39. // register
  40. //--------------------------------------
  41. //--------------------------------------
  42. // wire
  43. //--------------------------------------
  44. //--------------------------------------
  45. // assign
  46. //--------------------------------------
  47. //------------------------------------------------------------
  48. //------------------------------------------------------------
  49. ISERDESE3 #(
  50. .DATA_WIDTH (4 ),// Parallel data width (4,8)
  51. .FIFO_ENABLE ("FALSE" ),// Enables the use of the FIFO
  52. .FIFO_SYNC_MODE ("FALSE" ),// Always set to FALSE. TRUE is reserved for later use.
  53. .IS_CLK_B_INVERTED (1'b0 ),// Optional inversion for CLK_B
  54. .IS_CLK_INVERTED (1'b0 ),// Optional inversion for CLK
  55. .IS_RST_INVERTED (1'b0 ),// Optional inversion for RST
  56. .SIM_DEVICE ("ULTRASCALE" )// Set the device version (ULTRASCALE, ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1,ULTRASCALE_PLUS_ES2)
  57. )
  58. ISERDESE3_inst (
  59. .FIFO_EMPTY ( ),// 1-bit output: FIFO empty flag
  60. .INTERNAL_DIVCLK ( ),// 1-bit output: Internally divided down clock used when FIFO is, disabled (do not connect)
  61. .Q (data_out ),// 8-bit registered output
  62. .CLK (clk_625_p ),// 1-bit input: High-speed clock
  63. .CLKDIV (clk_312_5 ),// 1-bit input: Divided Clock
  64. .CLK_B (clk_625_n ),// 1-bit input: Inversion of High-speed clock CLK
  65. .D (data_in ),// 1-bit input: Serial Data Input
  66. .FIFO_RD_CLK ( ),// 1-bit input: FIFO read clock
  67. .FIFO_RD_EN ( ),// 1-bit input: Enables reading the FIFO when asserted
  68. .RST (rst )// 1-bit input: Asynchronous Reset
  69. );
  70. //------------------------------------------------------------
  71. //------------------------------------------------------------
  72. //------------------------------------------------------------
  73. //------------------------------------------------------------
  74. endmodule

顶层例化两个模块。

  1. // *********************************************************************************/
  2. // Project Name :
  3. // Author : i_huyi
  4. // Email : i_huyi@qq.com
  5. // Creat Time : 2024/4/1 15:53:53
  6. // File Name : .v
  7. // Module Name :
  8. // Called By :
  9. // Abstract :
  10. // iserdes + iodelay
  11. //
  12. // CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
  13. // All Rights Reserved
  14. //
  15. // *********************************************************************************/
  16. // Modification History:
  17. // 1. initial
  18. // *********************************************************************************/
  19. // *************************
  20. // MODULE DEFINITION
  21. // *************************
  22. `timescale 1 ns / 1 ps
  23. module io_delay_iserdes#(
  24. parameter U_DLY = 1
  25. )
  26. (
  27. //serdes data in and Parallel data out
  28. input wire data_in ,
  29. output wire[3:0] data_out ,
  30. //iodelay
  31. input wire[8:0] delay_data ,//延迟值
  32. input wire delay_valid ,//延迟值有效
  33. //system signal
  34. input wire clk_312_5 ,//625
  35. input wire clk_625_p ,//625mhz
  36. input wire clk_625_n ,
  37. input wire rst
  38. );
  39. //--------------------------------------
  40. // localparam
  41. //--------------------------------------
  42. //--------------------------------------
  43. // register
  44. //--------------------------------------
  45. //--------------------------------------
  46. // wire
  47. //--------------------------------------
  48. //--------------------------------------
  49. // assign
  50. //--------------------------------------
  51. io_delay3 u_io_delay3 (
  52. //serdes data in
  53. .data_in (data_in ),
  54. .data_delay_out (data_delay_out ),
  55. //iodelay
  56. .delay_data (delay_data ),
  57. .delay_valid (delay_valid ),
  58. //system signal
  59. .clk_312_5 (clk_312_5 ),
  60. .rst (rst ));
  61. //------------------------------------------------------------
  62. //------------------------------------------------------------
  63. iserdes3 U_iserdes3(
  64. //serdes data in and Parallel data out
  65. .data_in (data_delay_out ),
  66. .data_out (data_out ),
  67. //system signal
  68. .clk_312_5 (clk_312_5 ),
  69. .clk_625_p (clk_625_p ),
  70. .clk_625_n (clk_625_n ),
  71. .rst (rst ));
  72. //------------------------------------------------------------
  73. //------------------------------------------------------------
  74. //
  75. endmodule

添加仿真文件

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2024/04/01 16:43:25
  7. // Design Name:
  8. // Module Name: vtf_io_delay_iserdes
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module vtf_io_delay_iserdes;
  22. //
  23. wire [9:0] adc_di_p ;
  24. //iodelay
  25. reg [8:0] delay_data ;//延迟值
  26. reg delay_valid ;//延迟值有效
  27. //system signal
  28. reg clk_312_5 ;//625
  29. reg clk_625_p ;//625mhz
  30. reg clk_625_n ;
  31. reg rst ;
  32. reg data_clk ;
  33. wire [3:0] data_out[9:0] ;
  34. wire [9:0] data_p0 ;
  35. wire [9:0] data_p1 ;
  36. wire [9:0] data_p2 ;
  37. wire [9:0] data_p3 ;
  38. //-----------------------------------------------------------
  39. //-----------------------------------------------------------
  40. assign data_p0 = { data_out[9][0],
  41. data_out[8][0],
  42. data_out[7][0],
  43. data_out[6][0],
  44. data_out[5][0],
  45. data_out[4][0],
  46. data_out[3][0],
  47. data_out[2][0],
  48. data_out[1][0],
  49. data_out[0][0]
  50. };
  51. assign data_p1 = { data_out[9][1],
  52. data_out[8][1],
  53. data_out[7][1],
  54. data_out[6][1],
  55. data_out[5][1],
  56. data_out[4][1],
  57. data_out[3][1],
  58. data_out[2][1],
  59. data_out[1][1],
  60. data_out[0][1]
  61. };
  62. assign data_p2 = { data_out[9][2],
  63. data_out[8][2],
  64. data_out[7][2],
  65. data_out[6][2],
  66. data_out[5][2],
  67. data_out[4][2],
  68. data_out[3][2],
  69. data_out[2][2],
  70. data_out[1][2],
  71. data_out[0][2]
  72. };
  73. assign data_p3 = { data_out[9][3],
  74. data_out[8][3],
  75. data_out[7][3],
  76. data_out[6][3],
  77. data_out[5][3],
  78. data_out[4][3],
  79. data_out[3][3],
  80. data_out[2][3],
  81. data_out[1][3],
  82. data_out[0][3]
  83. };
  84. //-----------------------------------------------------------
  85. //-----------------------------------------------------------
  86. parameter WIDTH = 10;
  87. //-----------------------------------------------------------
  88. //-----------------------------------------------------------
  89. genvar i;
  90. generate
  91. for (i = 0; i<=(WIDTH-1); i = i +1) begin : adc_ch_di_p
  92. io_delay_iserdes u_io_delay_iserdes(
  93. //serdes data in and Parallel data out
  94. .data_in (adc_di_p[i] ),
  95. .data_out (data_out[i] ),
  96. //iodelay
  97. .delay_data (delay_data ),
  98. .delay_valid (delay_valid ),
  99. //system signal
  100. .clk_312_5 (clk_312_5 ),
  101. .clk_625_p (clk_625_p ),
  102. .clk_625_n (clk_625_n ),
  103. .rst (rst ));
  104. end
  105. endgenerate
  106. //-----------------------------------------------------------
  107. //-----------------------------------------------------------
  108. initial
  109. begin
  110. delay_data =0;
  111. delay_valid =0;
  112. data_clk =0;
  113. clk_312_5 =0;
  114. clk_625_p =0;
  115. clk_625_n =1;
  116. rst =1;
  117. #100;
  118. rst =0;
  119. #100;
  120. delay_data =9'd0;
  121. delay_valid =1'b1;
  122. #10;
  123. delay_data =9'd0;
  124. delay_valid =1'b0;
  125. #100;
  126. delay_data =9'd2;
  127. delay_valid =1'b1;
  128. #10;
  129. delay_data =9'd0;
  130. delay_valid =1'b0;
  131. #100;
  132. delay_data =9'd3;
  133. delay_valid =1'b1;
  134. #10;
  135. delay_data =9'd0;
  136. delay_valid =1'b0;
  137. #100;
  138. delay_data =9'd4;
  139. delay_valid =1'b1;
  140. #10;
  141. delay_data =9'd0;
  142. delay_valid =1'b0;
  143. #100;
  144. delay_data =9'd200;
  145. delay_valid =1'b1;
  146. #10;
  147. delay_data =9'd0;
  148. delay_valid =1'b0;
  149. end
  150. reg [9:0] data_cnt ;
  151. always@(posedge data_clk or posedge rst)
  152. begin
  153. if(rst == 1'b1)begin
  154. data_cnt <= 10'd0;
  155. end
  156. else begin
  157. data_cnt <= data_cnt + 10'h1;
  158. end
  159. end
  160. //-----------------------------------------------------------
  161. //-----------------------------------------------------------
  162. //产生数据
  163. assign adc_di_p[0] = data_cnt[0];
  164. assign adc_di_p[1] = data_cnt[1];
  165. assign adc_di_p[2] = data_cnt[2];
  166. assign adc_di_p[3] = data_cnt[3];
  167. assign adc_di_p[4] = data_cnt[4];
  168. assign adc_di_p[5] = data_cnt[5];
  169. assign adc_di_p[6] = data_cnt[6];
  170. assign adc_di_p[7] = data_cnt[7];
  171. assign adc_di_p[8] = data_cnt[8];
  172. assign adc_di_p[9] = data_cnt[9];
  173. always #1.6 clk_312_5 = ~clk_312_5;
  174. always #0.8 clk_625_p = ~clk_625_p;
  175. always #0.8 clk_625_n = ~clk_625_n;
  176. always #0.4 data_clk = ~data_clk;
  177. endmodule

在仿真文件中,我们模式外部ADC采集输入的并行数据。使用1.25ghz时钟将数据产生。产生的数据将通过并行的十根数据线发送到idelay+iserdes模块分别进行解串。解串后的数据为单bit的312.5mhz的四组并行数据。在仿真顶层我们需要将该数据装换为10bit的312.5mhz数据。所以这里例化十个解串模块。将其解串后的数据进行拼合。就将原始的10bit的1.25ghz的数据转换为了四组312.5mhz的10bit数据流。接下来具体看一下效果。

idelay调节。调节tap为0。可以看到调节后的数据较输入原始数据延迟了160ps。

idelay调节。调节tap为2。可以看到调节后的数据较输入原始数据延迟了170ps。

idelay调节。调节tap为200。可以看到调节后的数据较输入原始数据延迟了1160ps。

iserdes解串出来的数据。

为了验证每个通道到达iserdes数据的先后顺序不一致。我们在仿真时,将输入的bit0,作为单独的一路数据,延迟tap设置为500。

设置仿真。

  1. io_delay_iserdes u_io_delay_iserdes0(
  2. //serdes data in and Parallel data out
  3. .data_in (adc_di_p[0] ),
  4. .data_out (data_out[0] ),
  5. //iodelay
  6. .delay_data (9'd500 ),
  7. .delay_valid (delay_valid ),
  8. //system signal
  9. .clk_312_5 (clk_312_5 ),
  10. .clk_625_p (clk_625_p ),
  11. .clk_625_n (clk_625_n ),
  12. .rst (rst ));
  13. genvar i;
  14. generate
  15. for (i = 1; i<=(WIDTH-1); i = i +1) begin : adc_ch_di_p
  16. io_delay_iserdes u_io_delay_iserdes(
  17. //serdes data in and Parallel data out
  18. .data_in (adc_di_p[i] ),
  19. .data_out (data_out[i] ),
  20. //iodelay
  21. .delay_data (delay_data ),
  22. .delay_valid (delay_valid ),
  23. //system signal
  24. .clk_312_5 (clk_312_5 ),
  25. .clk_625_p (clk_625_p ),
  26. .clk_625_n (clk_625_n ),
  27. .rst (rst ));
  28. end
  29. endgenerate

bit0进过iserdes解串出来的并行数据。idelay=0;

bit0进过iserdes解串出来的并行数据。idelay=500;

经过idelay和iserdes还原出来的数据。在调节idelay之前。输入10bit并行数据,可以看到输出的数据为00f,010,011,012,与输入的1.25ghz数据一致。

经过idelay和iserdes还原出来的数据。在调节idelay之后。输入10bit并行数据,可以看到输出的数据为07f,081,080,083,与输入的1.25ghz数据不一致。数据已经错误。

这时再将所有通道idelay延迟设置为500taps。观察解串后的数据。

  1. genvar i;
  2. generate
  3. for (i = 0; i<=(WIDTH-1); i = i +1) begin : adc_ch_di_p
  4. io_delay_iserdes u_io_delay_iserdes(
  5. //serdes data in and Parallel data out
  6. .data_in (adc_di_p[i] ),
  7. .data_out (data_out[i] ),
  8. //iodelay
  9. .delay_data (delay_data ),
  10. .delay_valid (delay_valid ),
  11. //system signal
  12. .clk_312_5 (clk_312_5 ),
  13. .clk_625_p (clk_625_p ),
  14. .clk_625_n (clk_625_n ),
  15. .rst (rst ));
  16. end
  17. endgenerate
  18. //-----------------------------------------------------------
  19. //-----------------------------------------------------------
  20. initial
  21. begin
  22. delay_data =0;
  23. delay_valid =0;
  24. data_clk =0;
  25. clk_312_5 =0;
  26. clk_625_p =0;
  27. clk_625_n =1;
  28. rst =1;
  29. #100;
  30. rst =0;
  31. #100;
  32. delay_data =9'd500;
  33. delay_valid =1'b1;
  34. #10;
  35. delay_data =9'd0;
  36. delay_valid =1'b0;
  37. end

解串后的数据。在idelay写入时,存在几个周期的数据错误。在idelay生效后,解串出来的数据与原始数据一致。解串成功。

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

闽ICP备14008679号