AXI-Stream 反压握手:VALID/READY 时序、气泡传播与 RTL 坑
更新时间:2026-09-25。本文是「集成电路大类 · 芯片设计」序列里的一篇长尾时序文。valid/ready 握手:反压、气泡、Skid Buffer 与 AXI-Stream 基础 讲过握手的整体概念,这一篇专门把波形放大,逐拍讨论 AXI-Stream 反压握手的时序细节——协议文本只有寥寥几条规则,但 RTL 写反、仿真漏掉反压场景导致流片后丢数据的事故年年都有。AMBA 家族的来历见 AMBA 总线入门:从 APB/AHB 到 AXI 的演进。
本文要回答的问题
- TVALID 置起后,数据和信号能不能因为对端暂时没收就撤掉换一个?
- TREADY 随时拉低会在波形上留下什么,握手到底在哪一拍成立?
- 下游一级反压,为什么上游整条流水线会一起停住,气泡如何传播?
- 哪些 RTL 写法会做出组合环路或在反压时丢数据,skid buffer 为什么是标准答案?
一、握手规则:一条「置起不许反悔」,一条「随时可收」
AXI-Stream 的握手只有两个控制信号:发送方驱动 TVALID(数据有效),接收方驱动 TREADY(可以接收)。数据在 TVALID 与 TREADY 同时为高的那个时钟上升沿完成传递,业内叫一个 handshake(握手拍)。这一拍之外,TDATA、TLAST、TKEEP 等载荷怎么变都不影响协议,因为它们只在握手拍被采样。
协议对两个信号各有一条不对称的约束,所有时序问题都从这两条派生:
- TVALID 一旦置起,在握手完成之前不得撤销,载荷也不得改变。 发送方说出「我有数据」之后,必须原地保持,直到接收方点头。不能因为等了两拍没等到 TREADY 就把 TVALID 拉低、或把 TDATA 换成下一个数——接收方可能正是在第三拍采样。
- TREADY 可以随时置起或拉低,没有「置起后必须保持」的义务。接收方完全可以根据自己的缓冲余量逐拍决定收不收;但推荐(并非强制)TREADY 在复位结束后就尽快置起,以缩短延迟。
这种不对称是刻意的设计:发送方负责「把话讲清楚并保持」,接收方保留「逐拍拒绝」的自由,反压(backpressure)能力由此而来。接收方暂时不收,数据流就被顶在原地;恢复 TREADY 后自动继续,不需要重传、不需要额外的握线——前提是发送方老老实实地保持住了数据。
二、四种握手情形与波形逐拍解读
协议允许双方任意先后置起信号,组合起来有四种情形:
| 情形 | TVALID | TREADY | 握手拍 | 典型场景 |
|---|---|---|---|---|
| ① VALID 先 | T1 置起并保持 | T4 才置起 | T4 | 下游缓冲将满,反压最常见形态 |
| ② READY 先 | T3 才置起 | T1 已置起 | T3 | 接收方提前表态,单拍直通 |
| ③ 同拍 | T2 置起 | T2 置起 | T2 | 零气泡流水,吞吐最大 |
| ④ 无握手 | 低,或高但对端低 | 低或无 | 无 | 空闲 / stall 气泡,无数据传递 |
注意情形 ①里 TVALID 在 T1–T4 始终为高、TDATA 始终是同一个值;TREADY 哪怕在 T2、T3 间歇性跳高再低——只要没和 TVALID 同拍为高,就不算握手,发送方仍须继续保持。情形 ② 里 TREADY 先高也没有保持义务,若它在 TVALID 到来前提前拉低,这次就退化为 ④,等下一轮。
下图画出情形 ①的完整波形,这也是验证环境里最该被随机出来的时序:

逐拍读图:T1 发送方置起 TVALID 并放上数据;T2、T3 两拍 TREADY 为低,接口停在原地,这两拍就是气泡(bubble,也称 stall),数据通路没有任何传递;T4 TREADY 置高,与 TVALID 在上升沿相遇,握手成立,数据在这一拍被接收方采走;T5 起双方均可拉低,本次事务结束。统计吞吐时,T1–T4 四个周期只传了一个数据,等效带宽只有峰值的四分之一——反压的性能代价在波形上就是这样量化的。
三、反压在多级流水线中的传播
实际数据通路很少只有一级。典型链路是 DMA → 位宽适配器 → 计算核,中间还可能插着寄存器切片。反压的传播规则一句话:某一级的输出握手不上,它的输入 TREADY 就必须拉低,把停摆向更上游推。
下图画出两级流水线中,下游反压如何在同一拍顶到最上游接口:

