3、PCIe协议基础:PCIe分层结构、TLP与DLLP包格式、链路训练与初始化
3.1 PCIe分层结构概述
PCIe采用分层架构,从上到下依次为:事务层(Transaction Layer)、数据链路层(Data Link Layer)和物理层(Physical Layer)。每一层都有明确的职责边界,层间通过标准接口交换信息。这种分层设计使得协议栈可以独立演进,也便于FPGA实现时进行模块化划分。
调试要点:在Agilex高速收发器调试中,分层隔离是定位问题的核心思路——物理层问题(如信号完整性)不会影响TLP语义,反之亦然。务必在调试初期确认问题所在层级。
3.2 事务层与TLP包格式
事务层是PCIe协议栈的最上层,负责与设备核心逻辑(或软件驱动)交互。它生成和解析事务层包(TLP, Transaction Layer Packet)。TLP是PCIe通信的基本数据单元,包含所有读写请求、完成响应和消息。
3.2.1 TLP包结构
一个标准的TLP由以下字段组成:
| 字段 | 宽度(字节) | 说明 |
|---|---|---|
| 起始(STP) | 1 | 帧起始定界符,由数据链路层添加 |
| TLP前缀(可选) | 0/4/8 | 扩展TLP功能,如TCO(Trusted Computing) |
| TLP头 | 12/16/20 | 包含事务类型、地址/ID、长度、属性等核心信息 |
| 数据负载(可选) | 0~4096 | 实际读写数据,最大为4KB(受MaxPayloadSize限制) |
| ECRC(可选) | 4 | 端到端CRC校验,由事务层计算 |
| 结束(END) | 1 | 帧结束定界符,由数据链路层添加 |
3.2.2 TLP头格式详解
TLP头是解析事务的关键。以最常见的Memory Read/Write(32位地址)为例,TLP头为12字节:
Byte 0: [Fmt(2b)][Type(5b)][R(1b)]
Byte 1: [TC(3b)][R(5b)]
Byte 2: [Attr(2b)][R(1b)][TH(1b)][TD(1b)][EP(1b)][Attr2(2b)]
Byte 3: [Length(10b)][R(6b)]
Byte 4-7: [Requester ID(16b)][Tag(8b)][Last DW BE(4b)][First DW BE(4b)]
Byte 8-11: [Address(32b)]
调试技巧:在Agilex的PCIe Hard IP中,可以通过配置寄存器直接观察TLP头的Fmt/Type字段,快速判断当前事务类型。例如:
Fmt=00, Type=00000 表示Memory Read Request(无数据)。
3.2.3 主要TLP事务类型
| 事务类型 | Fmt/Type编码 | 方向 | 典型用途 |
|---|---|---|---|
| Memory Read Request | 00 00000 | 主→从 | 读取系统内存或BAR空间 |
| Memory Write Request | 10 00000 | 主→从 | 写入系统内存或BAR空间 |
| Completion with Data | 00 01010 | 从→主 | 返回读数据 |
| Completion without Data | 00 01011 | 从→主 | 写完成或错误响应 |
| Configuration Read/Write | 00/10 00100 | 主→从 | 访问配置空间(Type 0/1) |
| Message | 01 10010 | 任意 | 中断(MSI/MSI-X)、错误报告、电源管理 |
3.3 数据链路层与DLLP包格式
数据链路层位于事务层和物理层之间,主要职责包括:
- TLP封装/解封装:在TLP前后添加序列号(Sequence Number)和LCRC(链路CRC),形成数据链路层包。
- DLLP生成与解析:生成数据链路层包(DLLP),用于链路管理、流控和确认。
- 重传机制:基于Ack/Nak协议,确保TLP可靠传输。
- 链路状态管理:维护数据链路层的状态机(DL_Active、DL_Inactive等)。
3.3.1 DLLP包结构
DLLP是数据链路层内部使用的短包,长度固定为6字节:
| 字段 | 宽度(字节) | 说明 |
|---|---|---|
| DLLP类型 | 1 | 标识DLLP种类(Ack/Nak/InitFC1/UpdateFC等) |
| DLLP数据 | 4 | 根据类型不同,包含序列号、信用量等信息 |
| CRC | 1 | 8位CRC校验,覆盖前5字节 |
3.3.2 常见DLLP类型
| DLLP类型 | 类型值 | 用途 |
|---|---|---|
| Ack | 0x00 | 确认已正确接收TLP,携带序列号 |
| Nak | 0x01 | 拒绝接收TLP,请求重传 |
| InitFC1/InitFC2 | 0x02/0x03 | 初始化流控信用量(发布者/完成者) |
| UpdateFC | 0x04 | 更新流控信用量,允许对端发送更多TLP |
常见调试陷阱:在Agilex调试中,如果发现链路已训练完成(LTSSM进入L0)但无法收发数据,通常是因为数据链路层流控信用量未正确初始化。检查DLLP中的InitFC和UpdateFC是否正常交换。
3.4 链路训练与初始化(LTSSM)
链路训练与初始化由物理层的LTSSM(Link Training and Status State Machine)负责。LTSSM是PCIe链路建立的核心状态机,控制从复位到正常数据传输的完整过程。在Agilex调试中,LTSSM状态是判断物理层是否就绪的首要检查点。
3.4.1 LTSSM主要状态
| 状态 | 说明 | 典型停留时间 |
|---|---|---|
| Detect | 检测对端设备是否存在(通过接收检测电路) | ~12μs |
| Polling | 发送TS1/TS2训练序列,进行位锁定和符号锁定 | ~48μs |
| Configuration | 协商链路宽度(x1/x2/x4/x8/x16)和极性反转 | ~64μs |
| L0 | 正常操作状态,可收发TLP和DLLP | 持续 |
| L0s/L1 | 低功耗状态(可选),通过电气空闲进入 | 按需 |
| Recovery | 从错误或低功耗状态恢复,重新训练 | ~24μs |
| Hot Reset | 热复位,强制链路重新初始化 | ~2μs |
3.4.2 链路训练流程
- Detect阶段:物理层发送检测信号,确认对端接收器存在。如果未检测到,则循环等待。
- Polling阶段:双方交换TS1/TS2有序集,完成位锁定、符号锁定和块锁定。Agilex的收发器CDR(时钟数据恢复)在此阶段锁定。
- Configuration阶段:协商链路宽度(如x8链路可能降级为x4)和极性。如果某条通道训练失败,会被自动禁用。
- L0状态:链路进入正常工作模式,数据链路层开始交换InitFC DLLP,初始化流控信用量。之后TLP传输开始。
Agilex调试实战:在Signal Tap Logic Analyzer中捕获LTSSM状态寄存器(通常映射到Hard IP的物理层状态寄存器),可以精确观察链路训练过程。常见问题:
• 卡在Detect:检查差分对连接、参考时钟、AC耦合电容。
• 卡在Polling:检查CDR锁定状态、信号眼图质量。
• 卡在Configuration:检查链路宽度协商是否匹配(如FPGA配置为x8但对端只支持x4)。
• 卡在Detect:检查差分对连接、参考时钟、AC耦合电容。
• 卡在Polling:检查CDR锁定状态、信号眼图质量。
• 卡在Configuration:检查链路宽度协商是否匹配(如FPGA配置为x8但对端只支持x4)。
3.4.3 链路训练关键参数
| 参数 | Gen1/Gen2/Gen3/Gen4 | 说明 |
|---|---|---|
| 数据速率 | 2.5/5.0/8.0/16.0 GT/s | 每通道串行速率 |
| 编码方式 | 8b/10b / 8b/10b / 128b/130b / 128b/130b | Gen3+使用加扰的128b/130b编码 |
| 训练序列 | TS1/TS2 / TS1/TS2 / EIOS/EIEOS / EIOS/EIEOS | Gen3+引入电气空闲有序集(EIOS) |
| 链路宽度协商 | 1/2/4/8/16 通道 | 自动协商,支持降级 |
快速检查清单:当Agilex PCIe链路无法训练时,按以下顺序排查:
1. 参考时钟是否稳定(100MHz ±300ppm)?
2. 复位时序是否正确(PERST#与参考时钟的关系)?
3. LTSSM当前状态是什么(通过Hard IP寄存器读取)?
4. 差分对是否交叉连接(Tx→Rx, Rx→Tx)?
5. AC耦合电容是否在发送端(通常为100nF~220nF)?
1. 参考时钟是否稳定(100MHz ±300ppm)?
2. 复位时序是否正确(PERST#与参考时钟的关系)?
3. LTSSM当前状态是什么(通过Hard IP寄存器读取)?
4. 差分对是否交叉连接(Tx→Rx, Rx→Tx)?
5. AC耦合电容是否在发送端(通常为100nF~220nF)?