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调整策略串在了一起。建议你保存下来,做板级调试时对照着看。
这张图把从源同步系统到最终调整策略的路径都画清楚了。你可以看到,中心对齐和边沿对齐,最终需要的调整手段是不同的。前者必须依赖90度相移,后者则相对简单。
4.5 实战中的选择建议
说了这么多理论,落到实际项目里,到底该怎么做?我这里有几点个人经验,供你参考。
我推荐的做法:
- 优先选择边沿对齐的RGMII版本。虽然中心对齐在PCB走线上看似轻松,但它把最难解决的时序问题甩给了后端。在FPGA里做90度相移,不可避免会引入PLL抖动和额外的延迟。
- 在FPGA内部建立可编程的采样窗口。我习惯在顶层模块里,例化一个IDELAYE2原语(如果是Xilinx器件),或者类似的IO延时模块。通过SPI/I2C接口或者内部寄存器,可以动态调整时钟或数据的相位。
- 一定要做时序闭合检查。别光靠功能仿真。综合后,一定要跑静态时序分析,检查从IO pad到内部寄存器的Tsu和Th。如果余量不足,修改IOB中的延迟值,或者调整PLL的输出相位。
曾经有个项目,我在代码里把时钟反相了,然后直接去采样数据。逻辑上看是对的。结果生产了几百块板子,大约有2%的板子在高温下丢包。后来才发现,反相后的时钟边沿离数据变化太近,保持时间不够。解决办法是在IOB里加了200ps的延时,问题就解决了。
好,关于RGMII特有的DDR双沿采样以及相位关系,就聊到这。搞懂了中心对齐和边沿对齐的区别,理解了Tsu和Th的现实意义,后面我们再聊具体的约束写法,就轻松多了。