PCIe SerDes 全流程实战
数字部分——PCS-8b/10b 编码
本项目聚焦于高速串行通信本身。PCIe 作为广泛应用的高速串行通信协议,其历史悠久,协议栈层次多、设计复杂;Synopsys IP 更是在工业级别上对 PCIe 协议做了完整实现。
因此,本文 不 针对数字逻辑的每一个细节展开说明;若需深入,可结合 SystemVerilog 代码与波形自行学习。
个人经验
-
PCS 层的位置 PCS 作为 PCIe 架构的一环,向上通过 PIPE 接口连接数字 MAC 层,向下衔接 PMA SerDes 模拟层。
-
范围与排除 本项目仅关注高速串行通信核心逻辑,不涵盖低功耗管理、状态监控等附加功能。
-
8b/10b 编码 8b/10b 是 PCS 的核心职能之一:
- 向下满足 SerDes 对数据均衡与直流平衡的要求;
- 编码后数据经 PMA Serializer/MUX 及 TX Driver 发出;
- 接收路径先经 CDR + Deserializer,再做 10b/8b 解码,恢复数据信息与控制符。
-
128b/130b 与 8b/10b 的差异 两者在实现细节上不同,但目标一致——保障信号完整性与协议控制。
-
调试提示 项目中采用 PCIe IP 的 Generic PHY 与 Xilinx PHY。两者在若干接口信号上存在细微差别,务必详查官方文档,尤其关注 时钟与复位 的处理。
以下内容为O3-Pro对system verilog代码和标准文档的深度总结
一、缘起:为什么 PCI Express 要用 8b/10b 与 128b/130b 两种编码?
“PCI Express uses 8 b/10 b encoding when the data rate is 2.5 GT/s or 5.0 GT/s.
For data rates greater than or equal to 8 GT/s it uses a per‑Lane code along with physical‑layer encapsulation.” — PCI Express Base Specification Rev 4.0, §4.2
1.1 物理层设计目标
- 直流平衡 (DC‑Balance) – 避免长时间 0 或 1,保证 AC‑耦合链路不漂移。
- 足够的转移密度 (Transition Density) – 让接收端 CDR 能从数据里恢复时钟。
- 错误检测/控制字符 (K‑Codes) – 帧定界、链路管理。
- 编码效率 – 线路频率越高,额外开销越要小。
1.2 8b/10b 与 128b/130b 的取舍
项目 | 8b/10b | 128b/130b |
---|---|---|
每 8 bit 负载占用线路位 | 10 位 (效率 80 %) | ≈8.125 位 (效率 98.46 %) |
DC‑Balance | 通过“Running Disparity” 完全保证 | 依赖 Scrambler 和 2‑bit Sync Header |
控制字符 | 12 个 K‑codes,直接映射 | 通过 Sync Header+Framing Token |
最大工作速率 | 5 GT/s 之后开销过大 | 设计用于 8 GT/s 及更高 |
5 GT/s 以前,80 % 的效率足以覆盖时钟余量;进入 Gen3(8 GT/s)后,20 % 的冗余无法再忍受,于是引入只有 1.54 % 开销的 128b/130b。
二、8b/10b 编码/译码机制深入
2.1 字符/符号映射
标准将 8 bit 拆成 [ABC DE](5 bit)+[FGH](3 bit),分别查 5b/6b、3b/4b 表得到 10 bit:
// pipe_8b10b.v 片段:生成 6b 部分
wire [5:0] data_10b_abcdei_pre = {data_8b_abcde, 1'b0};
wire [5:0] data_10b_abcdei = data_10b_abcdei_pre ^ {6{compl_6b}};
- Running Disparity (RD):
compl_6b
、compl_4b
依赖当前 RD,确保输出 ‘+1’ 与 ‘‑1’ 数量接近平衡。 - 控制符 Kx.y:例如 K28.5 (001111 1010) 被硬编码检测:
wire datak_out = (!c_in && !d_in && !e_in && !i_in) // …K-code 判定
2.2 接收端自动对齐与逢错
pipe_rx_align_8b10b.v
里的 FSM(LOSS_OF_SYNC → SYNC_ACQ_n)利用 K28.5 COM
逗号字:
wire com_good_b = (data_full[19:10] == `DWC_PCIE4_X4NS_KCODE_10B_COM);
若检测到错位逗号 (com_bad
),就触发 ana_clk_shift
命令模拟移位复位,直到 “4 个好逗号 + 0 个坏逗号” 为止。
这正体现了 高速串行通信“自恢复” 能力:物理层可无额外引脚地重新捕获字边界。
三、128b/130b——向 16 GHz 迈进
3.1 Block 结构
每 130 bit Block = 2‑bit Sync Header + 128‑bit Payload
Sync Header | 含义 | Scramble | 备注 |
---|---|---|---|
10 |
Data Block | Scrambled | 正常数据 |
01 |
Ordered‑Set Block | 部分或全部 Bypass | SKP/EIEOS/TS 等 |
// pipe_tx_sync_enc.v 片段:16/32‑bit PIPE 数据与 Sync Header 拼接
casex({startblock_l,startblock_h,hdr4b})
4'b1000: data_b = {data_in[31:0], hdr_l[1:0]}; // 2‑bit Header
3.2 Scrambler
“The LFSR uses polynomial X^23 + X^21 + X^16 + X^8 + X^5 + X^2 + 1 …
All 16 symbols of a Data Block are scrambled.” — Spec §4.2.2.4
- 目的:① 打散模式,② 间接维持 DC‑Balance,③ 提供低级错误掩蔽。
dwc_pcie4_upcs_x4_ns_pipe_tx_sync_enc.v
中,Scrambler 输出与 128 bit payload 做异或。
3.3 Framing Token
128b/130b 不再有 K‑codes;物理层在 Data Stream 里插入 2‑/4‑symbol Token,例如:
Token | 长度(符号) | 作用 |
---|---|---|
IDL |
1 | 逻辑空闲 |
SDP |
2 | DLLP 起始 |
STP |
4 | TLP 起始 + 12‑bit Seq# |
EDS |
4 | Data Stream 结束 |
EDB |
4 | Nullified TLP 结束 |
编码器 pipe_tx_sync_enc
在 startblock_l/h
处把 Header 与 Payload 交错输出;解码 FSM 在 pipe_rx_sync_align
里先根据 EIEOS
找到 Block 边界,再进入 STP/SDP/EDS
解析。
四、代码级视角:Synopsys PCS 如何落地
注:以下文件路径对应 Synopsys DWC PCIe Gen4 PHY PCS RTL 3.00a
模块 | 职责 | 关键接口 |
---|---|---|
dwc_pcie4_upcs_x4_ns_pipe_8b10b.v |
8→10 b 编码 | data_in[7:0] → data_out[9:0] , disp_out |
dwc_pcie4_upcs_x4_ns_pipe_10b8b.v |
10→8 b 解码 | disp_err / code_err 上报 |
dwc_pcie4_upcs_x4_ns_pipe_rx_align_8b10b.v |
接收端字对齐 | com_det[] 、ana_clk_shift |
dwc_pcie4_upcs_x4_ns_pipe_tx_sync_enc.v |
128b/130b Block & Scramble | startblock_l/h , hdr_l/h |
dwc_pcie4_upcs_x4_ns_pipe_rx_sync_align.v |
128b/130b Block 对齐 | sob_det , sym_match , blk_loc_vld |
4.1 编码路径(Tx)
-
PIPE Tx Gasket (
lane_tx
)- Gen1/2: 32‑bit PIPE → 8b/10b encoder。
- Gen3/4: 32‑bit PIPE → 128b/130b encoder (
tx_sync_enc
),Header 插入。
-
tx_sym_enc
与tx_sync_enc
- 二选一:
lane_mode_8b10b
决定走哪条。 - 8b/10b 支持 OOB (SATA) 与 Bypass。
- 128b/130b 调整
sel_16b_mode
(16/32‑bit) 并串行发送 Sync Header。
- 二选一:
-
tx_data_out
- 把 20‑bit 或 16‑bit PCS 数据重新打包给 PHY,兼容 FPGA/ASIC 宽度差异。
4.2 解码路径(Rx)
-
字对齐
- Gen1/2:
rx_align_8b10b
统计COM
;移位硬件ana_clk_shift
控制模拟抽头。 - Gen3/4:
rx_sync_align
查找 130‑bit 唯一模式EIEOS
+SYNC
,输出blk_loc
给 PCS FIFO。
- Gen1/2:
-
码字解码
- 10b→8b:
pipe_10b8b
分离 6b/4b,计算disp_err
/code_err
通知 LTSSM。 - Scrambler:遇到
SKP
或EIEOS
时 LFSR 不进位,保持两端相同状态。
- 10b→8b:
五、深层机理 & 调试要点
5.1 Disparity 不是简单“奇偶校验”
8b/10b 的 RD 状态机在 每发一个 Symbol 后更新;在 Gen1/2 串扰更高、抖动更大的环境下,它本身就是一维 DC Feedback。
128b/130b 取消 RD,却依赖更高级的 CTLE+DFE 均衡和 前馈预加重,同时将 DC‑Balance 任务交给 Scrambler 和 link‑training EQ。
5.2 “同步头” 两个比特的 4 种合法值
10
= Data01
= OS00/11
= 非法 →pipe_rx_sync_align
检测到后立刻报 Framing Error 并驱动 LTSSM 进入 Recovery。
5.3 调试技巧
- 观察 Running Disparity:在逻辑分析仪中抓取 8b10b 后若 RD 偏移不断累计,说明编码器/decoder 失步或线路损坏。
- Gen3/4:校准 Block Alignment 时,看
blk_loc_vld
是否稳定;若不断抖动,多为信号完整性或EIEOS
链路训练失败。 - SKP Ordered‑Set 周期性出现,可用来推断双方 Tick‑Timer 及滑补(Clock Compensation)策略是否一致。
六、总结与展望
- 8b/10b:高冗余换来简单可靠,仍在 低速 边带和 OOB 场景(SATA、电源管理)中被继续使用。
- 128b/130b:带来接近极限的线路效率,是 PCIe Gen3/4/5/6 的核心;随着 PAM4、FLIT 模式的引入,PCIe 6.0 以后将进一步演变为 FLIT‑based 128b/130b+FEC+Gray‑code Scrambler。