GMII 接口信号定义:TXD、RXD、TX_CLK、RX_CLK 等信号功能

在真正动手写约束之前,得先把 GMII 这堆信号搞清楚。我见过不少新手,上来就照着模板写 set_input_delay,根本不管 TX_CLK 是源同步还是系统同步——结果板子调不通,回头查才发现信号定义没吃透。

说白了,GMII 就是千兆以太网的并行接口。它把 MAC 和 PHY 之间的数据通信用一组信号线串起来。这些信号虽然看起来多,但就几类:数据、时钟、控制。我把它们拆开来讲。

2.1 发送接口信号

先看发送方向——数据从 MAC 流向 PHY。这部分信号我习惯叫“源同步输出组”,因为时钟也是 MAC 给 PHY 的。

信号名位宽方向(MAC 侧)功能描述
TX_CLK1输出 / 输入(具体看模式)发送参考时钟,1000M 时为 125MHz,100M 时为 25MHz,10M 时为 2.5MHz
TXD[7:0]8输出发送数据总线,与 TX_CLK 的上升沿对齐
TX_EN1输出发送使能信号,高电平时 TXD 上数据有效
TX_ER1输出发送错误指示,用于插入错误码或传输暂停控制

这里有个容易犯迷糊的地方:TX_CLK 方向。在标准 GMII 模式下,TX_CLK 由 PHY 提供,MAC 用它来捕获自己的发送数据。嗯,听起来绕是吧?我当初也被坑过。后来查规范围发现——GMII 允许两种时钟方案:

  • 第一种:TX_CLK 由 PHY 产生给 MAC,MAC 内部用 PLL 重新同步后再送数据。
  • 第二种:MAC 自己生成 TX_CLK 送给 PHY(源同步),这样时序更可控,很多 FPGA 设计里我倾向用这种。

我个人建议:做 FPGA 设计时,把 TX_CLK 当成 MAC 的输出时钟处理,这样你在约束里能明确知道 delay 是相对于哪个时钟。

实战小技巧:在 Vivado 或 Quartus 里,我会把 TX_CLK 显式声明为 generated_clock,并关联到 MAC 的输入参考时钟。至于 TXD/TX_EN/TX_ER,统统归到这个 generated_clock 的 output delay 组里。这样约束写下来非常清爽,后期调试也不容易漏信号。

2.2 接收接口信号

接收方向反过来——数据从 PHY 流向 MAC。这是典型的源同步输入信号。PHY 用自己的 RX_CLK 把数据送来,MAC 要用这个时钟采样。

信号名位宽方向(MAC 侧)功能描述
RX_CLK1输入接收参考时钟,由 PHY 提供,频率与发送端一致
RXD[7:0]8输入接收数据总线,与 RX_CLK 的上升沿对齐
RX_DV1输入接收数据有效指示,高电平时 RXD 有效
RX_ER1输入接收错误标志,PHY 检测到编码或载波错误时拉高

为什么 RX_CLK 一定来自 PHY?因为 PHY 从线路上恢复时钟和数据,它最清楚眼图中心在哪。MAC 只能乖乖跟着这个时钟走。

曾经踩过的坑:有一次我直接把 RX_CLK 接到全局时钟网络,想着“反正都是时钟”。结果 PHY 输出 RX_CLK 的抖动很大,导致 setup 时间总是不满足。后来我改成用 BUFR(区域时钟缓冲)处理 RX_CLK,配合 input delay 约束加上 0.5ns 的裕量,问题就解了。所以说——不要迷信全局时钟,对于这种来源不太稳的时钟,建议用区域时钟或 BUFIO,降低时钟偏斜。

2.3 管理接口信号

除了数据通道,GMII 还有一根管理线,用来配置 PHY 内部寄存器。

信号名位宽方向(MAC 侧)功能描述
MDC1输出管理接口时钟,由 MAC 驱动,频率通常不超过 2.5MHz
MDIO1双向管理数据线,用于读写 PHY 寄存器

这部分时序要求比数据通道松得多。你想想看,2.5MHz 的时钟,周期 400ns,FPGA 内部随便一个 IO 逻辑都能满足 setup/hold。所以约束里通常不用特别针对 MDC/MDIO 写严格的 input/output delay,拿个虚时钟虚拟一下就行。

2.4 CRS 与 COL —— 半双工时代的余晖

GMII 规范里还定义了 CRS(载波侦听)和 COL(碰撞检测)。这两个信号功能如下:

  • CRS:PHY 检测到介质上有数据活动时拉高,无论是不是发给自己的。
  • COL:发生碰撞时拉高,仅在半双工模式下有意义。

现在基本上全双工模式一统天下,这两个信号用得极少。我在项目中干脆把它们接地或接固定电平,省得约束里多两笔。

2.5 信号分组与约束思路

好了,所有信号都过了一遍。我们来画个图,把这堆信号的关系理清楚。

GMII 接口信号分组与数据流向 MAC PHY TXD[7:0] + TX_EN + TX_ER TX_CLK(MAC 输出给 PHY 或 PHY 输出给 MAC) RXD[7:0] + RX_DV + RX_ER RX_CLK(PHY 输出给 MAC) MDC (MAC→PHY) / MDIO (双向) 箭头方向表示数据流向,时钟方向须根据具体设计区分:发送时钟可能来自 MAC 也可能来自 PHY

给一个快速判断法则:

  • 发送组(TXD, TX_EN, TX_ER, TX_CLK)—— 属于 源同步输出 时序组,约束用 set_output_delay 加上 generated_clock。
  • 接收组(RXD, RX_DV, RX_ER, RX_CLK)—— 属于 源同步输入 时序组,约束用 set_input_delay 并且时钟就是 RX_CLK 本身。
  • 管理组(MDC, MDIO)—— 属于 低速异步 时序组,通常虚拟一个 2.5MHz 时钟即可,不需要精确约束。

2.6 各信号频率与关系总结

工作模式时钟频率数据时钟关系典型约束场景
10 Mbit/s2.5 MHz每位时钟沿采样 1 个数据时序非常宽松,主要注意 IOB 管脚延时
100 Mbit/s25 MHz每位时钟沿采样 1 个数据中等速度,建议加 0.5~1ns 的 input delay
1000 Mbit/s125 MHz每个时钟沿采样 8 位数据时序最紧张,必须仔细处理 delay 和 clock jitter

我一般做千兆项目时,会额外测量 PCB 上 PHY 到 FPGA 的走线长度,然后算出大概的传输延时。如果走线超过 3 英寸,我会在 input delay 里加上 200ps 的 PCB 延时补偿。

这里有个容易忽略的细节:TX_CLK 和 RX_CLK 是不同源的时钟。哪怕它们的频率都标称 125MHz,实际相位和抖动都是独立的。所以你做跨时钟域处理时(比如把接收数据同步到系统时钟域),必须用两级同步器或异步 FIFO,不能直接用 TX_CLK 采样 RXD。