RGMII 时钟相位概念:时钟与数据对齐方式、双沿采样原理

搞 RGMII 调试,绕不开一个核心问题 —— 时钟和数据到底怎么对齐的?

很多人一上来就看眼图、调 delay,但根本概念没理清,调半天都是瞎蒙。

先说说 双沿采样。RGMII 这个名字里的「G」就是 gigabit,千兆。千兆以太网在 125 MHz 时钟下要传 1 Gbps 数据,传统 SDR(单沿采样)需要 8 位数据线同时翻转,PCB 布线压力超大。所以 RGMII 用了 DDR(双数据率)—— 时钟的上升沿和下降沿各采一次数据。说白了,一根数据线在单沿模式下只能传 1 bit/周期,DDR 就能传 2 bit。

SDR vs DDR 对比
参数SDR(单沿)DDR(双沿)
数据速率(125 MHz)125 Mbps250 Mbps
所需数据线数量8 根4 根
有效数据窗口半个周期(4 ns)四分之一周期(2 ns)
时钟抖动容限较宽较紧

你想想看,每根线在 4 ns 里要传两个 bit,数据稳定窗口只剩下 2 ns 左右。这对时钟和数据的相对相位要求就非常苛刻了。

两种对齐方式:边沿对齐 vs 中心对齐

按 RGMII 规范(IEEE 802.3-2008 条款 35),发送端有两种对齐方式:

  • 边沿对齐(Edge-aligned / Non-return-to-zero):时钟跳变沿正好位于数据翻转处。上升沿采 D0,下降沿采 D1。
  • 中心对齐(Center-aligned / Internal delay):时钟跳变沿对准数据的正中间(稳定区域)。

这是最容易被忽略的地方,也是我踩过最大的坑。

避坑指南: 我曾经接手一个项目,芯片厂商默认发送端是中心对齐,但板子上用的 PHY 却按边沿对齐来设计。结果就是:上电后 95% 的包都丢,靠示波器抓了三天才找到原因。你如果两个端口的对齐方式不匹配,延时全白调。

规范本身没强制要求 PHY 和 MAC 必须用哪种模式,但业界主流做法是:

  • 发送端(TX)通常使用 边沿对齐(数据随时钟同时输出)
  • 接收端(RX)必须通过 PCB 走线或内部延迟把数据移到时钟中心位置

但在实际芯片里,很多 FPGA 或 ASIC 的 RGMII 接口会在内部自带 2 ns 左右的延迟,让数据相对时钟偏移 90°。这其实就是把边沿对齐转成了中心对齐。

双沿采样的时序约束

我们先画一下理想情况下的时序。注意:下面的 SVG 图展示了时钟和数据的关系以及两种对齐方式。

RGMII 双沿采样与对齐方式 时钟 (125 MHz) 上升沿 下降沿 边沿对齐数据 (TX) 中心对齐数据 (加 2ns 延迟) 稳定窗口 稳定窗口 说明 • 边沿对齐:数据在时钟边沿处跳变,采样必须精确到“跳变后稳定”;容易受走线长度影响。 • 中心对齐:数据加 2 ns 延迟,时钟边沿直接落在数据中间;这是大多数 PHY 接收端期望的模式。

从图里能清楚看到:边沿对齐时,时钟的上升沿正好在数据从 0 变 1 的位置,理论上采样点就是跳变后的瞬间。但实际中走线延迟、门延迟都会让这个对齐变模糊。中心对齐则是在源端把数据延迟了约 90°(2 ns),这样时钟边沿就落到了数据稳定区的正中央,采样可靠性大大提高。

核心概念:RGMII 的双沿采样不是靠时钟占空比保证的,而是靠数据相对于时钟的相移。这个相移要么靠 PCB 走线长度差(外部延迟),要么靠芯片内部的延迟链(内部延迟)。

实际调试时的相位关系判断

我记得有一次调一块 FPGA 和 Marvell PHY 的对接,无论如何 link 都起不来。用示波器抓了 RX 时钟和数据,发现时钟上升沿落在数据的跳变区域,根本不是采样窗口内。那问题就清楚了:MAC 端没有做延迟,而 PHY 期望的是中心对齐。

解决办法:在 FPGA 的约束里加一个 set_output_delay,让 RGMII TX 输出去对齐到时钟中心。或者直接改 PHY 的寄存器,让它用边沿对齐模式收发。我后来习惯把 FPGA 端的 RGMII 接口都设计成可配置的:

// 示例:在 VHDL 中通过参数选择模式
entity rgmii_tx is
    generic (
        DELAY_MODE : integer := 1  -- 0: 边沿对齐  1: 中心对齐
    );
    port (
        clk125 : in  std_logic;
        data   : in  std_logic_vector(3 downto 0);
        txc    : out std_logic;
        txd    : out std_logic_vector(3 downto 0)
    );
end entity;

architecture behavioral of rgmii_tx is
    signal data_delayed : std_logic_vector(3 downto 0);
    signal clk_delayed  : std_logic;
begin
    -- 内部延迟生成(简化版)
    gen_center : if DELAY_MODE = 1 generate
        delay_data : process(clk125) begin
            if rising_edge(clk125) then
                data_delayed <= data;
            end if;
        end process;
        txd <= data_delayed;
    end generate;

    -- 边沿对齐直接输出
    gen_edge : if DELAY_MODE = 0 generate
        txd <= data;
    end generate;
end architecture;

对了,如果你在 PHY 端也遇到类似问题,可以去翻一下数据手册里关于 RGMII_DELAY_CTRL(或者 TXC_DELAY、RXD_DELAY)的寄存器描述。很多 PHY 都有内部粗调/细调单元,可以在 0~2 ns 范围内步进调节。

为什么双沿采样对相位如此敏感

说白了,单沿采样时数据窗口有 4 ns,你走线多 500 ps 基本没事。但双沿采样把周期二等分,每个 bit 的理论有效窗口只有 2 ns。再加上时钟抖动(jitter)、占空比失真、电源噪声,实际可用的窗口可能只剩 1 ns 左右。

我把常见的问题列了一张表,你可以对照排查:

RGMII 相位常见问题速查
现象可能原因检查方向
链路不通,偶尔通一下采样点完全落在跳变区示波器测时钟与数据相对相位
链路能通,但 ping 丢包 10%~50%采样点接近跳变边缘,margin 不足增加/减少 0.5~1 ns 的延迟步进试验
高温下丢包率上升温度导致内部延迟链漂移改用片外走线延迟,或加温度补偿
只有某些 PHY 或 FPGA 批次有问题芯片工艺角差异,延迟抖动量不同预留寄存器可调,不要写死

我自己最头疼的是第三种 —— 量产时高温箱 85 °C 下丢包,常温正常。查了一圈发现是 FPGA 内部的 ODELAY 受温度影响严重,后来换成 PCB 走线绕线(增加约 1.5 ns 延迟)并靠近 PHY,问题才解决。所以说,硬件调试不只靠示波器,还要理解芯片内部的延时单元是怎么实现的,它们受 PVT 影响多大。

小结一下

RGMII 时钟相位的核心就两点:

  1. 双沿采样 让数据窗口缩小到 2 ns,决定了你必须仔细控制相位。
  2. 对齐方式(边沿 vs 中心)决定了你的调试起点 —— 先确认两侧的模式匹配,再去调具体延迟值。

搞懂这两点,你再去调那个 rgmii_txc_delay 寄存器,心里就有底了。