Xilinx KU系列三速以太网IP核RGMII时序约束方法

本文转载自:米联客

1. 概述

基于RGMII时序广泛应用于以太网通信中,基于Xilinx的三速以太网时序分析,不同的Xilinx系列方法不一样。当使用2路以上以太网通信,KU系列FPGA的MAC核需要进行修改,以支持2路以太网和满足时序要求。以下笔者对修改的部分进行说明,希望对广大开发者有所帮助,如果有不对的地方欢迎指针。

2. 代码修改

主要针对以上三个文件修改,详细的可以打开我们的配套工程阅读代码,下图是第一个以太网的三个文件

1.png

tri_mode_ethernet_mac_1_rgmii_v2_0_if.v文件关键部分修改如下:
发送部分odelay3的代码修改,原来默认的代码对于rgmii_tx发送时序调整是通过级联一个idelay3模块来实现,这里注释掉级联的idelay3模块,默认为" TIME"模式最大是1ns延迟调整,修改odelay3模块的delay模式为"COUNT模式",这样每调整1个tap代表了0.005ns,最大可以调整512个tap,这样我们可以实现最大2ns以上的延迟调整
// Instantiate the Output Delay primitive (delay output by 2 ns).  In order to
   // achieve 2ns, an ODELAY is cascaded with an IDELAY from the bitslice
   // immediately below it.
  ODELAYE3 #(
       
      .DELAY_VALUE      (300),
      .DELAY_FORMAT     ("COUNT"),     // Units of the DELAY_VALUE (COUNT, TIME)  
       
      .DELAY_TYPE       ("FIXED"),
      //.CASCADE          ("MASTER"),
      .REFCLK_FREQUENCY (333.333),
      .SIM_DEVICE       ("ULTRASCALE")
       
   )
   delay_rgmii_tx_clk (
      .ODATAIN          (rgmii_txc_odelay),
      .DATAOUT          (rgmii_txc_obuf),
      .CLK              (1'b0),
      .CE               (1'b0),
      .INC              (1'b0),
      .CNTVALUEIN       (9'h0),
      .CNTVALUEOUT      (),
      .LOAD             (1'b0),
      .RST              (1'b0),
      .CASC_IN          (1'b0),
      .CASC_RETURN      (1'b0),
      .CASC_OUT         (),
      .EN_VTC           (1'b1)
   );
/*
 IDELAYE3 #(
      .DELAY_VALUE      (320),
      .DELAY_TYPE       ("FIXED"),
      .CASCADE          ("SLAVE_END"),
      .REFCLK_FREQUENCY (333.333),
      .SIM_DEVICE       ("ULTRASCALE_PLUS")
       
  )
  delay_rgmii_tx_clk_casc (
      .IDATAIN          (1'b0),
      .DATAOUT          (delay_rgmii_tx_clk_casc_return),
      .DATAIN           (1'b0),
      .CLK              (1'b0),
      .CE               (1'b0),
      .INC              (1'b0),
      .CNTVALUEIN       (9'h0),
      .CNTVALUEOUT      (),
      .LOAD             (1'b0),
      .RST              (1'b0),
      .CASC_IN          (delay_rgmii_tx_clk_casc_out),
      .CASC_RETURN      (1'b0),
      .CASC_OUT         (),
      .EN_VTC           (1'b1)
  );
*/
   
   //---------------------------------------------------------------------------
   // RGMII Transmitter Logic :
   // drive TX signals through IOBs onto RGMII interface
   //---------------------------------------------------------------------------
 
   // Encode rgmii ctl signal
   assign rgmii_tx_ctl_int = tx_en_from_mac ^ tx_er_from_mac;
 
   // Instantiate Double Data Rate Output components. Then
   // put data and control signals through ODELAY components to
   // provide similiar net delays to those seen on the clk signal.
 
   assign gmii_txd_falling = txd_from_mac[7:4];
 
   genvar i;
   generate for (i=0; i<4; i=i+1)
     begin : txdata_out_bus
       ODDRE1 #(
         
          .SRVAL         (1'b0)
       )
       rgmii_txd_out (
          .Q             (rgmii_txd_odelay[i]),
          .C             (tx_clk),
          .D1            (txd_from_mac[i]),
          .D2            (gmii_txd_falling[i]),
          .SR            (tx_reset)
       );
 
      ODELAYE3 #(
          .DELAY_VALUE      (0),
          .DELAY_TYPE       ("FIXED"),
          .REFCLK_FREQUENCY (333.333),
      .SIM_DEVICE       ("ULTRASCALE")
       
       )
       delay_rgmii_txd (
          .ODATAIN       (rgmii_txd_odelay[i]),
          .DATAOUT       (rgmii_txd_obuf[i]),
          .CLK           (1'b0),
          .CE            (1'b0),
          .INC           (1'b0),
          .CNTVALUEIN    (9'h0),
          .CNTVALUEOUT   (),
          .LOAD          (1'b0),
          .RST           (1'b0),
          .CASC_IN       (1'b0),
          .CASC_RETURN   (1'b0),
          .CASC_OUT      (),
          .EN_VTC        (1'b1)
       );
 
     end
   endgenerate

同理,接收部分idelay3的代码修改,原来默认为" TIME"模式最大是1ns延迟调整,修改idelay3模块的delay模式为"COUNT模式",这样每调整1个tap代表了0.005ns,最大可以调整512个tap,这样我们可以实现最大2ns以上的延迟调整

IDELAYE3 #(
     .DELAY_FORMAT     ("COUNT"),     // Units of the DELAY_VALUE (COUNT, TIME)
     .DELAY_TYPE       ("FIXED"),
     .REFCLK_FREQUENCY (333.333),
     .DELAY_VALUE      (330),           // Input delay value setting
     .SIM_DEVICE    ("ULTRASCALE")

  )
  delay_rgmii_rx_ctl (
     .IDATAIN       (rgmii_rx_ctl_ibuf),
     .DATAOUT       (rgmii_rx_ctl_delay),
     .DATAIN        (1'b0),
     .CLK           (1'b0),
     .CE            (1'b0),
     .INC           (1'b0),
     .CNTVALUEIN    (9'h0),
     .CNTVALUEOUT   (),
     .LOAD          (1'b0),
     .RST           (1'b0),
     .CASC_IN       (1'b0),
     .CASC_RETURN   (1'b0),
     .CASC_OUT      (),
     .EN_VTC        (1'b1)
     );


  genvar j;
  generate for (j=0; j<4; j=j+1)
    begin : rxdata_bus



      IDELAYE3 #(
      .DELAY_FORMAT     ("COUNT"),     // Units of the DELAY_VALUE (COUNT, TIME)        
         .DELAY_TYPE       ("FIXED"),
         .REFCLK_FREQUENCY (333.333),
         .DELAY_VALUE      (330),           // Input delay value setting
         .SIM_DEVICE    ("ULTRASCALE")

      )
      delay_rgmii_rxd (
         .IDATAIN       (rgmii_rxd_ibuf[j]),
         .DATAOUT       (rgmii_rxd_delay[j]),
         .DATAIN        (1'b0),
         .CLK           (1'b0),
         .CE            (1'b0),
         .INC           (1'b0),
         .CNTVALUEIN    (9'h0),
         .CNTVALUEOUT   (),
         .LOAD          (1'b0),
         .RST           (1'b0),
         .CASC_IN       (1'b0),
         .CASC_RETURN   (1'b0),
         .CASC_OUT      (),
         .EN_VTC        (1'b1)
      );
    end
  endgenerate

下图是第二个以太网的三个文件,由于需要贡献一部分FPGA的delay_ctr资源,他们的代码稍微有点差异。

2.png

修改方法和第一个以太网修改方法一样

ODELAYE3 #(

     .DELAY_VALUE      (300),
     .DELAY_FORMAT     ("COUNT"),     // Units of the DELAY_VALUE (COUNT, TIME)  

     .DELAY_TYPE       ("FIXED"),
     //.CASCADE          ("MASTER"),
     .REFCLK_FREQUENCY (333.333),
     .SIM_DEVICE       ("ULTRASCALE")

  )
  delay_rgmii_tx_clk (
     .ODATAIN          (rgmii_txc_odelay),
     .DATAOUT          (rgmii_txc_obuf),
     .CLK              (1'b0),
     .CE               (1'b0),
     .INC              (1'b0),
     .CNTVALUEIN       (9'h0),
     .CNTVALUEOUT      (),
     .LOAD             (1'b0),
     .RST              (1'b0),
     .CASC_IN          (1'b0),
     .CASC_RETURN      (1'b0),
     .CASC_OUT         (),
     .EN_VTC           (1'b1)
  );
/*
IDELAYE3 #(
     .DELAY_VALUE      (320),
     .DELAY_TYPE       ("FIXED"),
     .CASCADE          ("SLAVE_END"),
     .REFCLK_FREQUENCY (333.333),
     .SIM_DEVICE       ("ULTRASCALE_PLUS")

 )
 delay_rgmii_tx_clk_casc (
     .IDATAIN          (1'b0),
     .DATAOUT          (delay_rgmii_tx_clk_casc_return),
     .DATAIN           (1'b0),
     .CLK              (1'b0),
     .CE               (1'b0),
     .INC              (1'b0),
     .CNTVALUEIN       (9'h0),
     .CNTVALUEOUT      (),
     .LOAD             (1'b0),
     .RST              (1'b0),
     .CASC_IN          (delay_rgmii_tx_clk_casc_out),
     .CASC_RETURN      (1'b0),
     .CASC_OUT         (),
     .EN_VTC           (1'b1)
 );
*/


  //---------------------------------------------------------------------------
  // RGMII Transmitter Logic :
  // drive TX signals through IOBs onto RGMII interface
  //---------------------------------------------------------------------------

  // Encode rgmii ctl signal
  assign rgmii_tx_ctl_int = tx_en_from_mac ^ tx_er_from_mac;

  // Instantiate Double Data Rate Output components. Then
  // put data and control signals through ODELAY components to
  // provide similiar net delays to those seen on the clk signal.

  assign gmii_txd_falling = txd_from_mac[7:4];

  genvar i;
  generate for (i=0; i<4; i=i+1)
    begin : txdata_out_bus
      ODDRE1 #(

         .SRVAL         (1'b0)
      )
      rgmii_txd_out (
         .Q             (rgmii_txd_odelay),
         .C             (tx_clk),
         .D1            (txd_from_mac),
         .D2            (gmii_txd_falling),
         .SR            (tx_reset)
      );

     ODELAYE3 #(
         .DELAY_VALUE      (0),
         .DELAY_TYPE       ("FIXED"),
         .REFCLK_FREQUENCY (333.333),
     .SIM_DEVICE       ("ULTRASCALE")

      )
      delay_rgmii_txd (
         .ODATAIN       (rgmii_txd_odelay),
         .DATAOUT       (rgmii_txd_obuf),
         .CLK           (1'b0),
         .CE            (1'b0),
         .INC           (1'b0),
         .CNTVALUEIN    (9'h0),
         .CNTVALUEOUT   (),
         .LOAD          (1'b0),
         .RST           (1'b0),
         .CASC_IN       (1'b0),
         .CASC_RETURN   (1'b0),
         .CASC_OUT      (),
         .EN_VTC        (1'b1)
      );

    end
  endgenerate

接收部分

IDELAYE3 #(
     .DELAY_FORMAT     ("COUNT"),
     .DELAY_TYPE       ("FIXED"),
     .REFCLK_FREQUENCY (333.333),
     .DELAY_VALUE      (250),           // Input delay value setting              
     .SIM_DEVICE    ("ULTRASCALE")

  )
  delay_rgmii_rx_ctl (
     .IDATAIN       (rgmii_rx_ctl_ibuf),
     .DATAOUT       (rgmii_rx_ctl_delay),
     .DATAIN        (1'b0),
     .CLK           (1'b0),
     .CE            (1'b0),
     .INC           (1'b0),
     .CNTVALUEIN    (9'h0),
     .CNTVALUEOUT   (),
     .LOAD          (1'b0),
     .RST           (1'b0),
     .CASC_IN       (1'b0),
     .CASC_RETURN   (1'b0),
     .CASC_OUT      (),
     .EN_VTC        (1'b1)
     );


  genvar j;
  generate for (j=0; j<4; j=j+1)
    begin : rxdata_bus



      IDELAYE3 #(
         .DELAY_FORMAT     ("COUNT"),
         .DELAY_TYPE       ("FIXED"),
         .REFCLK_FREQUENCY (333.333),
         .DELAY_VALUE      (250),           // Input delay value setting              
         .SIM_DEVICE    ("ULTRASCALE")
      )
      delay_rgmii_rxd (
         .IDATAIN       (rgmii_rxd_ibuf[j]),
         .DATAOUT       (rgmii_rxd_delay[j]),
         .DATAIN        (1'b0),
         .CLK           (1'b0),
         .CE            (1'b0),
         .INC           (1'b0),
         .CNTVALUEIN    (9'h0),
         .CNTVALUEOUT   (),
         .LOAD          (1'b0),
         .RST           (1'b0),
         .CASC_IN       (1'b0),
         .CASC_RETURN   (1'b0),
         .CASC_OUT      (),
         .EN_VTC        (1'b1)
      );
    end
  endgenerate
以上也能看出第二个以太网和第一个以太网的时序调整有所差异。

3. 约束文件修改

由于我们在tri_mode_ethernet_mac_1_rgmii_v2_0_if.v中完成了时序的调整,因此需要注释以下约束

3.png

时序约束部分修改和硬件上PHY的delay延迟设置有关系,米联客的FPGA的PHY以太网芯片rx 有2ns延迟,tx没有2ns延迟。因此rgmii_rx数据是源同步中心对齐方式分析,而rgmii_tx数据是源源步边沿对齐方式分析,米联客使用的是RTL8211FD芯片,关键的时序参数如下:

4.png

5.png

6.png

7.png

8.png

因此给出如下时序约束:

############################################################
# RX Clock period Constraints (per instance)               #
############################################################
# Receiver clock period constraints: please do not relax
set rx_clk [get_clocks -of [get_ports rgmii_rxc]]

############################################################
# Obtain input clocks from top level XDC                         #
############################################################
set ip_gtx_clk     [get_clocks -of_objects [get_ports gtx_clk]]

#
####
#######
##########
#############
#################
#BLOCK CONSTRAINTS

############################################################
# For Setup and Hold time analysis on RGMII inputs         #
############################################################

# define a virtual clock to simplify the timing constraints
create_clock -name [current_instance .]_rgmii_rx_clk -period 8
set rgmii_rx_clk [current_instance .]_rgmii_rx_clk

# Identify RGMII Rx Pads only.  
# This prevents setup/hold analysis being performed on false inputs,
# eg, the configuration_vector inputs.

set_input_delay -clock [get_clocks $rgmii_rx_clk] -max -1.5 [get_ports {rgmii_rxd
rgmii_rx_ctl}]
set_input_delay -clock [get_clocks $rgmii_rx_clk] -min -2.5 [get_ports {rgmii_rxd
rgmii_rx_ctl}]
set_input_delay -clock [get_clocks $rgmii_rx_clk] -clock_fall -max -1.5 -add_delay[get_ports {rgmii_rxd
rgmii_rx_ctl}]
set_input_delay -clock [get_clocks $rgmii_rx_clk] -clock_fall -min -2.5 -add_delay[get_ports {rgmii_rxd
rgmii_rx_ctl}]

set_false_path -rise_from [get_clocks $rgmii_rx_clk] -fall_to $rx_clk -setup
set_false_path -fall_from [get_clocks $rgmii_rx_clk] -rise_to $rx_clk -setup
set_false_path -rise_from [get_clocks $rgmii_rx_clk] -rise_to $rx_clk -hold
set_false_path -fall_from [get_clocks $rgmii_rx_clk] -fall_to $rx_clk -hold

set_multicycle_path -from [get_clocks $rgmii_rx_clk] -to $rx_clk -setup 0
set_multicycle_path -from [get_clocks $rgmii_rx_clk] -to $rx_clk -hold -1

############################################################
# For Setup and Hold time analysis on RGMII outputs        #
############################################################

create_generated_clock -name [current_instance .]_rgmii_tx_clk -divide_by 1 -source[get_pins {tri_mode_ethernet_mac_i/rgmii_interface/rgmii_txc_ddr/C}] [get_ports rgmii_txc]
set rgmii_tx_clk [current_instance .]_rgmii_tx_clk

set_output_delay -0.5 -max -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd
rgmii_tx_ctl}]
set_output_delay -1.2 -min -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd
rgmii_tx_ctl}]
set_output_delay -0.5 -max -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd
rgmii_tx_ctl}] -clock_fall -add_delay
set_output_delay -1.2 -min -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd
rgmii_tx_ctl}] -clock_fall -add_delay

set_false_path -rise_from $ip_gtx_clk -fall_to [get_clocks $rgmii_tx_clk] -setup
set_false_path -fall_from $ip_gtx_clk -rise_to [get_clocks $rgmii_tx_clk] -setup
set_false_path -rise_from $ip_gtx_clk -rise_to [get_clocks $rgmii_tx_clk] -hold
set_false_path -fall_from $ip_gtx_clk -fall_to [get_clocks $rgmii_tx_clk] -hold

set_multicycle_path -from $ip_gtx_clk -to [get_clocks $rgmii_tx_clk] 0 -setup
set_multicycle_path -from $ip_gtx_clk -to [get_clocks $rgmii_tx_clk] -1 -hold

这里时序分析是比较难理解的部分,尤其是根据datasheet分析时序要求,更多的关于时序相关的内容,请看米联客时序课程相关内容。

最新文章

最新文章