valid/ready 的反压是什么?为什么 valid 不能依赖 ready?
更新时间:2026-09-21。问题驱动短答页。握手规范见 valid-ready 握手,X/组合环问题见 valid/ready X 问题,缓冲深度见 FIFO 深度计算,AXI 见 AXI outstanding。
一句话回答
反压(backpressure)是流控:发送方拉高 valid 并把数据放到总线上,表示“我有一笔要传”;接收方当下能收就拉高 ready,暂时处理不过来(缓冲满、忙)就把 ready 拉低,发送方必须保持 valid 和数据不变,等到某拍 valid 与 ready 同时为高,这笔才真正交接。关键规则是 valid(及其数据)一旦发出就不能因为 ready 为低而撤销或改变;如果让 valid 反过来由 ready 组合决定,valid→下游组合→ready→valid 就构成组合环路,会振荡/死锁。ready 允许纯组合地提前给出。要切断长组合路径并支持反压下零等待,常用 skid buffer(弹性寄存器)。
握手规则(典型 AXI-Stream 风格)
- 交接发生在
valid && ready同一拍。 - valid/data:拉高后保持,直到握手;不得等待 ready 才决定是否 valid。
- ready:可随时高低,可组合产生;建议在 reset 后有安全默认。
- 反压链路上每一级都要能把“收不下”往上游传播,且不能丢已握手的数据。
为什么 valid 依赖 ready 会出环
bash
valid = f(ready) // 错:上游
ready = g(valid, full)// 下游两者纯组合互相喂给,形成没有存储元件打断的环 → 组合环路,见 组合环路 vs latch 和 X 问题。正确方向是:valid 由源端自己的状态(有无数据)决定,ready 只决定何时取走。
skid buffer 的作用
- 下游 ready 来得晚或路径长时,在中间插一级 skid buffer:即使下拍 ready 突然拉低,也能把当前这笔先“滑”进缓冲,保证接口仍可完成一次交接。
- 解耦两侧时序,打断 ready 组合长链,是高频流接口的标准做法。
- 更深的突发速率不匹配用 FIFO,见 FIFO 深度、异步 FIFO。
常见坑
- ready 低时上游改了 data,接收端锁存到错误值。
- valid 由 ready 组合生成造成环路,综合报警、硬件振荡。
- ready 默认拉高又无缓冲,复位/满状态切换瞬间吞数据。
- 反压没逐级传播,中间级覆盖了未被取走的数据。
- valid/ready 信号出现 X 后仿真与门级行为分叉,见 X 问题。
总结
反压就是下游用 ready 告诉上游“现在收不动”,上游必须保持 valid 和数据稳定直到同拍握手完成;valid 只能由源端有无数据决定、绝不能组合依赖 ready,否则形成 valid-ready 组合环路导致振荡死锁。高频或 ready 路径长时用 skid buffer 切断时序并支持零等待反压,速率不匹配再加深为 FIFO,整条反压链必须逐级传播且不丢已交接的数据。