2. RGMII 时钟与数据关系:DDR 双沿采样、Tclk 与 Tdata 的约束、占空比要求

RGMII 接口,说白了就是「双倍速率」的杠精。别人在时钟上升沿采一次数据,它偏要上升沿和下降沿各采一次。我记得刚接手第一个千兆以太网项目时,一看 RGMII 的时序图,心里就犯怵——这上升沿和下降沿都要对齐,怎么设计?

别急,这一节我们就把核心概念拆开揉碎,让你从底层理解为什么会有这些约束,以及在实际板子上怎么保证不出错。

2.1 DDR 双沿采样到底怎么工作的?

DDR 是 Double Data Rate 的缩写。在 RGMII 里,时钟频率是 125 MHz,但数据率却是 250 Mbps——因为时钟的每个沿都传输一位数据。

举个具体的例子:

  • 上升沿:发送 / 接收 bit0
  • 下降沿:发送 / 接收 bit1
  • 一个时钟周期内,完整传输 2 位数据

你的 FPGA 内部逻辑可能还是单沿时钟域,所以需要一个 DDR 输出原语把两个内部数据合并到同一个时钟的两个沿上。很多新手在这里容易踩坑:告诉我,你用的是 IOB 里的 ODDR 还是自己用 LUT 搭的?我自己吃过亏——用 LUT 搭的双沿输出,在温度和电压变化时相位抖动大得吓人,直接导致链路断连。

我的个人习惯: 只要芯片支持,一律用厂商提供的 DDR 输出原语(比如 Xilinx 的 ODDR / IDDR,Altera 的 ALTDDIO_OUT / ALTDDIO_IN)。这些原语在 IOB 内部有专门的路由,能保证两个沿的偏移极小。

2.2 Tclk 与 Tdata 的约束——没它你玩不转

什么叫 Tclk?就是从发送端时钟输出到接收端时钟输入之间的总延迟。Tdata 则是从发送端数据输出到接收端数据输入的总延迟。RGMII 要求 Tclk 和 Tdata 之间满足一定的关系,否则采错位。

咱们先看一个典型时序参数表(来自 RGMII 标准 v2.0):

参数符号最小值典型值最大值
时钟周期Tclk7.5 ns8.0 ns8.5 ns
数据有效窗口tDVS1.0 ns——
时钟到数据输出延迟tCO0.5 ns—2.0 ns
占空比Duty45%50%55%
上升/下降时间tr / tf0.4 ns—1.0 ns

你可能会问:那 Tclk 和 Tdata 的约束到底怎么写?

其实核心就两个等式:

// 设置时钟延迟最小值
set_output_delay -clock [get_clocks rgmii_tx_clk] -min -add_delay \
    -clock_fall -rise [expr 0.5 * T_clk_period - t_CO_min]

// 设置时钟延迟最大值  
set_output_delay -clock [get_clocks rgmii_tx_clk] -max -add_delay \
    -clock_fall -rise [expr 0.5 * T_clk_period + t_CO_max]

上面的 -clock_fall -rise 表示「在下降沿对上升沿数据进行约束」。为什么这么写?因为 DDR 采样时,接收端在下降沿采到的是发送端上升沿送出的数据,两者相差 0.5 个时钟周期。

我曾经踩过的坑: 在一款国产 FPGA 上,厂商的 DDR 原语在下降沿输出时比上升沿输出额外多了 0.3 ns 的延迟,我一开始没注意到这个差异,结果板子跑起来偶尔丢包。后来加上专门的 set_output_delay 把两个沿分别约束,问题立刻解决。所以——两个沿的约束一定要分开写!

2.3 占空比要求——别小看这 5%

RGMII 标准要求时钟占空比在 45%~55% 之间,也就是高电平宽度在 3.6 ns ~ 4.4 ns(针对 125 MHz,周期 8 ns)。

你会想:差这么一点有什么关系?嗯,我举个例子你就明白了。

接收端内部通常用 PLL 对时钟倍频,或者用它作为内部逻辑的全局时钟。如果占空比偏移严重,会导致时钟沿的位置偏离理想点,进而使采样窗口缩小。我自己遇到过一个极端案例:一块板子用了一颗便宜的振荡器,占空比只有 40%,结果数据眼图开度直接减半,不得不换晶振。

特别注意: 不要只看数据手册上的占空比范围,还要看晶振 / 时钟缓冲器在负载电容不同时的实际表现。我建议在原理图阶段就把这部分容差算进去,留出 0.5 ns 以上的冗余。

2.4 知识结构一览(SVG)

RGMII时钟与数据关系知识结构 RGMII 时钟与数据关系核心知识体系 DDR 双沿采样 T_clk / T_data 约束 占空比要求 上升沿 + 下降沿 ODDR/IDDR 原语 min delay 等式 max delay 等式 45%~55% PLL 影响 数据眼图开度 IOB 专用路由 -clock_fall 用法 沿独立约束 负载电容影响 占空比失真 最终目标:保证每个数据沿都有足够建立/保持时间

2.5 避坑指南——从实际案例中长记性

做 RGMII 时序,有三个地方最容易出事:

  1. 占空比超限。 不是所有晶振都标称 50% 就真的 50%,尤其在高低温下,占空比会漂。我建议在板级测试时专门用示波器看时钟的占空比,同时把数据眼图也抓出来。
  2. 没有做双沿分别约束。 很多人只写了 -clock_fall 忘了 -rise,或者反过来,导致其中一个沿的余量是负的。Vivado 里用 report_timing_summary 可以明确看到每个沿的 slack,一定要两个沿都看。
  3. 忽略 PCB 走线长度匹配。 时钟线和数据线之间的长度差如果超过 200 mil(约 40 ps),在高频下就会破坏相对时序。我曾经在 6 层板上因为走线绕了一个 S 弯,导致长度差 500 mil,结果通信时好时坏。后来强制把时钟和数据的走线长度控制在 ±50 mil 以内,问题消失。
最后提醒一句: 以上所有约束最终都要落实到真实 PCB 的延迟参数上。仿真做一百遍,不如上示波器量一次。但仿真能帮你提前发现极端情况——所以两手都要抓。