SGMII技术全解析:从8B/10B编码到速率适配与工程避坑指南
简介SGMII Specification V1.8 是串行千兆媒体独立接口SGMII的规范文档面向 10/100/1000 以太网 PHY 与 MAC 之间的接口设计、验证与调试场景适合硬件工程师、FPGA 开发者和网络协议研究者。文档描述了两条数据信号与两条时钟信号的工作方式通过 1.25 Gbaud 数据率和 625 MHz DDR 时钟构建低引脚数的全双工/半双工链路并沿用 IEEE 802.3z 的 1000BASE-SX PCS 编解码思路。压缩包共 1 个文件PDF 格式大小约 133KB全文 11 页便于按章节快速查阅已有 3657 人学习下载。作为 2005 年 11 月发布的最新版本V1.8 相比早期版本增加了 PHY 发送数据通道中的 shim用于在 TX_EN 未断言时抑制 TX_ER同时明确了数据采样、时钟恢复、帧前导码/SFD 数据模式以及 Cisco 知识产权相关说明。读者可由此掌握 SGMII 信号定义、时序要求、配置寄存器与 Auto-Negotiation 流程并对照 MII/GMII 的兼容关系为千兆以太网接口设计提供可直接引用的参考依据。1. SGMII Specification V1.8 不是文档是网口调不通时的救命说明书第一次在某开发板上调 10/100/1000M 自适应网口PHY 的 link 寄存器已经置 1可 MAC 侧死活收不到帧最后查出来是 SGMII 自协商控制字没按 V1.8 的位定义回 ACK。SGMIISerial Gigabit Media Independent Interface用 1.25 Gbaud 差分数据和 625 MHz DDR 时钟把 GMII 的二十多根并行线压成四根差分线同时把 TX_EN、RX_DV、差错状态全部编进 8B/10B 码流。V1.8 是 2005 年修订后流传最广的版本核心变化是在 PHY 发送路径加了一段 TX_ER 抑制逻辑专治帧尾误报错导致的丢帧。这份规范适合三类人写 FPGA MAC 的 RTL 工程师、调 PHY 驱动和硬件链路的系统工程师以及被千兆协商成功但收发不通折磨的调试者。它只有 11 页但每页的信息密度都高到值得反复读。2. 四根线怎么替代二十多根SGMII 信号映射与 8B/10B 编码2.1 引脚缩减和信号清单传统 GMII 需要 TXD[7:0]、RXD[7:0]、TX_EN、RX_DV、TX_ER、RX_ER、TX_CLK、RX_CLK、GTX_CLK、CRS、COL 等二十多根单端信号SGMII 只保留两对数据和两对时钟全部走 LVDS 差分。引脚减少的直接收益是 PCB 布线面积、串扰和功耗同时下降代价是 MAC 和 PHY 两侧都要各放一套串化/解串和 8B/10B 编解码逻辑。SGMII 信号方向电平标准速率承载的 GMII 信息RX / RXCLKPHY → MACLVDS 差分对数据 1.25 Gbaud时钟 625 MHz DDRRXD[7:0]、RX_DV、RX_ERTX / TXCLKMAC → PHYLVDS 差分对数据 1.25 Gbaud时钟 625 MHz DDRTXD[7:0]、TX_EN、TX_ER注意几个容易被忽略的派生信号。CRS 不直接编码传输MAC 侧用恢复出的 RX_DV 推断载波侦听所以 RX_DV 的质量直接影响 CSMA/CD 的行为。COL 也不是从线上解出来的而是在 MAC 内部通过 RX_DV 与 TX_EN 同时拉高逻辑与出来。这意味着半双工模式下你看到的冲突信号实际上是本地组合逻辑的产物不是远端 PHY 告诉你的。2.2 收发数据通路的功能块拆解PHY 侧接收方向PHY 把 GMII 数据发给 MAC的数据流是这样的GMII 信号以 10/100/1000 Mbps 进入 PHY 的 Receive Rate Adaptation 块统一转换到 125 MHz 时钟域的 8 位 RXD[7:0]然后送进 802.3z 的 PCS Transmit State Machine生成 10 位编码 ENC_RXD[0:9]最后经串化器以 1.25 Gbit/s 发出同时送出 625 MHz DDR RXCLK。发送方向MAC 发数据给 PHY是镜像流程PHY 解串 TX 得到 ENC_TXD[0:9] 后先过 PCS Receive State Machine 恢复出 GMII 信号再过 PHY Transmit Rate Adaptation 按端口速率把数据段输出给 10/100/1000 PHY。中间还有一个 Synchronization 块持续检查编码流里的同步码组一旦检测到失步就重新对齐。失步判据和重对齐算法都来自 802.3zSGMII 本身没有额外定义。MAC 侧的结构与 PHY 侧对称但多了两个细节一是 MAC Receive Rate Adaptation 需要根据 PHY 通过自协商传来的速率信息决定怎么采样二是 MAC Transmit Rate Adaptation 要把 2.5/25/125 MHz 时钟域的 GMII 数据统一搬到 125 MHz 域。这两个块是 SGMII 速率适配的核心下一章专门讲。2.3 帧开始必须给足前导{8h55, 8h55, ..., 8hD5}规范里有一段容易被新手跳过的硬性要求PHY 发往 MAC 方向的帧开始RXD[7:0] 必须是 8h55、8h55、若干 8h55、最后接 8hD5SFD然后才是有效帧数据。也就是说至少两个前导符号加一个 SFD 符号。原因是 802.3z 的 PCS Transmit State Machine 在处理帧时可能丢掉第一个字节V1.7 修订明确承认了possible loss of the first byte of preamble。如果你自己写 MAC 侧的 PCS 接收状态机常见做法是检测到 /S/ 码组后开始组装数据但前导字节数不要硬性要求 7 个。实际抓波形时10/100M 模式下第一个 0x55 只出现 9 次而不是 10 次是正常现象不要当成丢帧误报。这个坑在第三章展开。2.4 修订历史里藏着的工程决策版本修订信息本身就是一份排错手册我整理成表版本日期关键变更工程含义1.01999.10初版SGMII 基本框架1.11999.11引入自协商更新链路状态控制字走 AN 通道1.22000.02加入时序预算分析LVDS 输入阈值降到 ±50 mV收端灵敏度要求提高1.32000.04放宽输入输出共模范围调整高低电平补 AC 耦合说明允许直流不达标时用交流耦合1.42000.06删除 Jabber 内容tx_Config_Reg[0] 从 0 改 1让自协商真正能跑起来1.52000.08规定 PHY 发往 MAC 方向的帧开始数据模式解决 PCS 层不工作的问题1.62001.01加入某厂商 IP 相关条款兼容特定实现1.72005.07澄清数据采样方式和前导首字节可能丢失解决采样对齐歧义1.82005.11PHY 发送路径加 shim 抑制 TX_ER 误报解决帧尾毛刺丢帧V1.8 的 shim 是这一版最重要的改动全双工模式下当 TX_EN 没有拉高时PHY 发送路径里的小逻辑块直接把 TX_ER 压掉防止 PCS 接收状态机在帧尾生成的错误信号把老式终端干翻。这个改动的背景是某些 legacy endpoint 在帧结束后的第一个时钟看到 RX_ER 就会丢帧而 RX_ER 往往是接收状态机正常收尾时顺带产生的。换句话说V1.8 不是加法是做了一次减法。3. 速率适配与帧拉长10/100M 的复制魔法3.1 为什么 1.25 Gbaud 接口要处理 10M 帧SGMII 的物理层速率是 1.25 Gbaud对应 1000BASE-X 的线路速率。如果端口工作在 10M 或 100M线上的数据率不变但帧内部的每个字节会被复制 10 次100M或 100 次10M。这就是帧拉长帧的总长度变长了但帧结构和 SFD 只出现一次。关键点在于复制发生在 802.3z PCS 层之上。链路两端的 PCS 收发状态机完全不知道速率这回事它们看到的只是 125 MHz 时钟域里一个被拉长的字节流。这么做的好处是 PHY/MAC 里的 8B/10B 编解码逻辑不需要为低速模式单独设计坏处是你要在接收侧想办法把这 10 个或 100 个相同的字节还原成 1 个字节还得保证采样对齐不出错。3.2 复制机制到底怎么工作100M 模式下原始字节 D0 会被复制成 10 个 D0D1 复制成 10 个 D1以此类推。10M 模式下每个字节复制 100 次。SFD 只在帧头出现一次帧数据和 FCS 全部复制但复制不会跨越帧边界——RX_DV 拉高对应帧内数据的区间拉低代表帧结束复制只发生在 RX_DV 拉高期间。端口速率PCS 前数据率时钟域每个字节复制次数SAMPLE_EN 采样间距1000M125 MHz × 8 bit125 MHz1每 1 段采 1 次100M25 MHz × 8 bit125 MHz10每 10 段采 1 次10M2.5 MHz × 8 bit125 MHz100每 100 段采 1 次PHY 侧发送方向的逻辑是GMII 数据在 2.5/25/125 MHz 时钟域进入 PHY Transmit Rate Adaptation按速率把数据段复制后输出到 125 MHz 域。MAC 侧接收方向的逻辑正好反过来从 125 MHz 域恢复 GMII 数据但要按 PHY 传来的速率信息决定每几个数据段取一个。3.3 SAMPLE_EN 与无固定边界的采样对齐MAC 内部有一个 SAMPLE_EN 信号控制 MAC 采样数据的时机。100M 模式下从第一个数据段也就是 /S/ 码组后的第一个数据开始每 10 个数据段拉高一次采样使能。10M 模式同理间距是 100。难点在于规范明确说there is no fixed boundary for the data sampling——采样窗口没有固定边界。如果你试图用 RX_DV 上升沿作为对齐基准数 10 拍采样一次大概率会在某些帧上采错位。原因就是 V1.7 提到的帧的第一个前导字节可能只复制了 9 次10M 下是 99 次PCS 状态机在发出 /S/ 之前可能已经吞掉了一个字节。正确的对齐策略是把 /S/ 码组当作基准。接收端 PCS 检测到 /S/ 后从紧随其后的第一个数据段开始计数每隔 10或 100段采一次。图 4 里画得很清楚D0 复制 10 次SAMPLE_EN 在第一个 D0 处拉高之后每 10 个 D0 再拉高到 D1 的第一个复制字节再次拉高。整个过程中 RX_DV 一直保持高电平SAMPLE_EN 与 RX_DV 的边沿没有固定相位关系。3.4 采样对齐的三个边界条件第一个边界帧首字节可能只复制 9/99 次。这是 PCS 算法导致的实际行为不是 PHY 没按规范做。所以你在写 RTL 计数器时不能假设首字节一定复制满 10 次要允许首段间隔是 9 或 99。第二个边界SFD 只出现一次但 /S/ 码组之前的对齐符/I/ 或 /K28.5/在帧间持续发送。如果你在 /S/ 之前用 /I/ 做计数基准会因为帧间空闲不确定而偏掉。第三个边界低速模式下 125 MHz 时钟始终在跑但 RX_DV 只在帧内拉高。复制计数器只应该在 RX_DV 拉高期间计数帧结束要立即清零否则下一帧的对齐会继承上一帧的计数相位。4. 控制信息交换tx_config_Reg 位级约定与 3.4ms 链路更新4.1 控制字位定义SGMII 没有用 802.3z Clause 37 的 ability advertisement 传速率信息而是直接把控制信息塞进 tx_config_Reg[15:0]。这个寄存器在自协商期间由 PHY 发给 MACMAC 收到后回 ACK。位定义如下位方向定义15PHY → MACLink1 链路 up0 down14MAC → PHY自协商 ACK13保留012PHY → MACDuplex1 全双工0 半双工11:10PHY → MACSpeed00 10M01 100M10 1000M11 保留9:0保留0注意 bit 14 的方向。PHY 发给 MAC 的控制字里bit 14 是 0MAC 收到并解码完链路信息后在自己的 tx_config_Reg 里把 bit 14 拉高回传给 PHYPHY 收到这个 ACK 才算完成一次链路状态更新。V1.4 把 bit 0 从 0 改成 1是确保自协商流程能正常启动的修复你在看老版本代码时如果发现控制字 bit 0 是 0可以直接判定为历史遗留问题。4.2 链路状态更新的完整握手当 PHY 检测到链路状态变化比如插拔、速率协商结果变化会启动自协商过程把自己的发送块从数据模式切到配置模式然后把更新后的 tx_config_Reg[15:0] 连续发出去。MAC 接收端解码出控制字后启动自己的自协商状态机同时发送块回 ACKbit 14 拉高。PHY 收到 ACK 后退出配置模式回到正常数据流程。这个握手的时序敏感点有两个。一是 PHY 的配置模式和正常数据模式切换会打断 8B/10B 流PCS 同步块必须能容忍这种切换。二是 MAC 收到控制字后回 ACK 的延迟不能太长否则 PHY 侧状态机可能会超时退出。实际调试时建议在 PHY 侧抓配置码组是否持续发送在 MAC 侧抓 ACK 是否及时拉高。4.3 link_timer 参数与 3.4ms 更新延迟规范特意把自协商内部的 link_timer 从 802.3z 默认的 10 ms 改成了 1.6 ms。这直接影响链路状态更新的速度期望延迟是 3.4 ms计算方式是 2 个 link_timer 周期加一次 ACK 过程。10 ms 对用户感知不明显但对交换机这类需要快速收敛拓扑的设备来说1.6 ms 是必须的。这里有一个容易被忽略的约束如果 MAC 侧自协商状态机是从别的 IP 核搬过来的内部 link_timer 常数很可能没改。10M/100M 模式下链路更新一次要 23.4 ms 以上表现就是插拔网线后要等好久才通。排查方法很简单测一下从 PHY 检测到 link 变化到 MAC 侧速率寄存器更新的间隔如果明显大于 3.4 ms十有八九是 link_timer 还停留在 10 ms。常见做法是直接把这个常数改成 1.6 ms同时确认两端的 ACK 处理不引入额外等待。4.4 速率信息如何参与接收采样MAC 侧收到控制字里的 Speed 位后把它传给 MAC Receive Rate Adaptation 块决定 SAMPLE_EN 的采样间距。这个信息是异步到达的链路运行时 PHY 突然协商出新的速率MAC 必须在帧边界完成切换。切换时机如果落在帧中间会导致半帧采样错乱。标准做法是等当前 RX_DV 拉低后再切换采样间距并在切换后的第一帧重新建立采样对齐。5. 电气边界与避坑LVDS 参数、时序预算和四个翻车点5.1 LVDS DC 参数速览SGMII 的电气基准是 IEEE 1596.3-1996但部分参数为 1.25 Gbaud 做了调整。负载电阻 100 Ω ±1%。几个关键 DC 参数参数最小值最大值单位Voh约 1.5—VVol—约 0.9VVod差分摆幅150400mVVos输出共模10751325mVRo单端输出阻抗40140ΩΔVod0/1 间变化—25mVΔVos0/1 间变化—25mVSGMII 采用的 DC 参数介于通用 LVDS 和低摆幅 LVDS 之间取的是两者中更宽松的组合。数据线和时钟线都是 DC 平衡的8B/10B 编码保证所以如果设计满足 AC 参数但 DC 共模不满足允许做 AC 耦合。这是规范的明确表述意味着 AC 耦合是官方认可的做法但前提是两端的 PCS 跑的是 8B/10B不能随便拿任意的直流不平衡码流硬耦合。5.2 时钟与数据的 90 度相位约束发送端 DDR 电路里数据与时钟的相位差是 90 度如图 5、图 6 所示。625 MHz DDR 时钟下每个时钟周期 1.6 ns数据位宽 800 ps90 度相位差正好把采样点放在数据眼的中心附近。接收端既可以在时钟上升沿和下降沿都采样也可以自行从数据流恢复时钟但无论哪种做法发送端都必须照常提供时钟。实测时最常遇到的问题是相位偏离。如果 PCB 上 RXCLK 比 RX 长了或者短了超过 100 ps采样点就可能滑出数据眼。1.25 G 的 bit time 只有 800 psDDR 双沿采样相当于每个沿只有 800 ps 的数据有效窗口Tclock2q 的 min/max 都要算进去。规范给的 timing budget 表是参考性的精确分配由实现决定但90 度相位必须保证这件事是硬性的。5.3 避坑记录四个亲身踩过的坑第一个坑帧首前导字节变成 9 个被采样逻辑当错帧丢弃。现象是 100M 模式下偶发丢包抓包看到 MAC 收到的帧前导只有 6 个 0x55。原因就是 802.3z PCS 吞掉第一个前导字节PHY 明明发了 55 55 55 ... D5到 MAC 恢复出来少了一个。解决方式是不要把前导数量当成校验条件按规范只要求至少两个 0x55 加一个 0xD5。第二个坑SAMPLE_EN 用 RX_DV 上升沿对齐100M 下隔几个帧就采样错位。现象是解出来的数据偶发变成重复字节或者漏字节链路层 CRC 全错。原因就是采样无固定边界必须从 /S/ 之后开始计数。解决方式是把计数器清零条件绑定在 SFD 检测上而不是 RX_DV 边沿上。第三个坑链路插拔后 10M 模式要等 20 多毫秒才通。现象是 PHY link 早就 upMAC 侧速率寄存器迟迟不更新。原因是 MAC 里的自协商 link_timer 用了 802.3z 默认的 10 ms 常数。解决方式是改成 SGMII 规定的 1.6 ms并确认 3.4 ms 的期望延迟符合你的系统收敛预算。第四个坑全双工模式下帧尾出现 RX_ER老终端直接丢帧。现象是新交换机对接老设备每次长帧传输后物理层报错。原因是 PCS 接收状态机在帧结束时会产生 RX_ER 信号某些老终端在帧结束后第一个时钟看到 RX_ER 就丢弃整帧。解决方式是老老实实按 V1.8 在 PHY 发送路径加 TX_ER 抑制 shim全双工、TX_EN 未拉高时直接把 TX_ER 清零。这块逻辑很小但漏掉了它你的设备对上老交换机就会不定时翻车。第五个坑附赠AC 耦合电容选型不合适导致低频游标漂移。现象是 AC 耦合后 10M 模式工作不稳定1000M 正常。原因是 10M 模式帧拉长后同一电平持续时间长耦合电容太小会引入基线漂移。解决方式是电容取 0.1 µF 以上的陶瓷电容并确认接收端恢复时钟电路能容忍低频分量。6. 从规范到 RTL一个用于验证速率适配的字节间隔计数器规范读完最该先落地的一件事不是写完整 PCS而是先验证你拿到的 PHY/MAC 通路是否真的按规范做了速率适配。我常用的验证技巧是写一个字节间隔计数器统计 SGMII 解串后恢复出的 GMII 数据流里相邻不同数据字节之间间隔了多少个 125 MHz 时钟周期。// 速率适配验证计数器检测 RXD 字节重复间隔 module rate_adapt_checker ( input logic clk_125m, input logic rst_n, input logic rx_dv, // 恢复出的 RX_DV input logic [7:0] rxd, // 恢复出的 RXD output logic [7:0] repeat_cnt, // 当前字节复制次数 output logic cnt_valid // 数据变化那一刻拉高一个周期 ); logic [7:0] rxd_last; logic [7:0] cnt; logic in_frame; always_ff (posedge clk_125m or negedge rst_n) begin if (!rst_n) begin cnt 8d0; repeat_cnt 8d0; cnt_valid 1b0; in_frame 1b0; rxd_last 8d0; end else begin cnt_valid 1b0; if (rx_dv) begin // 检测到 SFD进入帧并开始计数 if (rxd 8hD5) begin in_frame 1b1; cnt 8d1; rxd_last rxd; end else if (in_frame) begin if (rxd rxd_last) begin // 相同字节连续出现复制计数 1 cnt cnt 8d1; end else begin // 字节变化输出前一个字节的复制次数 repeat_cnt cnt; cnt_valid 1b1; cnt 8d1; rxd_last rxd; end end end else begin // RX_DV 拉低帧结束清零所有状态 in_frame 1b0; cnt 8d0; rxd_last 8d0; end end end endmodule逻辑说明这个模块在 RX_DV 拉高期间检测 SFD0xD5进入帧后开始统计相邻数据字节的重复次数。cnt_valid 拉高时读 repeat_cnt得到的就是上一个字节被复制的次数。1000M 模式下 repeat_cnt 应该是 1100M 下应该是 1010M 下应该是 100。帧首第一个数据字节可能出现 9 或 99这是规范允许的不要当异常处理。参数说明模块工作在 125 MHz 时钟域直接挂在 PCS 接收状态机输出端。使用时可以通过串口打印 repeat_cnt也可以在逻辑分析仪上抓 cnt_valid 脉冲。如果 100M 模式下重复次数稳定为 10说明 PHY/MAC 的速率适配逻辑工作正常如果始终是 1说明适配块没生效问题在 PHY Transmit Rate Adaptation 或 MAC Receive Rate Adaptation 的速率配置没有正确传递。从那以后我每次换一块新网卡或者新 PHY都会先跑一遍这个计数器确认三种速率下的重复次数符合预期再开始调协议栈。一个 1.25 Gbaud 的接口只要采样对齐错一拍后面的 CRC 错误全是歪的与其在海量日志里猜不如直接在 RTL 层把复制次数这个数抓出来。希望帮到你。本文还有配套的精品资源点击获取