
本篇位置FPGA NVMe Host 实战连载 · 第一幕共同底座 · 第 04 篇第 02 篇解决的是链路能否进入 L0第 03 篇解决的是 FPGA 为什么要站在 Root Port 一侧。两件事都成立后下一步的问题很具体FPGA 向 SSD 发出的配置访问到底以什么形式在线上传输SSD 又怎样把结果送回来答案不是一条 AXI 信号也不是一段 NVMe 命令文本。PCIe 链路上走的是不同类别的协议单元其中与 Host 最直接相关的是 TLP。先把这些名字和方向分清后面看配置空间访问时就不会把“请求发出了”“返回包到了”“控制器能访问”混成一件事。本文先给出控制路径FPGA Root Port → Configuration Read TLP → NVMe SSD Endpoint → Completion with Data → FPGALink Up 后链路上跑的三类东西PCIe 从训练到正常工作会遇到 Ordered Set、DLLP 和 TLP 三类内容。它们都可能出现在同一条物理链路上但用途不同。图 1PCIe 链路中三类协议单元的职责示意。图为理解和调试用途的自绘图并未列出所有类型。Ordered Set更靠近物理链路。TS1、TS2 用于训练和状态切换链路进入 L0 后SKP 等 Ordered Set 仍可能用于链路运行期维护。DLLPData Link Layer Packet服务于链路层的流控、确认和维护。它不承载 SSD 的配置字段也不承载 NVMe 用户数据。TLPTransaction Layer Packet事务层数据包。Configuration、Memory、Completion、Message 等访问都属于这一类。本篇的重点就是它。可以把 L0 理解为“链路已经具备传输这些内容的条件”。但 L0 本身不等于某一个配置读取已经完成是否真的完成还要看 TLP 请求和对应返回。三类单元的包结构并不一样它们都走在 PCIe Link 上却不能按同一类“包头 数据”的思路理解。最直接的区别是Ordered Set 由物理层符号或块组成DLLP 是一个固定长度的链路层小包TLP 才是携带访问请求、返回状态和可选数据的事务包。协议单元在线上怎样定义用途本项目事务 AXI4-Stream 是否可见Ordered Set按具体类型规定的物理层 Symbol/Block 序列训练、状态控制、时钟容差等链路维护否DLLPNon-Flit Mode 下固定为 6 ByteType 24 bit 特定信息 16 bit CRC流控、确认、重传与电源管理等链路服务否TLP3-DW 或 4-DW Header加可选 PayloadConfiguration、Memory、Completion、Message 等事务是表中“是否可见”专指本项目使用的 AMD 7 系列 PCIe IP 的事务 AXI4-Stream 接口。不同厂商或不同层级的调试接口可能提供额外状态但不能把它们与用户事务口混为一谈。Ordered Set按符号位置定义不是 TLP 式包头Ordered Set 属于物理层使用的控制序列。它没有统一的 3-DW/4-DW Header也不携带一次配置读取的地址或返回数据。每一种 Ordered Set 自己规定各个 Symbol/Block 的含义接收端先根据开头的标识识别类型再按规定的位置解释后续内容。TS1 是最常接触到的一种。下面截取 PCIe Base 7.0 对 TS1 的前 3 个 Symbol 定义Symbol 0 是 TS1 IdentifierSymbol 1 是 Link NumberSymbol 2 是 Lane Number。表格后续还有 N_FTS、链路控制等字段因此这张图用于说明“按符号位置解释”不是 TS1 的完整格式。图 2PCI-SIG《PCI Express Base Specification Revision 7.0》Table 4-36PDF p.484。图中截取 TS1 Ordered Set 的 Symbol 02完整表格继续定义后续 Symbol。在第 02 篇排查 LTSSM 时TS1/TS2 是训练侧的重要观察对象但不要把 Ordered Set 只理解成“训练数据”。例如 SKP 也会在 L0 的正常运行期间出现用于处理两端参考时钟之间的频率偏差。DLLP固定 6 Byte服务链路本身本项目所用的 7 系列 PCIe IP 工作在 Non-Flit Mode。该模式下PCIe Base 7.0 §3.5.1 给出 DLLP 的固定结构第 0 Byte 是 DLLP Type接下来的 3 Byte 共 24 bit 为 Type-specific information最后 2 Byte 是 16-bit CRC。因此 DLLP 一共 6 Byte。图 3PCI-SIG《PCI Express Base Specification Revision 7.0》Figure 3-4PDF p.337。Non-Flit Mode 下 DLLP 的 Type、24 bit 类型特定信息和 16 bit CRC 字段。先看 Byte 0 的 Type就能知道这是不是哪一类 DLLP之后再按该类型解释 24 bit 的内容。Ack/Nak 用于 TLP 的确认和重传控制Flow Control DLLP 用于传递缓冲区 Credit。它们让链路可靠地传输 TLP但 DLLP 本身不等于一次 SSD 配置访问也不会带回 Vendor ID 这类配置字段。TLP事务内容在线路上还会加一层链路封装TLP 本身由事务层定义Header 为 3 DW 或 4 DW后面是否有 Payload 由具体事务决定。Configuration Read、Memory Read 通常是“带 Header、不带返回数据”的请求Completion with Data 则在 Header 后面带回读取结果。在 Non-Flit Mode 的实际链路传输中数据链路层还会在 TLP 前加入 4 bit 和 TLP Sequence Number并在末尾追加 32-bit LCRC。图中的{TLP Header}之后可以继续接 TLP 的可选 Payload。接收端完成序号与 LCRC 校验后才把这些链路封装剥离将原来的 TLP 交给事务层。图 4PCI-SIG《PCI Express Base Specification Revision 7.0》Figure 3-17PDF p.347。Non-Flit Mode 下数据链路层给 TLP 加入 TLP Sequence Number 和 LCRC 后的线上形式。因此抓到一个“看起来像 TLP”的线上字节序列时不能把最前面的序号和最后的 LCRC 误当成 TLP Header 或 Payload它们属于数据链路层的可靠传输封装。用户 AXIS 口实际看到什么对本项目的用户逻辑PCIe IP 提供的是事务 AXI4-Stream 接口。发送侧通过s_axis_tx_*交给 IP 的是待发送 TLP接收侧通过m_axis_rx_*交给用户逻辑的是已通过链路检查的接收 TLP。AMD PG054 的接口章节将这组接口称为事务接口并在 Basic TLP Receive Operation 中说明由m_axis_rx_*向用户逻辑呈现 TLP。图 5本项目 PCIe IP 与用户 RTL 的接口边界示意。图为自绘接口名称和 TLP 接收行为依据 AMD《PG054 v3.3》Chapter 3。这张图可以直接回答调试时最常见的疑问。ILA 接在m_axis_rx_*一侧看到的是 TLP 的 Header 和可选 Payload以及tvalid、tready、tkeep、tlast等流接口信号不是串行线上原始的 8b/10b 或 128b/130b 编码数据。TLP 的 Sequence Number、LCRC以及 Ack/Nak、Flow Control 等 DLLP由 PCIe IP 的数据链路部分生成、校验或处理不交给这个用户事务口。TS1、TS2、SKP 等 Ordered Set 同样由物理层处理不会作为 AXI4-Stream 的一个 TLP 送到用户逻辑。这里的“只看到 TLP”不表示用户逻辑只连接一根tdata总线。实际收发仍需遵守 AXI4-Stream 握手和 IP 的tuser定义例如 PG054 规定传输侧以tvalid和tready同时有效作为一次数据交接。它表示的是协议边界用户接口面向事务层而不是让 RTL 自己处理物理编码、DLLP CRC 或 TLP 的链路重传。TLP 不是一种固定格式而是一组事务在 FPGA 直连 SSD 的场景中最早会遇到的不是所有 PCIe 事务而是下面几类。TLP 类别谁发起常见方向是否有 Completion这类事务解决什么问题Configuration ReadRoot PortFPGA → SSD有通常为 CplD读取配置空间中的识别与能力信息Configuration WriteRoot PortFPGA → SSD有不带数据写入允许由 Host 配置的字段Memory Read访问方FPGA ↔ SSD有通常为 CplD读取控制器寄存器或由 SSD 取得 Host 准备的数据Memory Write访问方FPGA ↔ SSD常规访问中没有写控制器寄存器或由 SSD 写回数据与完成信息Completion / CplD被请求方与原请求反向是对读取类请求的响应返回状态CplD 还会带回数据Message设备或端口双向取决于消息类型用于特定通知和管理场景图 6PCI-SIG《PCI Express Base Specification Revision 7.0》Table 2-1PDF p.154。规范将 Memory、I/O、Configuration、Message 分为不同地址空间并给出各自的基本用途。表中的 Configuration Read / Write 用于设备 Function 的配置和建立§2.1.1.3 进一步说明这两类 Configuration Transaction 分别由“Read Request / Completion”和“Write Request / Completion”组成。这样配置写入也属于有返回的事务而不是所有写入都没有返回。这里最容易误判的是没有 Completion 不一定是错误。本篇所说的常规 Memory Write 不包含 UIO 等特殊事务它属于 Posted Request发起方正常情况下不会等待一个 Completion。相反Configuration Read 和 Memory Read 都需要看到相应的 Completion没有返回就需要检查请求是否到达、对端是否接受以及返回是否被接收。一次配置读取在线上是怎样来回的第 03 篇已经说明 SSD 不会在 Link Up 后主动把自己的信息推给 FPGA。第一步仍由 Root Port 发起 Configuration Read。SSD 接收到请求后再以 Completion with Data 返回本次读取的内容。图 7配置读取的请求—响应关系。CplD 是带数据的 Completion请求和返回是两次方向相反的 TLP 传输。这张图里有三个判断点。请求是否真的离开 FPGA。user_lnk_up1只说明可以开始传输不代表 Configuration Read 已经发出。SSD 是否有返回。对读取类访问Endpoint 应给出 Completion带回读取数据时就是 CplD。返回是否属于这次访问。FPGA 不能因为看见一个包就直接当作结果还要确认它与当前请求对应并检查返回状态和数据是否合理。后续配置空间实测章节会把这三个观察点放到同一条板上路径中请求从哪里产生、返回从哪里进入、字段怎样被解析。当前先把事务关系看清后面读到的每一个信号和波形才有位置可放。Memory Read 与 Memory Write后面为什么总会遇到配置空间访问解决的是“SSD 是谁、它提供什么 PCIe 能力”。而 NVMe 控制器寄存器、命令和数据传输则会继续使用 Memory Read、Memory Write。方向看起来多实际上只要记住“读需要数据返回写通常不等待返回”即可。图 8四种常见方向。前两条是 FPGA 访问 SSD 控制器时会遇到的路径后两条说明 SSD 执行后续命令时也可能主动发起 PCIe 事务。图中的后两条并不改变 SSD 是 Endpoint 的事实。角色由 PCIe 拓扑和控制责任决定Root Port 负责发现和配置下游设备SSD 在得到 Host 提供的地址和命令后可以发起内存访问完成数据搬运。NVM Express 的 NVMe over PCIe Transport 规范说明控制器属性寄存器位于 PCI BAR0/BAR1 指定的内存空间中Host 通过内存映射访问它们。也就是说配置读取之后才会逐步走到 Memory Read 和 Memory Write 这一类访问。FPGA 逻辑怎样接触这些包PCIe IP 负责编码、链路训练、流控、DLLP 和 TLP 的链路可靠性处理。对 FPGA 用户逻辑来说发送和接收侧通过事务 AXI4-Stream 接口交接 TLP。Host 逻辑需要做的是在合适的时机组织访问、接收返回并推动自己的状态继续向前。这也是 FPGA 做 PCIe Host 和调用普通寄存器外设不同的地方一次读取不是“给地址立刻得到数据”而是一段跨越链路的请求—返回过程。链路上的时延、返回顺序、异常状态和接收能力都会影响状态机下一步能否正确判断。AMD 的 PG054 对 7 系列 PCIe IP 的事务接口和接收 TLP 行为给出了说明它也明确区分了可由用户逻辑接收的 Posted、Non-Posted 与 Completion 事务。实际做调试时先确认 IP 已把返回事务交给用户侧再确认用户逻辑是否把它当作当前请求的结果处理效率会高很多。为什么 Link Up 后仍不能直接读 SSD现在可以把前几篇的关系串起来供电/时钟/复位正确 → LTSSM 进入 L0 → 可以传输 TLP → Configuration Read 与 CplD 正常往返 → 配置空间信息有效 → 继续处理后续访问每个箭头都是一个独立检查点。若停在 L0 前优先回第 02 篇查物理链路若 L0 已稳定但读取没有结果就应把注意力转到请求、Completion 和返回解析而不是直接怀疑 NVMe 命令。调试时先看什么现象优先观察容易犯的错误LTSSM 未进入 L0REFCLK、PERST#、Lane、收发器状态把物理层问题归到 TLPConfiguration Read 后没有结果请求是否送出、是否出现 Completion只看user_lnk_up收到 Completion 但结果不合理返回状态、数据长度、与当前请求的对应关系只因收到一个包就继续状态机常规 Memory Write 后没有 Completion先确认事务类型把 Posted Request 的正常现象当成丢包小结PCIe Link Up 后FPGA 与 NVMe SSD 之间传输的不是抽象的“SSD 命令”而是 Ordered Set、DLLP 和 TLP 等不同用途的协议单元。Ordered Set 按物理层 Symbol/Block 定义DLLP 在 Non-Flit Mode 下是固定 6 Byte 的链路维护包TLP 才承载配置、内存访问与 Completion 等事务TLP 在线上还会由数据链路层加入 Sequence Number 和 LCRC。对本项目的用户 AXI4-Stream 逻辑收发边界是 TLPDLLP、LCRC、序号和 Ordered Set 都在 PCIe IP 内部处理。明确这条边界后看到 ILA 中的一段m_axis_rx_tdata时才能知道它应按 TLP Header/Payload 解析而不是从物理层符号或 DLLP 开始猜。读取类事务需要看 CompletionCplD 还会带回数据常规 Memory Write 则通常没有 Completion。理解这个差异后才能把“链路已经可用”和“某次配置访问已经得到结果”严格分开。下一篇进入配置空间本身SSD 的基础信息放在哪里FPGA 读取时究竟在确认什么。参考资料AMDPG054 v3.37 Series FPGAs Integrated Block for PCI Express事务层接口与接收 TLP 说明参见 Chapter 3Root Port 相关说明参见 Chapter 4。NVM ExpressNVMe over PCIe Transport Specification v1.4第 2 章说明 PCIe Transport 的内存映射传输第 3 章说明 BAR0/BAR1 与控制器属性寄存器的关系。PCI-SIGPCI Express Base Specification Revision 7.0Table 2-1PDF p.154和 §2.1.1.3PDF p.155是本章事务分类与 Configuration Transaction 请求—返回关系的直接来源。