RGMII Interface Timing Considerations

RGMII Timing Basics

The RGMII interface is the physical connection between the Ethernet PHY and the Ethernet MAC. If you are using the Ethernet FMC, the PHY is the Marvell 88E1510, and the Ethernet MAC is inside the FPGA. The RGMII interface is a dual data rate (DDR) interface that consists of a transmit path, from FPGA to PHY, and a receive path, from PHY to FPGA. Both paths have an independent clock, 4 data signals and a control signal.

The RGMII standard specifies that data and clock be output simultaneously (ie. without any skew on the clock), as shown in the left-side image below. For proper sampling of the data signals at the receiver side, the RGMII standard specifies that skew be added to the clock signal, either by the PCB traces, or by the receiver itself (on the TX path, the receiver is the PHY, whereas on the RX path, the receiver is the FPGA). The right-side image below shows the clock and data signals after clock skew has been added.

If you are experiencing one of the following problems, then you probably have an issue with your RGMII interface:

  • Ethernet port is transmitting but not receiving
  • Ethernet port is receiving but not transmitting
  • Ethernet port is working at 10Mbps and 100Mbps but unable to work at 1Gbps

RGMII Interface without clock skew

Figure 1. The RGMII standard specifies clock and data signals to be output with no skew, ie. the clock edges are aligned with the data edges. This is not ideal for the receiver’s sampling circuit, but it greatly simplifies the transmitter circuit.

RGMII Interface with clock skew

Figure 2. RGMII clock and data signals as they must be presented to the receiving circuit for optimal sampling. The clock skew has been added by the PCB trace or the receiving device.

Adding the clock skew

In an FPGA based system, there are three stages where the required skew (ie. delay) can be added to the TX and RX clock signals. The first stage is in the FPGA, the second stage is on the PCB traces (ie. with longer clock traces than the data traces) and the third stage is in the PHY. In an optimal RGMII interface, the skew is added at only one stage in the TX and RX path, and the other two delay stages are disabled or not implemented.

Clock skew stages in the RGMII interface

The skew of the TX and RX clocks can be managed independently, it does not have to be implemented at the same stage on each path, but it must be implemented somewhere on each path. So it is critical to understand each of the delay stages in your target system in order to ensure that the clocks in your RGMII interface are properly skewed. We will now discuss each skew stage and the various ways to enable or disable them.

Stage 1: FPGA

Whether or not the clock skew is implemented in the FPGA, and how it is implemented depends on the IP that you are using to implement the MAC.

AXI Ethernet Subsystem

TX clock skew: YES
The AXI Ethernet Subsystem IP core is designed to output a TX clock with skew, and there is no option in the Vivado GUI to disable this skew. It does this by clock forwarding a clock with a 90 degrees phase shift with respect to the clock that is used to output the data signals. In summary, when using AXI Ethernet Subsystem, you must disable TX clock skew in the PHY and ensure that there is no skew added by the TX clock trace on the PCB.

RX clock skew: NO
The AXI Ethernet Subsystem IP core does not add skew to the RX clock, therefore the skew must be added by either the PHY or the PCB trace.

For more detailed information concerning the TX and RX clock skew in the AXI Ethernet Subsystem, you must refer to the product guide for the Tri-mode Ethernet MAC IP, which is wrapped by AXI Ethernet Subsystem.

GMII-to-RGMII

(for connecting the Zynq GEM via EMIO)

TX clock skew: OPTIONAL
The GMII-to-RGMII core has an option to add 2ns of skew to the TX clock. This option can be accessed in the Vivado GUI through the option “Skew added by PHY” (see below image). When this option is ticked, the core will output the TX clock without skew. When unticked, the core will output the TX clock with 2ns of skew.
Skew added by PHY option

RX clock skew: NO
According to the GMII-to-RGMII product guide page 29, the GMII-to-RGMII core does not add skew to the RX clock, so the skew must be added by the PHY or the PCB clock trace.

For more detailed information regarding the TX and RX clock skew in the GMII-to-RGMII core, please refer to the product guide.

Zynq GEM via MIO

TX clock skew: NO
The Zynq GEMs do not add clock skew to the TX clock, therefore the skew must be added by the PHY or the PCB trace.

RX clock skew: NO
The Zynq GEMs do not add clock skew to the RX clock, therefore the skew must be added by the PHY or the PCB trace.

If you are using the Ethernet FMC, it is very unlikely that the Zynq MIO pins are routed to the FMC connector, but this case has been included here for completeness.

Stage 2: PCB

The Ethernet FMC has clock and data traces that are length matched between the FMC connector and the PHYs, therefore, no clock skew is added by the Ethernet FMC PCB traces. However, to get the complete picture, we must also consider the length of the traces on the FPGA board. Luckily, most FMC carriers (such as the ZedBoard and the ZC706) are designed with length matched traces between the FPGA and all of the FMC connector’s I/Os. Hence in most cases, when using the Ethernet FMC, you can expect the overall clock and data traces to be length matched all the way from the PHYs to the FPGA. As such, you must ensure that the clock skew is added by either the PHY or the FPGA.

Custom FPGA Boards

Although the PCB traces can be designed to implement the clock skew, in most cases this is the least ideal location to implement the skew, so most board designers will route RGMII clock and data traces that are length matched. That said, it is important to know if your PCB’s RGMII interface has been routed with clock skew so that you know how to appropriately configure the FPGA and PHYs – ask your board designer if you’re not sure. If your PCB has been routed with clock skew, then you must disable clock skew in both the FPGA and the PHY.

Stage 3: PHY

