news 2026/8/30 5:47:18

第四章:PCIe Link Up 后怎么传输数据?FPGA 先认识 TLP、DLLP 和 Completion

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第四章:PCIe Link Up 后怎么传输数据?FPGA 先认识 TLP、DLLP 和 Completion

本篇位置: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 → FPGA

Link Up 后,链路上跑的三类东西

PCIe 从训练到正常工作,会遇到 Ordered Set、DLLP 和 TLP 三类内容。它们都可能出现在同一条物理链路上,但用途不同。

图 1:PCIe 链路中三类协议单元的职责示意。图为理解和调试用途的自绘图,并未列出所有类型。

  • Ordered Set:更靠近物理链路。TS1、TS2 用于训练和状态切换;链路进入 L0 后,SKP 等 Ordered Set 仍可能用于链路运行期维护。
  • DLLP:Data Link Layer Packet,服务于链路层的流控、确认和维护。它不承载 SSD 的配置字段,也不承载 NVMe 用户数据。
  • TLP:Transaction 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 Byte:Type + 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 Identifier;Symbol 1 是 Link Number;Symbol 2 是 Lane Number。表格后续还有 N_FTS、链路控制等字段,因此这张图用于说明“按符号位置解释”,不是 TS1 的完整格式。

图 2:PCI-SIG《PCI Express Base Specification Revision 7.0》Table 4-36,PDF p.484。图中截取 TS1 Ordered Set 的 Symbol 0~2;完整表格继续定义后续 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。

图 3:PCI-SIG《PCI Express Base Specification Revision 7.0》Figure 3-4,PDF 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 交给事务层。

图 4:PCI-SIG《PCI Express Base Specification Revision 7.0》Figure 3-17,PDF 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,以及tvalidtreadytkeeptlast等流接口信号;不是串行线上原始的 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 规定传输侧以tvalidtready同时有效作为一次数据交接。它表示的是协议边界:用户接口面向事务层,而不是让 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设备或端口双向取决于消息类型用于特定通知和管理场景

图 6:PCI-SIG《PCI Express Base Specification Revision 7.0》Table 2-1,PDF 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 传输。

这张图里有三个判断点。

  1. 请求是否真的离开 FPGA。user_lnk_up=1只说明可以开始传输,不代表 Configuration Read 已经发出。
  2. SSD 是否有返回。对读取类访问,Endpoint 应给出 Completion;带回读取数据时就是 CplD。
  3. 返回是否属于这次访问。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、收发器状态把物理层问题归到 TLP
Configuration 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 逻辑,收发边界是 TLP:DLLP、LCRC、序号和 Ordered Set 都在 PCIe IP 内部处理。明确这条边界后,看到 ILA 中的一段m_axis_rx_tdata时,才能知道它应按 TLP Header/Payload 解析,而不是从物理层符号或 DLLP 开始猜。

读取类事务需要看 Completion,CplD 还会带回数据;常规 Memory Write 则通常没有 Completion。理解这个差异后,才能把“链路已经可用”和“某次配置访问已经得到结果”严格分开。下一篇进入配置空间本身:SSD 的基础信息放在哪里,FPGA 读取时究竟在确认什么。

参考资料

  1. AMD,PG054 v3.3:7 Series FPGAs Integrated Block for PCI Express,事务层接口与接收 TLP 说明参见 Chapter 3,Root Port 相关说明参见 Chapter 4。
  2. NVM Express,NVMe over PCIe Transport Specification v1.4,第 2 章说明 PCIe Transport 的内存映射传输;第 3 章说明 BAR0/BAR1 与控制器属性寄存器的关系。
  3. PCI-SIG,PCI Express Base Specification Revision 7.0,Table 2-1(PDF p.154)和 §2.1.1.3(PDF p.155)是本章事务分类与 Configuration Transaction 请求—返回关系的直接来源。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 5:47:02

世界模型的新台阶:心智世界建模让AI理解他人意图

现在大家都在讨论世界模型,但很多讨论把它默认为“物理世界的模拟器”——预测物体的位置、学习环境变换规律、让智能体在脑海里预演动作。这个理解没有错,却漏掉了一个更值得关注的转向。牛津、NUS 团队提出的“心智世界建模”(Mental World…

作者头像 李华
网站建设 2026/8/30 5:46:46

ComfyUI+ControlNet涂鸦引导图生图:从草图到插画的完整工作流

简介:本资源是一套面向ComfyUI初学者与AIGC图像生成实践者的ControlNet涂鸦引导图生图工作流配置方案,专为SD1.5模型环境设计,解决手绘草图精准控制生成内容结构与构图的核心需求。压缩包仅含1个3KB的JSON文件,为ComfyUI可直接导入…

作者头像 李华
网站建设 2026/8/30 5:46:45

六大查重系统一站式对接值不值?5维度拆解

围绕"一站式对接六大查重系统到底值不值"这个问题,我们沿着覆盖度、官方性、效率、完整性、口径一致性五个维度做了拆解。结论先说:对需要在多个系统间反复切换、又想和学校终检口径对齐的同学,一站式官方通道对接能明显省事。以知…

作者头像 李华
网站建设 2026/8/30 5:46:35

Dify + ECharts 实战:自然语言一键生成饼状图

之前在业务迭代中遇到一个高频需求:用户输入一段业务数据,系统自动生成可视化图表。常见的做法是前端先约定好数据结构,后端写死几种图表模板,一旦遇到字段变化就要改代码,整个过程并不“智能”。后来我尝试用 Dify 搭…

作者头像 李华
网站建设 2026/8/30 5:45:34

手把手拆解:降重后语句不通顺怎么修?2026语义修复全流程操作指南

重复率是压下来了,可段落读起来磕磕巴巴,上一句和下一句像两个人写的——这是降重环节很容易被忽略的后遗症。本文不做工具红黑榜,只给一套能照着做的修复顺序:先定损、再分层修、收尾回测。知学术AIPaperGPT 的 AI 无限改稿一次付…

作者头像 李华
网站建设 2026/8/30 5:44:59

VL53L9 demo binary运行指南:从烧录到串口调试

很多人第一次接触VL53L9,卡住的往往不是激光测距原理本身,而是那个已经编译好的demo binary——官方给了一个能直接跑的二进制文件,连工程都帮你建好了,结果拿到手却不知道下一步干什么。这篇文章我就从“拿到compiled demo binar…

作者头像 李华