PCIe SerDes 全流程实战
数字部分——MAC-LTSSM链路训练
本项目聚焦于高速串行通信本身。PCIe 作为广泛应用的高速串行通信协议,其历史悠久,协议栈层次多、设计复杂;Synopsys IP 更是在工业级别上对 PCIe 协议做了完整实现。
因此,本文 不 针对数字逻辑的每一个细节展开说明;若需深入,可结合 SystemVerilog 代码与波形自行学习。
个人经验
- LTSSM 是 PCIe 协议在物理层的初始化阶段,负责速率协商、均衡协商以及低功耗等功能。
- LTSSM 协商流程较为复杂,Synopsys 实现中 LTSSM 的单个 SystemVerilog 文件超过 3 800 行。
- 复杂性主要来源于以下因素:
- 对 PCI 和 PCIe 的前向兼容与后向兼容需求;
- 通道数量可调(1–16 Lane);
- 需适应高插损与低插损等多种均衡场景;
- 满足桌面端、嵌入式与数据中心等不同应用需求。
- 调试时,应在 PHY 稳定后拉高 LTSSM_enable 信号,以触发链路训练过程。
以下内容为O3-Pro对system verilog代码和标准文档的深度总结
PCI Express Base Specification 4.0 §4.2.4
“The Link Training and Status State‑Machine (LTSSM) is responsible for configuring and initializing the Link, negotiating Link width and data‑rate, managing error recovery, and restarting a Port from low‑power states.”
1 LTSSM在系统中的位置与作用
LTSSM 运行在 Physical Layer / MAC 边界,结合 PIPE‑PHY、Link Layer 以及电源管理模块完成以下关键职能:
目标 | 实现手段 | 本设计中核心信号/代码 |
---|---|---|
检测对端并建立初始链路 | Detect.Active / Polling.Active | phy_mac_rxdetected , cfg_lane_en , S_DETECT_ACT |
协商Lane 数 & Link Width | Configuration.Linkwidth.* | ltssm_lanes_active , S_CFG_LINKWD_START … |
协商数据速率(x1 Gen1→Gen6) | Recovery.Speed / Equalization | mac_phy_rate , current_data_rate , S_RCVRY_SPEED |
建立 位/符号锁 & Lane 去斜 | TS1/TS2 + EIEOS/SDS | rmlh_deskew_complete , deskew_lanes_active |
进入/退出低功耗 (L0s/L1/L2/L3) | L0s、L1/L23 子状态 | pm_smlh_entry_to_l1 , rmlh_rcvd_eidle_set |
错误恢复 | Recovery.RcvrLock / RcvrCfg / Idle | rmlh_deskew_alignment_err , smlh_eidle_inferred |
热复位 / 协议复位 | HotReset.Entry/HotReset | latched_direct_rst , S_HOT_RESET_ENTRY |
环回测试 | Loopback.Entry / Active / Exit | cfg_lpbk_en , 多段 lpbk_entry_state |
理解这些宏观职责后,再看源码及波形就能迅速定位问题。
1.1 LTSSM 速查表
编码 | 状态 | Base Spec 要点(节选) | 代码符号 | 波形验证关键点 |
---|---|---|---|---|
000000 |
Detect.Quiet | 端口上电后保持电平;RX 端处于 Hi‑Z;等待 12 ms | S_DETECT_QUIET |
phy_mac_rxdetected==0 ,timeout_12ms |
000001 |
Detect.Active | 置位 RxDetect/RxStandby;等待 RX[0] 拉高 | S_DETECT_ACT |
int_rxdetect_done 上升 |
000010 |
Polling.Active | 发送 TS1;侦测全宽后转 Configuration | S_POLL_ACTIVE |
xmtbyte_ts1_sent 1024 次统计 |
000100 |
Configuration.Xxx | TS1/TS2 协商宽度/Lane# | S_CFG_* |
link_latched_live_* 组合 |
000111 |
Recovery.RcvrLock | “锁链恢复” —— TS1 训练 | S_RCVRY_LOCK |
TS1 ≥1024 个连续、deskew_complete |
… | … | … | … | … |
2 Synopsys ku5p_smlh_ltssm
模块扫盲
2.1 顶层接口速览
端口 | 方向 | 说明 | 调试要点 |
---|---|---|---|
ltssm[5:0] |
O | 当前状态编码 | 建议在波形中着色以宏观查看迁移路径 |
ltssm_cmd[3:0] |
O | 发送端动作:XMT_IN_EIDLE / SEND_TS1 / … |
与 xmtbyte_*_sent 配合验证 |
current_data_rate[2:0] |
I | 0‑Gen1, 1‑Gen2, 2‑8 GT/s, 3‑16 GT/s, 4‑32 GT/s | 和 mac_phy_rate 一起反映协商结果 |
xmtbyte_ts1_sent / ts2_sent |
I | 单个 Ordered Set 发送完毕脉冲 | 用来统计 1024 TS1、16 TS2 触发迁移 |
rmlh_rcvd_eidle_set |
I | 捕获到 EIOS | L0/L0s/L1/L2 认定关键 |
smlh_lanes_rcving[N‑1:0] |
I | 各 Lane 接收训练序列指示 | Debug 多 Lane 去斜 |
timeout_* |
I | 多颗 1/2/3/10/24 ms 计时器 | 标准严格规定最长等待时间 |
源码的 S_*
状态枚举与规范一一对应,编译时通过编译指令展开;手动对照《表 4‑1 LTSSM states》即可。
2.2 状态总览图
Detect.Quiet ─► Detect.Act ─► Polling.Active ─► Polling.Configuration
▲ │
│ ▼
└── Detect.Wait ◄── Polling.Compliance
...
Cfg.Complete ─► Cfg.Idle ─► L0 ─┬─► L0s (Tx/Rx)
├─► L1 / L2 / L3
├─► Recovery.Lock │
│ ▼
├─► Loopback.Entry → Loopback.Active → Loopback.Exit
└─► HotReset.Entry → HotReset
建议在波形窗口中同时放 ltssm[5:0]
、ltssm_last
、ltssm_cmd
三条总线,一目了然。
3 Detect & Polling —— 从“看见”到“互认”
3.1 Detect.Active
代码片段:
S_DETECT_ACT: begin
if (int_rxdetect_done & all_phy_mac_rxdetected & ~retry_detect)
next_lts_state = S_POLL_ACTIVE;
...
end
-
关键信号
int_rxdetect_done
由 PIPEPHY_STATUS
驱动,确认 Rx‑Detect 完成。
all_phy_mac_rxdetected
= 所有被配置为活动的 Lane 上rxdetected==1
。 -
波形验证
在 FSDB 中把phy_mac_rxdetected
、int_rxdetect_done
拉到一组,可见 Detect.Act 末尾所有选通 Lane 拉高一个比特时间,随后 LTSSM 跳到00_0100
(Polling.Active)——与ltssm
总线值 0x04 对齐。
3.2 Polling.Active —— TS1 洪流
“Ports shall transmit at least 1024 consecutive TS1 Ordered Sets before switching to TS2.” — PCIe 4.0 §4.2.4.1
-
波形观测
xmtbyte_ts1_sent
周期:640 unit = 64 ns;前 80 unit 高电平,低 560,正对应 15.625 MHz TS1 速率。第一段高脉冲 1 026 个 —— 完整满足“≥1024”规范;紧接出现 1.1 µs 静默进入 TS2 阶段(见题给表)。 -
代码联动
xmtbyte_1024_consecutive_ts1_sent =
cfg_fast_link_mode ? (xmtbyte_ts_pcnt>=16)
: (xmtbyte_ts_pcnt>=1024);
...
if (link_latched_live_all_8_ts_plinkn_planen_rcvd && xmtbyte_1024_ts_sent)
next_lts_state = S_POLL_CONFIG;
实测当计数器 xmtbyte_ts_pcnt
达 1024 且所有 Lane 至少收到 8 个 TS(1/2),next_lts_state
将置为 S_POLL_CONFIG
(0x05)。
4 Configuration —— 宽度 & Lane 编号协商
PCIe 4.0 §4.2.4.10 描述协商顺序:Link‑width Start → Accept → Lane‑num Wait → Accept → Complete。
代码与状态命名保持一致:
设计状态 | 规范章节 | 条件 & 信号 |
---|---|---|
S_CFG_LINKWD_START |
Configuration.Linkwidth.Start | 任何 2 个 TS1 linkn/lanen 有效 (link_any_2_ts1_*_rcvd ) |
S_CFG_LINKWD_ACEPT |
Configuration.Linkwidth.Accept | 所有 Lane 均收到匹配 TS1 |
S_CFG_LANENUM_WAIT |
Configuration.Lanenum.Wait | 等待对端用正确 Lane 编号回应 (link_*lanen_rcvd ) |
S_CFG_LANENUM_ACEPT |
Configuration.Lanenum.Accept | 所有 Lane 互认 |
S_CFG_COMPLETE |
Configuration.Complete | 发送 TS2 16 个,Deskew OK |
波形要点
ltssm[5:0]
轨迹依次 0x06 → 0x07 → 0x08 → 0x09 → 0x0A,且deskew_complete
拉高。ltssm_cmd
在 Start/Accept/Wait/Accept 均输出SEND_TS1
,到 Complete 切换SEND_TS2
。
Lane PAD / K23.7 现象
在 x1 训练时,剩余 7 Lane 需发送 K23.7 PAD。代码 / 波形中可见:
ltssm_xk237_4lannum <= ~latchd_smlh_lanes_rcving;
PAD Lane 的 lnknum/lanenum
位被强制置 1(K‑code)。
5 Recovery —— 数据速率协商 & Equalization
5.1 Recovery.Lock –> Recovery.RcvrCfg
进入 S_RCVRY_LOCK
的条件:
- 本端 至少发送 1024 TS1(若
cfg_ext_synch
置 1)。 - 对端 全 Lane 收到 TS1/TS2,且
spd_chg==0
、EC==00b
。
源码验证:
if ( link_latched_live_all_8_ts_linknmtx_lanenmtx_rcvd
&& (cfg_ext_synch ? xmtbyte_1024_consecutive_ts1_sent : 1'b1))
next_lts_state = S_RCVRY_RCVRCFG;
5.2 Recovery.RcvrCfg –> Recovery.Idle
标准要求 DSP 必须先收齐 16 TS2 再进入 Idle;USP 能早点进入。
设计用 link_xmlh_16_ts2_sent_after_1_ts2_rcvd
计数,配合 deskew_complete_i
:
if (link_latched_live_all_8_ts2_linknmtx_lanenmtx_rcvd
&& link_xmlh_16_ts2_sent_after_1_ts2_rcvd && deskew_complete_i)
next_lts_state = S_RCVRY_IDLE;
Equalization (Gen3+)
当对端发送 “Modified TS2 Skip‑EQ / No‑EQ‑Needed” 且 Core 尚未 Link‑up,可利用协议特权跳过 EQ:
link_latched_live_all_8_mod_ts2_skip_eq_*
→int_rcvd_8_ts2_skip_eq
link_latched_live_all_8_mod_ts2_noeq_nd_*
→int_rcvd_8_ts2_noeq_nd
这些布尔在 Idle→L0 前向下层 EQ 模块发指令(int_bypass_gen3_eq
/ gen4_eq
)。
6 进入 L0 —— Deskew、Idle 计数与最终 Link‑Up
“When operating at 2.5 GT/s and 5.0 GT/s the receiver shall observe at least 8 consecutive idle symbols before asserting LinkUp.”
代码路径:
if ((GEN1/2 rate) && rcvd_8idles && idle_16_sent)
next_lts_state = S_L0;
...
always @(posedge) if (lts_state==S_L0) smlh_link_up <= 1;
波形中 smlh_link_up
在 time 828 261 抬高,与日志一致;同时 ltssm_in_training
由 1→0。
7 低功耗路径(L0s / L1 / L2)
-
L0s:两路子状态机
- Tx:
S_L0S_XMT_*
— 先发 Idle/EIEOS,再发 N_FTS,最后 Wait/Idle。 - Rx:
S_L0S_RCV_*
— 检测 EIOS 连续性,clked_rxstandby
控制 PHY standby。
- Tx:
-
L1 / L23:
S_L123_SEND_EIDLE
:发送一帧 EIEOS ,并等待对端 EIOS (latched_rcvd_eidle_set
);若 2 ms 超时进入 Error_Enter_L1 路径。- 在
S_L1_IDLE
/S_L2_IDLE
仍保持ltssm_cmd = XMT_IN_EIDLE
。
8 Hot Reset & Loopback
8.1 热复位
当 latched_direct_rst
置 1(由 cfg_reset_assert
或 App Reset 驱动),LTSSM:
L0/L1_IDLE ─► S_RCVRY_LOCK ─► S_HOT_RESET_ENTRY ─► S_HOT_RESET
S_HOT_RESET_ENTRY
使用 SEND_TS1
携带 HotReset 控制位;S_HOT_RESET
中继续 TS1 直到对端回应两个 TS1 带 HotReset=0,随后回到 Detect。
8.2 内/外环回
cfg_lpbk_en
上升沿 + DSP 接收到对端 TS1(Lpbk1) →S_LPBK_ENTRY
。S_LPBK_ENTRY_EIDLE
要求速度切回 Gen1 并发送 EIEOS;之后 Tx 侧 16 TS1 with PAD 进入 Loopback.Active。- 退出环回采用 2 ms 超时或软件 Clear,经过
S_LPBK_EXIT
、S_LPBK_EXIT_TIMEOUT
再回 Detect。
9 上行/下行差异及 Upconfigure
上行(USP)与下行(DSP)在 Configuration 阶段职责不同:
- USP 把 Link Number / Lane Number PAD,等待 DSP 决定。
- DSP 在
S_CFG_LINKWD_START
即用xmt_ts_lnknum
发送自己的 Link#/Lane#。
Upconfigure‑capable (cfg_upconfigure_support=1
) 时,链路可在 L0 后自行扩宽;ltssm_ts_auto_change
被拉高并在 Recovery.Lock 触发速率或宽度重协商。
10 电源管理接口 & PIPE 交互
mac_phy_rate[2:0]
通过 三级延迟 保证在 PIPEphy_status
全撤销后再改速。- 进入 RxStandby 依据
rxstandby_assertion_enable
策略位,结合int_rcvd_eidle_rxstandby
(已收 EIOS)rate_change_flag
(正在变速)current_powerdown
(P1/P2)
eiexit_hs_in_progress
用于阻止速率切换期间 RX standby 抖动。
11 深层初始化机制透视
初始化环节 | 波形/信号示例 | 标准引用 |
---|---|---|
位锁定 (Bit‑Lock) | xmtbyte_fts_sent 计数达 N_FTS |
“FTS provides bit‑lock… 130 × N_FTS UI” |
符号/块锁 | rmlh_all_sym_locked 拉高 |
§4.2.4.1 Training Sequences |
极性检测 | latched_lane_reversed |
§4.2.4.4 Lane Polarity |
去斜 (Deskew) | rmlh_deskew_complete |
§4.2.4.11 Lane‑to‑Lane De‑skew |
DC Balance 跟踪 | TS1/TS2 Symbol 14/15 自动替换 | “Transmitters must evaluate running DC Balance…” |
速率协商 | latched_ts_data_rate 比较 + mac_phy_rate 更新 |
§4.2.4.9 Link Data Rate Negotiation |
这些步骤在波形中可直接定位:从 Detect 到 L0 共需 ~830 µs(见时间轴 0→832 661 unit),与规范 < 1 ms 要求相符。
12 小结
- 状态机 —
ltssm[5:0]
与规范逐一对照,配合ltssm_cmd
可精确锁定阶段。 - 训练序列 — 使用
xmtbyte_ts*_sent
和波形周期计算,确认 TS1≥1024、TS2≥16。 - Deskew & Equalization —
rmlh_deskew_complete
和 “Modified TS2 Skip‑EQ” 信号帮助加速 Gen3+ 训练。 - 恢复 / 低功耗 — 计时器、EIOS 检测与
rxstandby
handshake 共同保障快速且可靠的电源转换。 - 调试策略 — 建议“状态‑命令‑计数器‑关键脉冲”四组信号固定放在波形模板,出现异常抓住第一跳转点即可定位。
结合本文的 代码摘录 + 波形解析 + 标准条文,你可以为同事构建一套完整的 LTSSM 实战教程,既能解释高阶串行链路的初始化机理,又能在测试或现场故障时直接落地调试。祝写作顺利、培训成功!