The Marvell 88E1510 Ethernet PHYs were designed with two internal delays which can be enabled to add skew to the incoming RGMII TX clock and the outgoing RGMII RX clock independently. The delay, regardless of link speed, is always 1.9ns. The delays are enabled or disabled by writing to a particular register in the PHY, accessed over the MDIO bus. How this is handled depends on whether you are running Linux or a stand-alone application.

Linux

In Linux applications, the simplest way to enable or disable the internal clock delays is through the device tree. The device tree will contain a section for each of your Ethernet interfaces and it should look similar to the one shown to the right.

To enable or disable the internal clock delays, we specify a particular value for the “phy-mode” parameter.

Both internal delays DISABLED:

    phy-mode = "rgmii";

Both internal delays ENABLED:

    phy-mode = "rgmii-id";

Only RX internal delay ENABLED:

    phy-mode = "rgmii-rxid";

Only TX internal delay ENABLED:

    phy-mode = "rgmii-txid";
&axi_ethernet_0 {  
    local-mac-address = [00 0a 35 00 01 22];  
    phy-handle = <&phy0>;  
    xlnx,has-mdio = <0x1>;  
    phy-mode = "rgmii";  
    mdio {  
        #address-cells = <1>;  
        #size-cells = <0>;  
        phy0: phy@0 {  
            compatible = "marvell,88e1510";  
            device_type = "ethernet-phy";  
            reg = <0>;  
        };  
    };  
};

Stand-alone

When using a standalone application, we have to perform the specific register writes over the MDIO bus in order to enable/disable the internal clock delays.

  • The TX clock delay is enabled by setting bit 4 of register 21 of page 2.
  • The RX clock delay is enabled by setting bit 5 of register 21 of page 2.

Below is an example of doing this for each of the 4 possible configurations. Note that we are using function calls to the AXI Ethernet Subsystem library; the names of the equivalent functions for the Zynq GEM will be slightly different.

#define PHY_ADDRESS                0   // Ethernet FMC PHY address
#define IEEE_CONTROL_REG_MAC       21  // The register containing the TX/RX clock delay enables
#define IEEE_PAGE_ADDRESS_REGISTER 22  // For specifying the page number
#define IEEE_RGMII_TX_CLOCK_DELAYED_MASK 0x0010
#define IEEE_RGMII_RX_CLOCK_DELAYED_MASK 0x0020

u16 control;

/* RGMII with both internal delays disabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control &= ~(IEEE_RGMII_TX_CLOCK_DELAYED_MASK | IEEE_RGMII_RX_CLOCK_DELAYED_MASK);
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

/* RGMII with both internal delays enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control |= (IEEE_RGMII_TX_CLOCK_DELAYED_MASK | IEEE_RGMII_RX_CLOCK_DELAYED_MASK);
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

/* RGMII with only RX internal delay enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control &= ~IEEE_RGMII_TX_CLOCK_DELAYED_MASK;
control |= IEEE_RGMII_RX_CLOCK_DELAYED_MASK;
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

/* RGMII with only TX internal delay enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control |= IEEE_RGMII_TX_CLOCK_DELAYED_MASK;
control &= ~IEEE_RGMII_RX_CLOCK_DELAYED_MASK;
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

Case-by-case

In closing this technical guide, we will list the required RGMII delay configuration for each of the possible use cases. As the majority of applications use length matched PCB traces, we will assume no clock skew is added by the PCB. Here are the required configurations for each of the three MAC options:

Case 1: Using AXI Ethernet Subsystem

  • TX clock skew must be DISABLED in PHY (because the skew is implemented in the FPGA)
  • RX clock skew must be ENABLED in the PHY

In Linux, use:

phy-mode = "rgmii-rxid";

In standalone applications, use the following code:

/* RGMII with only RX internal delay enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control &= ~IEEE_RGMII_TX_CLOCK_DELAYED_MASK;
control |= IEEE_RGMII_RX_CLOCK_DELAYED_MASK;
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

Case 2: Using GMII-to-RGMII (Zynq GEM via EMIO)

When using GMII-to-RGMII, you have the choice of where to implement the TX clock skew, so there are two possibilities:

Option 1: TX clock skew ENABLED in FPGA

  • TX clock skew must be DISABLED in the PHY
  • RX clock skew must be ENABLED in the PHY

In Linux, use:

phy-mode = "rgmii-rxid";

In standalone applications, use the following code:

/* RGMII with only RX internal delay enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control &= ~IEEE_RGMII_TX_CLOCK_DELAYED_MASK;
control |= IEEE_RGMII_RX_CLOCK_DELAYED_MASK;
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

Option 2: TX clock skew DISABLED in FPGA

  • TX clock skew must be ENABLED in the PHY
  • RX clock skew must be ENABLED in the PHY

In Linux, use:

phy-mode = "rgmii-id";

In standalone applications, use the following code:

/* RGMII with both internal delays enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control |= (IEEE_RGMII_TX_CLOCK_DELAYED_MASK | IEEE_RGMII_RX_CLOCK_DELAYED_MASK);
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

Case 3: Using Zynq GEM via MIO

  • TX clock skew must be ENABLED in the PHY
  • RX clock skew must be ENABLED in the PHY

In Linux, use:

phy-mode = "rgmii-id";

In standalone applications, use the following code:

/* RGMII with both internal delays enabled */
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, &control);
control |= (IEEE_RGMII_TX_CLOCK_DELAYED_MASK | IEEE_RGMII_RX_CLOCK_DELAYED_MASK);
XAxiEthernet_PhyWrite(xaxiemacp, PHY_ADDRESS, IEEE_CONTROL_REG_MAC, control);

Still having problems?

Contact us