10GBASE-R中的PCS层
IEEE Std 802.3-2022 在 49章,介绍了10GBASE-R的PCS(Physical Coding Sublayer,物理编码子层)64b/66b原理。
下面这几个 10G 以太网物理层变种均使用该同步头:
10GBASE-SR(多模光纤,短距离)
10GBASE-LR(单模光纤,中距离)
10GBASE-ER(单模光纤,长距离)
10GBASE-LRM(老的多模光纤)
10GBASE-KR(背板铜缆,数据中心内部)
10GBASE-T 是 IEEE 802.3 标准中定义的 10 Gbit/s 以太网通过双绞铜缆(即普通网线)传输 的物理层规范,简单说就是“10G 铜缆以太网”。
PCS在Tx方向将用户数据进行加扰,添加同步头后送往PMA,在Rx方向接收PMA的数据,进行同步并去掉同步头,然后解扰恢复出并行数据送给MAC层,数据流向如下:

GEAR BOX可以理解为“变速箱”,用来做速率匹配。因为输入数据是64bit,输出数据为66bit,每隔32clk就会多出一拍数据。
PCS中的数据在PMA中做并串和串并转换,低bit先发送:

前面说到,PCS将用户数据(如XGMII)从32/64bit位宽转换成66bit。为什么是 66 位?因为前 2 位是“同步头”(sync header),后面 64 位是实际负载,所以叫 64B/66B。前 2 位的同步头用于快速锁定边界,这些数据块只在 PCS 内部存在,外面完全看不到(不感知这个同步头),具体怎么转全看 49.2.4 的编码表。这就是为什么 10GBASE-R能做到极低的编码开销(66/64 = 1.03125,仅 3.125% 开销),远比 1000BASE-X 的 8B/10B(25% 开销)高效得多。
1.1 64B/66B编码的作用
64B/66B编码要做到:
编码必须保证比特流里有很多 0↔1 的跳变(high transition density)。
为什么?因为接收端没有单独的时钟线,全靠从数据里自己“抠”出时钟(Clock Data Recovery, CDR)。跳变得少,CDR 就漂移、失锁。
有限连 0/连 1 长度(run-length-limited):
最长连续 0 或 1 不会超过某个值(64B/66B 加上扰码后,最长跑长大概 66 左右),避免基线漂移(DC wander)和电磁干扰问题。
快速同步
每个 66 位块前 2 位的同步头,让接收端能在几百比特之内就找到“块边界在哪里”,这叫 Block Lock。 找到边界之后,后面的解码、解扰、错误检查就全都能对齐了。
编码规则如下图:

一个 66-bit 块 = 连续两个 XGMII 周期的 8 个字符 XGMII 是双 32-bit(4 字节 × 2 路),两个周期正好 8 字节 → 打包成一个 66-bit 块。
8 个字符的编号规则
D0 D1 D2 D3 D4 D5 D6 D7 → 纯数据八字节
C0–C7 → 普通控制字符(比如 Idle、Error)
S0 或 S4 → Start(帧起始),只能出现在第 1 或第 5 个位置(对应 XGMII 的 lane 0)
T0–T7 → Terminate(帧结束),可以出现在任意位置
O0 或 O4 → Ordered_set(比如 /LPI/、/LF/、/RF/),也只能出现在第 1 或第 5 个位置
下标 0~3 属于第一个 XGMII 周期,4~7 属于第二个周期。
块格式只有两大类
同步头 = 01 → 纯数据块:01 + 8 个 D0~D7
同步头 = 10 → 控制块:10 + 8-bit 块类型字段(block type field)+ 若干控制字符/数据混合
XGMII接口66B编码举例:
场景一:纯数据传输 (Data Block)
XGMII 状态: 正在传输一个大文件的中间部分。
输入: 8 个字节全是数据,XGMII 的控制位(TXC)全是 0。
数据内容:11 22 33 44 55 66 77 88 (16进制)
查表: 对应表格第一行 D0 D1 D2 D3 D4 D5 D6 D7。
编码结果:
Sync: 01
Payload: 直接就是 11 22 33 44 55 66 77 88
最终 66B: 01 11 22 33 44 55 66 77 88
场景二:数据包开始 (Start of Packet)
以太网规定,数据包必须从第 0 通道 或第 4 通道 开始。
XGMII 状态: 开始发送一个新包。
输入: 第 1 个字节是 /S/ (Start),后面 7 个字节是前导码/SFD/MAC地址数据。
XGMII 数据: FB 55 55 55 55 55 55 D5 (FB 是 Start 的控制码)
XGMII 控制位: 1 0 0 0 0 0 0 0 (只有第1个字节是控制符)
查表: 找到以S_0 开头的那一行 -> S0 D1 D2 D3 D4 D5 D6 D7。
编码结果:
Sync: 10 (因为有控制符)
Block Type Field: 0x78 (看表格中间那列,对应S_0 行)
Payload: 扔掉S_0 (因为 Type Field 0x78 已经隐含了“第一个字节是 Start”的意思),只保留后面 7 个数据字节。
最终 66B: 10 78 55 55 55 55 55 55 D5
这种机制极其巧妙地把 8 bit 的控制开销压缩到了 2 bit (Sync) + 偶尔出现的 8 bit (Type Field) 中。
不过个人觉得上述的控制码表没那么重要,主要是和XGMII接口配合使用,当我们不关心接口,只把PCS+PMA用来传输数据的时候,我们只需要考虑把数据正确恢复出来即可。给我32个32bit数据,我就恢复出对应的32个32bit数据就完事了,不用考虑XGMII 64bit数据,还有8bit控制符这些。
1.2 Scramble(加扰)
上面介绍PCS提到,编码必须保证比特流里有很多 0↔1 的跳变,保证不出现连续的0或者1,那么在添加同步头之前,还需要进行加扰。

