4. RGMII特有的DDR双沿采样约束:数据与时钟的相位关系

好,咱们进入第4章。这部分内容,说白了就是RGMII接口能不能跑稳的关键。

很多新手刚接触RGMII时,都会被它的时序搞晕。为什么?因为它用的是DDR(双沿采样)技术。时钟的上升沿和下降沿都要采样数据。这和我们平时做的单沿同步设计,完全是两码事。

我最初接手一个千兆以太网项目时,就栽在这里。板子调通了,数据偶尔丢包。查了整整两天,最后发现是时钟和数据之间的相位关系没搞对。嗯,从那以后,这块我就格外小心了。

4.1 什么是DDR双沿采样?

DDR是Double Data Rate的缩写。传统的SDR(单沿)只在时钟上升沿传输数据。DDR呢?上升沿和下降沿都用上。这样,一个时钟周期就能传2比特数据。

你想想看,对于RGMII来说,千兆速率下时钟频率是125MHz。如果用SDR,数据速率只有125Mbps。但RGMII必须达到1000Mbps。怎么办?数据位宽扩展成4位,再配合DDR双沿采样。

  • 上升沿:采样数据总线的低4位(TXD[3:0] / RXD[3:0])
  • 下降沿:采样数据总线的高4位(TXD[7:4] / RXD[7:4])

这样就拼成了一个完整的8位数据字节。一举两得。既降低了时钟频率,又满足了带宽需求。

核心点:DDR采样不是并行两个时钟,而是利用时钟的两个边沿。这个采样方式,直接决定了后续的时序约束策略。

4.2 数据与时钟的相位关系:中心对齐 vs. 边沿对齐

RGMII标准中,对数据与时钟的相位关系,有一个非常"微妙"的规定。它并不是一成不变的。嗯,这里要注意,在不同版本的RGMII标准里,这种关系甚至截然相反。

4.2.1 RGMII v1.0 / v2.0:中心对齐

在早期的RGMII标准(v1.0和v2.0)中,发送端(MAC)送出的时钟与数据是中心对齐的。

  • 数据的跳变沿,正好落在时钟周期的中间位置
  • 接收端(PHY)要用时钟的边沿去锁存数据

这有什么问题呢?你想想,数据在时钟边沿处跳变,接收端用时钟边沿采样,正好踩在数据变化的不稳定区。这叫建立时间(Tsu)和保持时间(Th)都为零,甚至为负。说白了,就是几乎没法正常采样。

为什么标准要这么干?我个人的理解是,他们想让PCB走线更容易。中心对齐意味着时钟和数据可以在PCB上等长走线,不必额外做延时。但这个"方便",却把时序调整的难题甩给了接收端的PHY芯片。

我的经验:遇到中心对齐的RGMII,千万不要指望FPGA能直接正确采样。必须在FPGA内部或者PCB上,对时钟或数据做90度的相移,把数据对齐到时钟边沿前面。

4.2.2 RGMII v2.5 / v3.0:边沿对齐

后来,大家发现中心对齐实在太坑了。所以修订版标准(v2.5、v3.0)做了调整,变成了边沿对齐。

  • 数据的跳变沿,与时钟的边沿对齐
  • 数据稳定窗口,在时钟信号的中间位置
  • 接收端通常使用时钟的反相沿或内部PLL进行采样

说白了,就是把相位往回调了90度。这样,接收端在时钟边沿采样时,数据正处于稳定的中间区域,Tsu和Th都非常充裕。

特性 RGMII v1.0 / v2.0(中心对齐) RGMII v2.5 / v3.0(边沿对齐)
数据跳变相对于时钟 时钟周期中间 时钟边沿
接收端采样方式 时钟边沿直接采样(Tsu/Th极差) 时钟反相或PLL采样(Tsu/Th好)
PCB走线要求 时钟/数据可等长,相对宽松 需要额外延时或相移
我的建议 尽量别用,或加外部延时芯片 推荐使用,FPGA内部容易处理