逐拍读图:T1 上游放来数据;T2 级间 ready 与上游 TREADY 同高,数据推进一级;T3 下游突然反压,级间 ready 拉低,本级的输出寄存器无处可推,于是它在同一拍把输入侧的 TREADY 也拉低,上游 TVALID 虽保持高却无法握手——T3 到 T5 三级全冻在原地;T6 下游恢复,级间 ready、上游 TREADY 依次(组合逻辑上是同一拍)恢复,流水线重新流动。
这里有两个工程含义。其一,ready 通常是沿数据流反向组合传播的,链路级数越多、组合路径越长,频率越容易被这条 ready 链拖垮,这正是插入 AXI 寄存器切片:时序收敛、Skid Buffer 与多拍延迟插桩 的理由。其二,stall 期间各级寄存器必须保持原值不动:使能条件是「输出侧 TVALID 与 TREADY 同时为高」,而不是只要 TREADY 为高——漏掉这个保持条件,就是反压丢数据的头号根因。
四、常见 RTL 坑:组合环路与 VALID 依赖 READY
第一个高频坑是组合环路。如果写出 tready <= downstream_ready 组合直连,同时下游模块的 ready 又组合依赖本级输出的 valid,环路即成:valid → ready → valid。综合工具报 combinational loop,硅上行为完全不可预测。正确的 ready 必须以本地状态(寄存器满标志、skid buffer 占用位)为支点断开环路,而不是两侧信号直接对顶。
第二个坑更隐蔽:让 TVALID 组合依赖 TREADY。例如:
// 错误:ready 一低,valid 跟着变,协议违例
assign m_tvalid = s_tvalid && m_tready;
assign m_tdata = s_tdata;这违反第一节「TVALID 置起后不得依赖 TREADY、不得撤销」的硬规则。协议规定:决定 TVALID 的组合逻辑里不许出现 TREADY。正确写法是 TVALID 只由「我是否持有未发数据」这一寄存器状态决定;握手拍到了(valid && ready)才更新状态、接受新数据。
第三个坑是反压时提前覆盖输入寄存器。接收方在 TREADY 为低的周期照写输入寄存器,旧数据被新数据顶掉,而发送方以为还没被收走仍在保持——数据凭空丢失。寄存器写使能务必加上握手条件。第四是验证侧的坑:如果 driver/monitor 或现成 VIP 默认让 TREADY 恒高,反压路径在仿真里永远不被触发,上述三个坑全部漏到流片后。务必随机 TREADY 的拉低间隔与持续长度,并检查 stall 期间 TDATA 稳定,SVA 断言是最省事的手段。
五、正确写法:skid buffer 切断反压并吸收气泡
标准修法是在两级之间插入 skid buffer(也叫两拍寄存器缓冲)。它只存一拍数据,但带来两个关键性质:正常情况下输入到输出组合直通,不增加延迟;当输出侧反压时,把当前正在输出的数据「滑入」备用寄存器暂存,同时仍能在这一拍接收上游一个数据,之后再对上游拉低 TREADY。
效果是把上游看到的 TREADY 时序与下游的反压隔开一拍:ready 链被寄存器切断,组合环路和长 ready 路径同时消失,时序收敛难度大降;反压瞬间也不丢任何一个在途数据。完整的两拍寄存器 RTL、占用状态机与 ready 时序优化,Skid Buffer RTL 实现:两拍寄存器、反压吸收与 ready 时序优化 有逐行实现,这里不重复。
工程上的选型搭配是:偶发突发、需要跨时钟域时用 FIFO(深度算法定 FIFO 深度计算与设计:突发长度、读写速率与水位标志);同频、只为切时序和吸收一拍反压用 skid buffer,面积最省。AXI-Stream 在 DMA 与位宽适配场景的完整信号语义,另见 AXI4-Stream 与 DMA 数据流 和 AXI-Stream 位宽适配器。
这一篇在知识体系里的位置
握手概念与气泡基础见 valid/ready 握手:反压、气泡、Skid Buffer 与 AXI-Stream 基础;时序收敛侧的插桩见 AXI 寄存器切片;完整 AXI4 五通道与 burst 规则见 AXI4 完整协议:五通道、burst、outstanding 与 ID 保序;RTL 编码层面的通用规范见 可综合 RTL 编码规范:组合/时序分离、锁存器规避与位宽匹配。
总结
AXI-Stream 反压握手只在 TVALID 与 TREADY 同高的时钟沿传递数据:TVALID 置起后到握手前必须保持信号和载荷不变,TREADY 则可随时拉低制造气泡,VALID 先、READY 先、同拍三种情形外加无握手空闲都合法;多级流水线中某一级握手不上,其输入 TREADY 同拍拉低,stall 沿链路反向组合传播,各级寄存器只有在输出握手拍才允许更新;写 RTL 时要杜绝 ready 与 valid 对顶形成的组合环路、TVALID 组合依赖 TREADY、反压拍覆盖输入寄存器三类坑,并让验证环境随机拉低 TREADY 覆盖反压路径,标准答案是插入 skid buffer——一拍缓冲既吸收反压瞬间的在途数据,又切断 ready 组合链,兼顾不丢数据与时序收敛。