上面这张图体现了同步头和加扰以及原始数据之间的关系:根据原始数据可以确定同步头是01还是10,然后按照低位优先的顺序把数据送入加扰模块,得到输出数据后再添加上同步头,得到完整的66b数据,最后送入Gearbox做速率匹配,保证输出的还是64/32/16bit位宽。
加扰通常使用一个本原多项式,可以用线性反馈移位寄存器(LFSR)实现,通过这个移位寄存器可以将所有非连续0的序列变成具有伪随机特征的序列,PCS里面使用的多项式为:
该过程可以表示如下:

对于不使用FEC的编码,数据加扰之后可以直接再加上同步头,形成66B数据,再经过GearBox变成64/32bit码流输出给PMA,PMA将并行数据转换成串行数据后发送到对端,接收端PMA首先需要进行串并转换。串并转换之后数据并不能直接使用,还需要先做块同步,也就是把数据恢复成发送的原始并行数据。例如PAM发送数据为16个0和16个1交替的串行数据,对端PMA恢复出来的并行数据并不是{16'h0,16'hffff},而是{16'h0,16'hffff,16'h0,16'hffff}这个串行码流中的任意一个连续的32bit数据,但是显然我们后级模块是无法处理这种数据的。

1.3 Block Sync (块同步)
接收端的处理流程如图49-6所示,首先做块同步,这个步骤会去除同步头并将PMA的数据恢复成原始的并行数据,然后对数据进行解扰。其状态机流程如下图所示:

状态机的各个状态含义如下:
图中的信号含义如下:
PCS 接收来自 PMA 的数据流后,首先进入初始化状态并清零计数器,随后开始逐块检测同步头(Sync Header)。若连续 64 个块均检测到有效同步头且无错误,则判定为同步成功,置位 rx_block_lock 信号,进入锁定状态;若在同步建立前累计出现 16 次无效同步头,则判定为失锁,触发滑动(Slip)操作——即丢弃当前对齐位置并重新调整块边界,之后返回初始状态重新尝试同步。一旦已锁定状态下再次频繁检测到无效同步头,也可能触发滑动以恢复同步。如果在锁定下出现一个非法同步头,并不会直接失锁,会重新跳转到TEST_SH,直到超过阈值(这里是16)才会跳转到SLIP 状态。
1.4 Descramble(解扰)
前面使用的扰码是一种自同步扰码,也就是说,经过加扰后的数据,再通过一个完全相同的本原多项式,等待一段时间后会自动恢复成原始未加扰的数据,这个是其本身的性质,可以参考其他文章。解扰的流处理过程如下图所示:

以 IEEE 802.3 常用的 1 + x²⁵ + x⁵⁷ 为例:
扰码多项式:G(x) = 1 + x^{25} + x^{57}
发送端扰码公式:
s(n) = d(n) \oplus s(n - 25) \oplus s(n - 57)其中 d(n) 是原始数据,s(n) 是扰码后输出。
接收端解扰公式:
\hat{d}(n) = r(n) \oplus r(n - 25) \oplus r(n - 57)其中 r(n) 是接收到的数据(理想情况下 r(n)=s(n)),代入后可以得到\hat{d}(n) = {d}(n)。
注意:解扰器只依赖接收到的 r(n),不依赖原始数据或初始状态!这是因为即使接收端 LFSR 初始状态错误,经过最多 N 比特(N = 最大抽头延迟,如 57)后,内部状态会自动“被正确数据覆盖”而收敛到正确状态。
以一个简单的多项式 1+x^3为例:
扰码公式(发送端):
解扰公式(接收端):
假设接收端初始寄存器为 [?, ?, ?](未知),但一旦开始接收 r(0),r(1),r(2),…,从第 3 个比特起:
即使 r(0) 被错误地用于反馈,但从 n=3 开始,所有用于反馈的 r(n−k) 都是真实的扰码输出,因此解扰结果立即正确!即只要连续接收到 N+1 个正确的扰码比特(N 为最大延迟),解扰器就能自动输出正确的原始数据,无需知道初始状态。
总结
本文介绍了IEEE Std 802.3-2022 Clause49的内容,该章节没有对PCS层中的FEC模块做过多描述,事实上当Serdes速率超过10G后,不可避免会出现误码,而上面所提到的加扰又会放大这种错误,因为错1bit,会影响到前后57bit的数据,导致连锁反应。因此还需要额外增加一些纠错手段,能够将少量错误恢复出来,这就是Forward Error Correction (FEC),即前向纠错编码。
评论