3. SGMII 链路自动协商:一言不合就降速?

自动协商这个词,做以太网的工程师没有不熟的。但 SGMII 的自动协商和咱们平常说的千兆电口自动协商还真不太一样。它不是在链路上发脉冲来协商,而是通过一种固定的码流,在 SerDes 链路建好之后,快速交换双方的能力。

说白了,SGMII 的自动协商是个“假协商”。它不负责决定谁做 Master 谁做 Slave,也不负责训练均衡器。它的任务只有一个:告诉对端——我能跑多快,我想用什么模式跑。

3.1 协商过程:分两步走

我记得刚开始调 SGMII 时,总觉得芯片上电后应该自动就通。结果示波器一抓,SerDes 链路锁定了,数据也在跑,但网络就是不通。后来才明白,SGMII 的自动协商分两个阶段:

  1. SerDes 链路建链:物理层先搞定。RX 检测到信号,CDR 锁定,同步头对齐。这时候链路层的“管道”是通的。
  2. 能力通告与确认:双方通过 /C/ 码(Configuration码流)互相发“我能干啥”。这个过程非常快,通常几百微秒就结束了。

你想想看,第二步才是决定咱们最终用什么速度跑的关键。如果第二步没走完,哪怕 SerDes 信号再漂亮,上层协议也收不到数据包。

我个人的习惯: 调 SGMII 时,不要一上来就盯着眼图看。先用 IP 核的寄存器确认“链路协商完成位”有没有拉高。这个位没拉高,后面所有时序分析都是白费。

3.2 能力通告:咱们都在报什么?

SGMII 的能力通告是通过 /C/ 码来传递的。这个 /C/ 码可不是随便发的,它有自己的格式。简单说,它包含三个关键字段:

字段 位置 说明
Link Status Bit 15 1 = 链路已建立,0 = 链路断开
Speed Bits [14:13] 10M: 00,100M: 01,1000M: 10,Reserved: 11
Duplex Bit 12 1 = 全双工,0 = 半双工

看到没?就这么简单。它不需要像 1000BASE-T 电口那样去协商 Master/Slave 时钟,也不需要交换繁杂的能力向量表。SGMII 的协商字段就那么几个 bit。

我在项目中遇到过一种奇怪的现象:FPGA 和交换芯片对接,明明代码里配置的是千兆全双工,但协商结果出来却是百兆半双工。抓了 /C/ 码一看,原来是交换芯片那边收到的 Link Status bit 一直为 0。说白了,是 SerDes 链路上的同步头有问题,导致 /C/ 码被丢弃了。

3.3 速度/双工模式选择:谁说了算?

这个问题的答案其实挺直接的:在 SGMII 中,通常是 PHY 或者 MAC 的远端决定了速度和双工。你作为本地端,只需要把“我的能力”通过 /C/ 码发过去,并且接受对端发回来的“确认”。

为什么这样设计?

嗯,这里要搞清楚。SGMII 的典型应用是 MAC 到 PHY 的连接,或者 FPGA 到交换芯片的连接。如果是 MAC 到 PHY,PHY 才是真正和网线打交道的那一端。它知道对端是千兆还是百兆,是全双工还是半双工。PHY 通过 /C/ 码把这个结果告诉 MAC。MAC 就老老实实跟着改自己的速率和双工。

如果是 FPGA 到交换芯片,情况类似。交换芯片的 SerDes 端口通常配置为“自适应”模式,它会根据远端 FPGA 送出的 /C/ 码来动态调整自己的内部通道。反过来,FPGA 也可以设置成“强制模式”,不管交换芯片发回什么 /C/ 码,我都按我设定的速率跑。

我曾经踩过这个坑: 有一次 FPGA 和交换芯片对接,FPGA 设置为强制千兆全双工,但交换芯片那边的 SGMII 端口配置错了,变成了自适应。结果是交换芯片认为 FPGA 发送的是“无效的能力通告”,于是它自己降级到了 100M。两边各说各话,一个发千兆的包,一个按百兆收。最后链路丢包惨不忍睹。解决的办法很简单——两边都统一用强制模式,或者两边都用自适应。

所以你需要记住一个原则:

  • 强制模式:只管发 /C/ 码,不管回码。本地速度固定。
  • 自适应模式:发自己的能力通告,同时解析对端回码。速度由最后握手结果决定。

3.4 完整协商流程(一张流程图说清楚)

下面这个图,我建议大家收藏。每次调 SGMII 协商卡壳时,对照这张图排查,能省下不少时间。

SGMII 链路自动协商核心流程 1. 上电 / 复位 2. SerDes 建链(RX锁定) 3. 发送能力通告 /C/ 码 4. 等待对端 /C/ 码确认 5. 确定速度 & 双工模式 强制模式旁路 强制模式下: 不等待对端确认 直接进入第5步

你可以看到,图中右侧有一个“强制模式旁路”。这就是我前面提到的——如果你对自己的配置有信心,可以选择跳过第4步等待,直接进入模式选择。但大部分时候,我建议你还是老老实实走完整个流程。省这一步,后面排错可能要花十倍的时间。

3.5 一些小窍门

  • 抓 /C/ 码:如果你的 FPGA 有内部逻辑分析仪(比如 Vivado 的 ILA),直接把 /C/ 码接收逻辑的寄存器拉出来看。看看对端发来的 Speed[1:0] 和 Duplex bit 是不是你预期的那样。一目了然。
  • 注意 Link Timer:SGMII 协议规定,自动协商超时时间通常是 1.6ms 左右。如果超过这个时间还没收到有效 /C/ 码,就应该进入“链路断开”状态。我在项目中遇到过因为 SerDes 链路抖动导致 Timer 反复超时的案例,最后发现是电源纹波太大。
  • 不要在同一个端口上同时使能 SGMII 和 1000BASE-X:很多 SerDes IP 核支持同一个端口跑不同的协议。但如果你把两个协议都使能了,自动协商就会乱套。我见过有人犯这个低级错误,查了三天。

核心要点总结:

  1. SGMII 自动协商通过 /C/ 码传递速度(10M/100M/1000M)和双工(半/全)。
  2. 协商过程依赖 SerDes 建链,建链失败则协商失败。
  3. 强制模式和自适应模式的区别在于是否等待对端确认。
  4. 排查协商问题,第一步看寄存器,第二步抓 /C/ 码,第三步查电源。