PCIe SerDes 全流程实战
数字部分——MAC-Lane Deskew
本项目聚焦于高速串行通信本身。PCIe 作为广泛应用的高速串行通信协议,其历史悠久,协议栈层次多、设计复杂;Synopsys IP 更是在工业级别上对 PCIe 协议做了完整实现。
因此,本文 不 针对数字逻辑的每一个细节展开说明;若需深入,可结合 SystemVerilog 代码与波形自行学习。
个人经验
- 由于 SerDes 缺乏统一时钟,多条 Lane 之间需执行 Lane Deskew。
- 为降低 FPGA 的时序、综合及调试难度,本项目仅采用一条 Lane。
以下内容为O3-Pro对system verilog代码和标准文档的深度总结
一、引子:为什么 Lane‑to‑Lane Deskew 是 PCIe 多通道的「生命线」
在 PCI Express(以下简称 PCIe)体系内,同一个 Link 里的所有通道(Lane)必须「像整齐的士兵」一样,以几乎同步的时间关系把比特送到接收端。规范在 §4.2.4.11 中明确提出:
“The Receiver must compensate for the allowable skew between all Lanes within a multi‑Lane Link … before delivering the data and control to the Data Link Layer.”
对于 2.5 GT/s(Gen1)速度,接收端必须能吸收 20 ns 的最大通道间偏斜(skew)——相当于 80 Byte 的物理传输时间。超过这个限度,数据流就在层间错位,后面的 DLL/TLP 切分和校验都会出错。
而在实际硬件里,**通道间去偏斜(Lane‑to‑Lane Deskew)**并不是“简单地等待最慢的那条线”,而要综合考虑:
- 分层编码(8b/10b vs. 128b/130b)带来的对齐符号;
- LTSSM 状态(Configuration / Recovery / L0s);
- Retimer 对 SKP Ordered Set 的插入/删除;
- 可选特性(SRIS、Loopback、Lane Reversal)。
下面我们以 Synopsys® DWC_pcie_ctl 5.60a 为例,通过阅读 ku5p_rmlh_deskew 及其子模块源码,结合规范文字,解析一个工业级 RTL 如何实现这一过程,并进一步说明 多通道数据合并(aggregation) 的实现细节。
二、系统级视角:从 PHY 到 MAC 的 Deskew‑Pipeline
整体数据流可以用一张“七级流水”示意图来理解(由上至下是 RX 方向):
# | 层级/模块 | 主要任务 | 相关文件 |
---|---|---|---|
1 | PIPE PHY | 8b/10b 或 128b/130b 解码、位级对齐 | – |
2 | ku5p_rmlh_pipe |
把 每 Lane×NB Bytes 的 PHY 总线转成内部总线,检测码错/色散错 | …/rmlh.sv |
3 | ku5p_scramble |
解扰 & 处理 Lane Flip | …/scramble.sv |
4 | ku5p_rmlh_deskew |
通道级 FIFO + 对齐判决,输出 已消偏齐的多 Lane 数据 | …/rmlh_deskew.sv |
5 | ku5p_rmlh_pkt_finder |
把多 Lane Stream 重排&拼宽成 NW × 32 b 数据面,寻找 STP/SDP/END | …/rmlh_pkt_finder.sv |
6 | RDLH | 组包、CRC 校验、ACK/NAK | – |
7 | 上层(DL/DMA) | – | – |
本教程聚焦第 4~5 级:Deskew FIFO 与 多 Lane 拼宽。
三、基于规范的 Deskew 原理回顾
“An unambiguous Lane‑to‑Lane de‑skew mechanism may use the COM Symbol of a received TS1 or TS2 Ordered Set, … or the COM Symbol of the first received SKP Ordered Set after an FTS sequence.” — PCIe Base Spec r6.1 §4.2.4.11
关键信息:
- 对齐锚点(Alignment Marker)
- Gen1/2:TS1/TS2、EIEOS、SKP(带 COM)。
- Gen3/4/5:SDS、SKP、Electrical‑Idle Exit。
- 去偏斜时机
- LTSSM 的 Configuration、Recovery、L0s 均须执行。
- 最大可消偏窗口
L_RX‑SKEW
:20 ns (Gen1);随后随速率放宽,但由 SKP 注入周期保证。
四、源码深度剖析——ku5p_rmlh_deskew
4.1 模块入口
ku5p_rmlh_deskew #(.INST(INST)) u_rmlh_deskew (
.core_clk (core_clk),
.deskew_lanes_active (deskew_lanes_active), // 哪些 Lane 需要参与 Deskew
.smlh_do_deskew (smlh_do_deskew), // LTSSM 控制:何时允许 Deskew
.rxdata_i (descrambled_rxdata), // 各 Lane 已解扰的字节流
...
);
smlh_do_deskew
由 Sequence Finder 根据 TS1→TS2 及 SKP 检测触发(后文 §5 说明)。
4.2 总线宽度与 FIFO 深度
parameter NB = `ku5p_macro_CX_NB; // 每周期的 Byte 数
parameter DEPTH= `ku5p_macro_CX_DESKEW_DEPTH; // 典型 9 ~ 17 Bytes
- NB 按 Gen 不同可为 1/2/4/8;
- DEPTH 至少满足
L_RX‑SKEW
/ (Byte 周期),Gen1 下取 20 ns / 4 ns ≈ 5 Byte,Synopsys 默认保守设 9 Byte+; - FIFO 数目 = 活跃 Lane 数,所有 Lane 共用同一卸载指令
unload
,保证“跨 Lane 同步 pop”。
4.3 锚点检测与 Deskew 使能
- TS 跟踪状态机 (
ts_state
)
IDLE → TS1_RCVD → TS2_RCVD → SUCCESS - SKP & Idle‑Data 监视
assign skp_lock_point = ... & int_rxdata_dv & ( rxdata_skprm[0] ? 1'b1 : prev_com_reg & ~prev_skprm_reg & rxdata_skip[0] );
- Deskew Enable
assign deskew_enable = look_for_alignment & (ts_do_deskew | ts2_lid_do_deskew | skp_lid_do_deskew | fts_skp_do_deskew | skp_do_deskew);
deskew_enable
由 0→1,就开始对各 Lane FIFO 进行“齐头 pop”,直到deskew_rxdata_dv_i
对所有 Lane 均为 1,进而拉高deskew_complete
。
4.4 对齐错误与回退
deskew_alignment_err
同时监测- SKP 在各 Lane 上不同行位置(
valid_skp_n
); - FIFO 溢出 (
deskew_overflow
); - 对齐后又观察到 EIOS(Idle Ordered Set),说明 Link 进入 L0s / Recovery,应重新 Deskew。
- SKP 在各 Lane 上不同行位置(
- 一旦出错,
deskew_complete
拉低,等待 LTSSM 发起新一次smlh_do_deskew
。
4.5 Gen1/2 Deskew Bypass
assign rmlh_deskew_bypass =
(`ku5p_macro_CX_DESKEW_DISABLE) ? 1'b1 : cfg_deskew_disable;
- 对 Gen1/2 可让 PHY 直接完成 Deskew,此时 MAC 层 FIFO 旁路,信号路径短、延时小。
- 但
smseq_fts_skp_do_deskew
/deskew_rxdata_flush_gen12
仍会产生,以便 pkt_finder 能刷新内部缓冲。
五、对齐锚点的“探测器”——ku5p_smlh_seq_finder
seq_finder
是 Deskew 的「前哨」,它负责在 每个 Lane 里打标签,并累计「持续收到 TS 的次数」,主要输出包括:
信号 | 描述 |
---|---|
smseq_ts1_rcvd_pulse / smseq_ts2_rcvd_pulse |
本周期检测到带 COM 的 TS1/TS2 |
smseq_in_skp |
每 Byte 是否为 SKP |
smseq_fts_skp_do_deskew |
在 Rx.L0s 场景下,检测到 FTS ➔ SKP 序列,用来触发 deskew |
smseq_ts_rcvd_pcnt |
某 Lane 上连续接收到 相同 TS 的计数,达到 16 便满足规范“Persistently Transmitted”要求 |
在 rmlh_deskew.v
中:
.smlh_do_deskew ( |smseq_ts1_rcvd_pulse_bus | |smseq_ts2_rcvd_pulse_bus | ...)
即:当所有 Lane 都观测到锚点后,统一发起 Deskew。
六、把多 Lane 拼成「并行高速公路」——ku5p_rmlh_pkt_finder
Deskew 完成后,各 Lane 字节流仍以“交错”顺序进入 MAC。pkt_finder
负责将其重排为 按字(DWORD)对齐的 128 b 总线:
- 符号重排
lane_order_byte(data_in, link_mode)
link_mode
(x1/2/4/8/16)把 Lane0 Byte0 ➔ lane0.d[7:0],Lane1 Byte0 ➔ lane0.d[15:8] … 形成升序 Lane。 - 数据宽度适配
当active_nb
<NB
时(Gen1/2 x1/x2),需要把低速字节“填平”到 32 b 对齐;辅助变量sym_cnt
记录已经累积的 Byte 数。 - STP/SDP/END/EBD 识别
stps = compare_bytes(rx_data, rx_datak, 8'hFB); // STP = K28.5 / 0xFB
dllp_start
/tlp_start
等信号立即标记新包开始。 - 错误插桩
Code/Disparity Error、EOF 缺失、对准偏移 等都会置位pkt_err
,供 RDLH 作重放或报告。
七、实战经验:调试 Deskew / Aggregation 的七条锦囊
# | 现象 | 可能原因 | 定位要点 |
---|---|---|---|
1 | deskew_alignment_err 反复出现,且 deskew_complete 迟迟拉不上 |
对端发送 Back‑to‑Back SKP,本端检测逻辑未区分 Standard vs Control SKP(见规范 §4.2.4.11 Implementation Note) | 抓 COM+SKP 的波形,确认 skp_vec* 是否同步 |
2 | x8 Link 在 Gen3 正常,升到 Gen4 后偶发 FCT 报错 | FIFO 深度不足;16 GT/s 的 L_RX‑SKEW ≥ 40 ns,需要更大 DEPTH |
查 ku5p_macro_CX_DESKEW_DEPTH 是否 ≥ 17 |
3 | smseq_ts_rcvd_pcnt 从未到 16,LTSSM 卡在 Recovery.RcvCfg |
对端 TS1 与 TS2 的 LaneNum/LinkNum 字段不一致 |
打印 smseq_ts_info [LaneNum],检查编码 |
4 | 单 Lane 测试 OK,多 Lane 嵌线出现 LinkNum mismatch | 上板布线跨了交叉(Lane Reversal 需双方都支持) | 观察 lane_flip_ctrl ,确保 TX/RX 同时 reverse |
5 | Loopback.Master 模式 Deskew 不完成 | 覆盖配置 cfg_ts2_lid_deskew==0 ,依赖 SKP 检测 |
确认 skp_do_deskew 分支生效 |
6 | 仅在 L0s 唤醒时报 EIOS error | 需要允许 fts_skp_do_deskew 作为锚点 |
看 smseq_fts_skp_do_deskew 是否 16 连续检测 |
7 | Gen1/2 下空闲时 deskew_rxdata_flush_gen12 一直为 1 |
说明 smlh_do_deskew 未取消;通常是 LTSSM 配置流 |
检查 LTSSM 指令发送时机及 ltssm_clear |
八、小结与展望
- Lane‑to‑Lane Deskew 是保证多通道并行链路「逻辑同步」的关键;
- Synopsys MAC 采用 按 Lane FIFO + 锚点对齐 方式,完全遵守规范列举的五类锚点,且能在 Gen1~Gen5 间自适应;
- 多 Lane 合并 通过对齐后的字节重排,再以 NW×32 b 数据总线喂入 Packet Finder,确保 DLL/TLP 可以无感地处理宽链路;
- 设计者可通过
deskew_alignment_err
,smseq_ts_rcvd_pcnt
,pkt_err
等信号进行系统级监控与调优。
对更多高速串行特性(如 L0p/L1 ASPM、SR‑IS、Retimer Pipelines)的软硬协同实现,可在后续教程继续展开。