ISERDES和IODELAYE1在项目中的使用

ISERDES和IODELAYE1的使用
在公司调试了一个接口,使用Xilinx V6 FPGA的普通IO管脚使用LVDS电平传输1.25GHz数据,本工程使用ISERDES1 和OSERDES1原语做串并转换。

代码说明

ISERDES1原语:

   ISERDESE1 #(
      .DATA_RATE("DDR"),           // "SDR" or "DDR" 
      .DATA_WIDTH(10),              // Parallel data width (2-8, 10)
      .DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (TRUE/FALSE)
      .DYN_CLK_INV_EN("FALSE"),    // Enable DYNCLKINVSEL inversion (TRUE/FALSE)
      // INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
      .INIT_Q1(1'b0),
      .INIT_Q2(1'b0),
      .INIT_Q3(1'b0),
      .INIT_Q4(1'b0),
      .INTERFACE_TYPE("NETWORKING"),   // "MEMORY", "MEMORY_DDR3", "MEMORY_QDR", "NETWORKING", or "OVERSAMPLE" 
      .IOBDELAY("IFD"),           // "NONE", "IBUF", "IFD", "BOTH" 
      .NUM_CE(2),                  // Number of clock enables (1 or 2)
      .OFB_USED("FALSE"),          // Select OFB path (TRUE/FALSE)
      .SERDES_MODE("MASTER"),      // "MASTER" or "SLAVE" 
      // SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
      .SRVAL_Q1(1'b0),
      .SRVAL_Q2(1'b0),
      .SRVAL_Q3(1'b0),
      .SRVAL_Q4(1'b0) 
   )
   ISERDESE1_inst_master (
      .O( ),                       // 1-bit output: Combinatorial output
      // Q1 - Q6: 1-bit (each) output: Registered data outputs
      .Q1(data_out_iser[0]),
      .Q2(data_out_iser[1]),
      .Q3(data_out_iser[2]),
      .Q4(data_out_iser[3]),
      .Q5(data_out_iser[4]),
      .Q6(data_out_iser[5]),
      // SHIFTOUT1-SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
      .SHIFTOUT1(shift1_ise),
      .SHIFTOUT2(shift2_ise),
      .BITSLIP(BITSLIP),           // 1-bit input: Bitslip enable input
      // CE1, CE2: 1-bit (each) input: Data register clock enable input 
      .CE1(1'b1),
      .CE2(1'b1),
      // Clocks: 1-bit (each) input: ISERDESE1 clock input ports
      .CLK(clk),                   // 1-bit input: High-speed clock input
      .CLKB(!clk),                 // 1-bit input: High-speed secondary clock input
      .CLKDIV(clk_div),             // 1-bit input: Divided clock input
      .OCLK(),                 // 1-bit input: High speed output clock input used when
                                   // INTERFACE_TYPE="MEMORY" memory    
      // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
      .DYNCLKDIVSEL(), // 1-bit input: Dynamic CLKDIV inversion input   
      .DYNCLKSEL(),       // 1-bit input: Dynamic CLK/CLKB inversion input  
      // Input Data: 1-bit (each) input: ISERDESE1 data input ports
      .D(ose),                       // 1-bit input: Data input
      .DDLY(ose_dly),                 // 1-bit input: Serial input data from IODELAYE1
      .OFB(),                   // 1-bit input: Data feedback input from OSERDESE1  
      .RST(reset),                   // 1-bit input: Active high asynchronous reset input
      // SHIFTIN1-SHIFTIN2: 1-bit (each) input: Data width expansion input ports
      .SHIFTIN1(),
      .SHIFTIN2() 
   );
ISERDESE1 #(
      .DATA_RATE("DDR"),           // "SDR" or "DDR" 
      .DATA_WIDTH(10),              // Parallel data width (2-8, 10)
      .DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (TRUE/FALSE) 
      .DYN_CLK_INV_EN("FALSE"),    // Enable DYNCLKINVSEL inversion (TRUE/FALSE)
      // INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
      .INIT_Q1(1'b0),
      .INIT_Q2(1'b0),
      .INIT_Q3(1'b0),
      .INIT_Q4(1'b0),
      .INTERFACE_TYPE("NETWORKING"),   // "MEMORY", "MEMORY_DDR3", "MEMORY_QDR", "NETWORKING", or "OVERSAMPLE" 
      .IOBDELAY("IFD"),           // "NONE", "IBUF", "IFD", "BOTH" 
      .NUM_CE(2),                  // Number of clock enables (1 or 2)
      .OFB_USED("FALSE"),          // Select OFB path (TRUE/FALSE)
      .SERDES_MODE("SLAVE"),      // "MASTER" or "SLAVE" 
      // SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
      .SRVAL_Q1(1'b0),
      .SRVAL_Q2(1'b0),
      .SRVAL_Q3(1'b0),
      .SRVAL_Q4(1'b0) 
   )
   ISERDESE1_inst_slave (
      .O(),                       // 1-bit output: Combinatorial output
      // Q1 - Q6: 1-bit (each) output: Registered data outputs
      .Q1(),
      .Q2(),
      .Q3(data_out_iser[6]),
      .Q4(data_out_iser[7]),
      .Q5(data_out_iser[8]),
      .Q6(data_out_iser[9]),
      // SHIFTOUT1-SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
      .SHIFTOUT1(),
      .SHIFTOUT2(),
      .BITSLIP(BITSLIP),           // 1-bit input: Bitslip enable input
      // CE1, CE2: 1-bit (each) input: Data register clock enable input
      .CE1(1'b1),
      .CE2(1'b1),
      // Clocks: 1-bit (each) input: ISERDESE1 clock input ports
      .CLK(clk),                   // 1-bit input: High-speed clock input
      .CLKB(!clk),                 // 1-bit input: High-speed secondary clock input
      .CLKDIV(clk_div),             // 1-bit input: Divided clock input
      .OCLK(),                 // 1-bit input: High speed output clock input used when
                                   // INTERFACE_TYPE="MEMORY" 
      // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
      .DYNCLKDIVSEL(), // 1-bit input: Dynamic CLKDIV inversion input 
      .DYNCLKSEL(),       // 1-bit input: Dynamic CLK/CLKB inversion input 
      // Input Data: 1-bit (each) input: ISERDESE1 data input ports
      .D(),                       // 1-bit input: Data input
      .DDLY(),                 // 1-bit input: Serial input data from IODELAYE1
      .OFB(),                   // 1-bit input: Data feedback input from OSERDESE1 
      .RST(reset),                   // 1-bit input: Active high asynchronous reset input
      // SHIFTIN1-SHIFTIN2: 1-bit (each) input: Data width expansion input ports
      .SHIFTIN1(shift1_ise),
      .SHIFTIN2(shift2_ise) 
   );

ISERDES原语支持级联模式,每一个级原语支持6位并行输出,本次工程使用的是10位并行数据,所以采用两个ISERDES原语级联,级联图示如下:
在这里插入图片描述
本次使用10位数据,Master接收低6位,Slavej接收高4位从Q3开始。切记SHIFTOUT1、SHIFTOUT1和SHIFTIN1、SHIFTIN1连接位置,如果接反了数据会出错。

注意:但比特输出O不能用,不能用ila看,不能用做上升沿采样,否则编译出错。

时钟说明:

      .DATA_RATE("DDR"),           // "SDR" or "DDR" 
      .CLK(clk),                   // 1-bit input: High-speed clock input
      .CLKB(!clk),                 // 1-bit input: High-speed secondary clock input
      .CLKDIV(clk_div),             // 1-bit input: Divided clock input

原语只使用两个时钟,clk clk_div,本次传输速率为1.25Gbps,所以clk = 125MHz clk_div=625MHz。
数据传输时序如下:
在这里插入图片描述
两根黄线之间的时间是8ns,刚好传输10bit穿行数据(DDR双沿采样)。

IODELAYE1

RTL图:
在这里插入图片描述

IDELAYCTRL: IDELAYCTRL 和 IDELAYE2 一般同时使用, IDELAYCTRL 对 IDELAYE2 延时进行校准。
IODELAY_GROUP 为延时 IO 分组,一般数据接口位于多个 BANK 时,才需要分组。
IDELAYCTRL 通过参考时钟 REFCLK 来校准 IDELAY2 每个 tap 的延时值,可用的 REFCLK 频率为190Mhz~210Mhz 或者 290Mhz~310Mhz。时钟频率越高对应的 tap 延时平均值越小,即延时调节精度越高。
当参考时钟为 200Mhz 时,一个 tap 为 78ps。

原语代码:

       (* IODELAY_GROUP = "idelay1" *)    
    IDELAYCTRL IDELAYCTRL_inst (
        .RDY                    (               ),                       
        .REFCLK                 (clk_200mpll    ),         
        .RST                    (reset          )                   
    );

    (* IODELAY_GROUP = "idelay1" *)                 // Specifies group name for associated IODELAYs and IDELAYCTRL
    IODELAYE1 #(
        .CINVCTRL_SEL           ("FALSE"        ),  // Enable dynamic clock inversion ("TRUE"/"FALSE") 
        .DELAY_SRC              ("I"            ),  // Delay input ("I", "CLKIN", "DATAIN", "IO", "O")
        .HIGH_PERFORMANCE_MODE  ("FALSE"        ),  // Reduced jitter ("TRUE"), Reduced power ("FALSE")
        .IDELAY_TYPE            ("VARIABLE"     ),  // "DEFAULT", "FIXED", "VARIABLE", or "VAR_LOADABLE" 
        .IDELAY_VALUE           (0              ),  // Input delay tap setting (0-32)
        .ODELAY_TYPE            ("FIXED"        ),  // "FIXED", "VARIABLE", or "VAR_LOADABLE" 
        .ODELAY_VALUE           (0              ),  // Output delay tap setting (0-32)
        .REFCLK_FREQUENCY       (200.0          ),  // IDELAYCTRL clock input frequency in MHz
        .SIGNAL_PATTERN         ("DATA"         )   // "DATA" or "CLOCK" input signal
    )
    IODELAYE1_inst1 (
        .CNTVALUEOUT            (cnt_dly_out    ),  // 5-bit output - Counter value for monitoring purpose   //0.78ps  
        .DATAOUT                (ose_dly        ),  // 1-bit output - Delayed data output          
        .C                      (clk_div        ),  // 1-bit input - Clock input                
        .CE                     (CE             ),  // 1-bit input - Active high enable increment/decrement function 
        .CINVCTRL               (1'b0           ),  // 1-bit input - Dynamically inverts the Clock (C) polarity      
        .CLKIN                  (1'b0           ),  // 1-bit input - Clock Access into the IODELAY               
        .CNTVALUEIN             (               ),  // 5-bit input - Counter value for loadable counter application  
        .DATAIN                 (1'b0           ),  // 1-bit input - Internal delay data              
        .IDATAIN                (ose            ),  // 1-bit input - Delay data input              
        .INC                    (INC            ),  // 1-bit input - Increment / Decrement tap delay                 
        .ODATAIN                (               ),  // 1-bit input - Data input for the output datapath from the device                 
        .RST                    (reset          ),  // 1-bit input - Active high, synchronous reset, resets delay chain to IDELAY_VALUE/     
                                                    // ODELAY_VALUE tap. If no value is specified, the default is 0.
        .T                      (               )   // 1-bit input - 3-state input control. Tie high for input-only or internal delay or     
                                                    // tie low for output only.    
   );

IODELAY原语主要是基于输入时钟clk_div(200MHz) ,对输入的串行数据IDATAIN进行ps级别的延迟,输出的穿行数据DATAOUT直接接到ISERDES1的串行输入数据。

IODELEY主要配置的参数为INC CE RST三个,RST为高复位,直接接系统复位就行,如下图所示,INC为控制延迟的方向,INC=1时,向后延迟,INC=0时,向前延迟。最小延迟步进78ps。
在这里插入图片描述
在没开始调延迟的时候会又144ps的延迟(具体原因还没搞懂,应该是原语本身原因)。

在这里插入图片描述
在INC=1的情况下,拉高一个时钟(125MHz)周期的CE后,DATAOUT相比于IDATAIN向后延迟为222ps,差值为78ps(向前向后延迟时间都一样)。

在这里插入图片描述
在做IODELAY的时候,需要时刻观察ISERDES输出的并行数据,此时需要使用ISERDES和OSERDES之间的标校功能。
使用标校功能需要发送端发送一段时间的固定数,用于ISEDERS标校(当然这是ISERDES和OSERDES之间通信的时候使用),如果接收端不受控制则不需要标校,直接对接收的并行数据做其他处理即可。

ISERDES1标校流程

发送端一直发送10’b0000011111,接到接收端回送标校完成标志后再发送用户数据,此流程上电的时候便开始,也可以手动开始。
上电后,发送端一直发送接10’b0000011111,收端开始使用IODELAY对串行数据进行延迟,首先拉高INC,每个周期拉高一次CE,判断ISERDES并行数据是否变化,同时加个计数器,如下所示,数据在cnt=9 (t0)和cnt=19(t1)的时候并行数据发生变化,因为数双沿采样,所以两次数据变化的时间差,就是上升沿和下降沿之间的位置,找到双沿位置后,再向前延迟(t1+t0)/2,此时数据便调节到双沿之间的位置。此时IODELAY功能便调试完毕,完毕后便可以开始BITSLIP的位调节。

在这里插入图片描述

BITSLIP调节:本次使用的是DDR Mode
在这里插入图片描述
如图所示,DDR Mode :BITSLIP调节流程为,拉高一个周期的BITSLIP后,并行数据会右移一位输出,下次拉高一个周期的BITSLIP后,并行数据会左移三位输出。
SDR Mode :拉高一个周期的BITSLIP后,并行数据会左移一位输出,下次拉高一个周期的BITSLIP后,并行数据仍会左移一位输出,高位直接放到最低位。循环左移。
每次拉高一个周期的BITSLIP后,便需要判断ISERDES并行数据是否为10’b0000011111,如果不相等则继续移位调节,如果是,则停止移位操作,发送标校完成标志。
此时接收端的并行数据便会和发送端的并行数据一致。

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值