重要:芯片数据手册里通常会写明它支持哪个版本的RGMII。我见过不少板子,MAC芯片是v2.0,PHY芯片是v3.0,结果联调时不匹配,数据错位。一定要核对两边的RGMII版本是否兼容。

我个人习惯,在设计FPGA代码时,不管PHY芯片声称支持什么版本,我都会在FPGA内部做一个可编程的相位选择器。通过一个寄存器,可以动态选择用时钟的上升沿、下降沿,或者经PLL移相后的时钟去采样数据。这样无论面对哪种对齐方式,都能灵活适配。

4.3 Tsu/Th要求:建立时间与保持时间

无论哪种对齐方式,最终都要落到Tsu和Th这两个指标上。它们是时序约束的底线。

  • Tsu (Setup Time,建立时间):数据在时钟有效边沿到来之前,必须保持稳定的最小时间。
  • Th (Hold Time,保持时间):数据在时钟有效边沿到来之后,必须保持稳定的最小时间。

对于中心对齐模式,Tsu和Th几乎为0,有时甚至为负值。这意味着什么?你的PCB走线延迟稍微大一点点,数据就采错了。

对于边沿对齐模式,Tsu和Th通常为正,且有一定的余量。比如常见的PHY芯片,会要求Tsu > 1ns,Th > 1ns。这是一个可以轻松满足的目标。

应用公式(简化版):

实际满足的Tsu = 时钟周期 - 数据路径延迟 + 时钟路径延迟 - Tsu要求值

实际满足的Th = 数据路径延迟 - 时钟路径延迟 - Th要求值

只有这两个值都大于0,时序才算收敛。

4.4 这张SVG图:RGMII DDR采样与相位关系总结

下面这张图,是我总结的RGMII时序调整核心逻辑。它把源同步系统、DDR采样、两种对齐方式,以及最终的Tsu/Th调整策略串在了一起。建议你保存下来,做板级调试时对照着看。

RGMII时序调整核心逻辑 源同步系统 (时钟+数据) DDR双沿采样 (2x速率) 中心对齐 (v1.0/v2.0) 边沿对齐 (v2.5/v3.0) Tsu/Th ≈ 0 需90°相移 Tsu/Th 充裕 直接采样可行 时序调整策略:IDELAY / PLL / ODELAY 避坑提示 核对MAC和PHY的RGMII版本是否兼容 FPGA内部务必保留相位选择寄存器

这张图把从源同步系统到最终调整策略的路径都画清楚了。你可以看到,中心对齐和边沿对齐,最终需要的调整手段是不同的。前者必须依赖90度相移,后者则相对简单。

4.5 实战中的选择建议

说了这么多理论,落到实际项目里,到底该怎么做?我这里有几点个人经验,供你参考。

我推荐的做法:

  1. 优先选择边沿对齐的RGMII版本。虽然中心对齐在PCB走线上看似轻松,但它把最难解决的时序问题甩给了后端。在FPGA里做90度相移,不可避免会引入PLL抖动和额外的延迟。
  2. 在FPGA内部建立可编程的采样窗口。我习惯在顶层模块里,例化一个IDELAYE2原语(如果是Xilinx器件),或者类似的IO延时模块。通过SPI/I2C接口或者内部寄存器,可以动态调整时钟或数据的相位。
  3. 一定要做时序闭合检查。别光靠功能仿真。综合后,一定要跑静态时序分析,检查从IO pad到内部寄存器的Tsu和Th。如果余量不足,修改IOB中的延迟值,或者调整PLL的输出相位。

曾经有个项目,我在代码里把时钟反相了,然后直接去采样数据。逻辑上看是对的。结果生产了几百块板子,大约有2%的板子在高温下丢包。后来才发现,反相后的时钟边沿离数据变化太近,保持时间不够。解决办法是在IOB里加了200ps的延时,问题就解决了。

好,关于RGMII特有的DDR双沿采样以及相位关系,就聊到这。搞懂了中心对齐和边沿对齐的区别,理解了Tsu和Th的现实意义,后面我们再聊具体的约束写法,就轻松多了。