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 搭的双沿输出,在温度和电压变化时相位抖动大得吓人,直接导致链路断连。
2.2 Tclk 与 Tdata 的约束——没它你玩不转
什么叫 Tclk?就是从发送端时钟输出到接收端时钟输入之间的总延迟。Tdata 则是从发送端数据输出到接收端数据输入的总延迟。RGMII 要求 Tclk 和 Tdata 之间满足一定的关系,否则采错位。
咱们先看一个典型时序参数表(来自 RGMII 标准 v2.0):
| 参数 | 符号 | 最小值 | 典型值 | 最大值 |
|---|---|---|---|---|
| 时钟周期 | Tclk | 7.5 ns | 8.0 ns | 8.5 ns |
| 数据有效窗口 | tDVS | 1.0 ns | — | — |
| 时钟到数据输出延迟 | tCO | 0.5 ns | — | 2.0 ns |
| 占空比 | Duty | 45% | 50% | 55% |
| 上升/下降时间 | tr / tf | 0.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 个时钟周期。
2.3 占空比要求——别小看这 5%
RGMII 标准要求时钟占空比在 45%~55% 之间,也就是高电平宽度在 3.6 ns ~ 4.4 ns(针对 125 MHz,周期 8 ns)。
你会想:差这么一点有什么关系?嗯,我举个例子你就明白了。
接收端内部通常用 PLL 对时钟倍频,或者用它作为内部逻辑的全局时钟。如果占空比偏移严重,会导致时钟沿的位置偏离理想点,进而使采样窗口缩小。我自己遇到过一个极端案例:一块板子用了一颗便宜的振荡器,占空比只有 40%,结果数据眼图开度直接减半,不得不换晶振。
2.4 知识结构一览(SVG)
2.5 避坑指南——从实际案例中长记性
做 RGMII 时序,有三个地方最容易出事:
- 占空比超限。 不是所有晶振都标称 50% 就真的 50%,尤其在高低温下,占空比会漂。我建议在板级测试时专门用示波器看时钟的占空比,同时把数据眼图也抓出来。
- 没有做双沿分别约束。 很多人只写了 -clock_fall 忘了 -rise,或者反过来,导致其中一个沿的余量是负的。Vivado 里用 report_timing_summary 可以明确看到每个沿的 slack,一定要两个沿都看。
- 忽略 PCB 走线长度匹配。 时钟线和数据线之间的长度差如果超过 200 mil(约 40 ps),在高频下就会破坏相对时序。我曾经在 6 层板上因为走线绕了一个 S 弯,导致长度差 500 mil,结果通信时好时坏。后来强制把时钟和数据的走线长度控制在 ±50 mil 以内,问题消失。