valid/ready 握手里的“X 问题”和组合环是什么?
更新时间:2026-09-21。问题驱动短答页。握手实现与时序见 valid-ready 握手,时序解耦见 skid buffer。
一句话回答
valid/ready 协议里,一笔传输发生在 valid && ready 同拍为高时。两个铁律是:valid(及数据)一旦置起就不能因为 ready 没好而撤回,ready 可以根据自己有没有空来决定。常见错误一是让 valid 组合依赖 ready、或 ready 又依赖 valid 形成组合环路;二是上电/复位时握手信号没赋确定值(尤其来自未初始化存储或跨域),出现 X 并沿数据通路传播,仿真卡 X、硅上行为不定。正确做法是给 valid/ready 明确复位默认值、valid 只由自己的状态决定,需要打断长组合路径时插入 skid buffer(弹性缓冲)。
协议规则
- 发送端:
valid=1后数据保持稳定,直到当拍ready=1完成握手;不能“看 ready 脸色”撤销。 - 接收端:
ready=1表示本拍能收;它可以等 valid,也可以提前拉好。 - 完成条件:同拍
valid & ready。
两种典型 bug
verilog
// 错误:valid 依赖 ready,可能与上游/下游形成组合环
assign valid = ready & data_valid;
// 错误:未初始化,valid 可能是 X,X & ready = X,仿真全链路污染
reg valid; // 复位里没赋值- 组合环:
ready = f(valid)而valid = g(ready),零延时环路,STA 不收敛,见 组合环路。 - X 传播:valid/data 为 X 时,
if(valid)在 2 态 vs 4 态仿真分叉,下游寄存器被 X 污染;门级仿真尤其明显。
正确做法
- valid/ready 都在复位里给确定初值(通常 ready 复位为 1 或按可接收状态置位,valid 复位为 0)。
- valid 由发送端“是否有数据 + 是否已被接收”的时序状态决定,不组合依赖 ready。
- 用 skid buffer 打断 valid/ready 串起来的长组合路径,支持反压且改善时序。
- 上游数据来自存储器时,先把有效标志位做确定复位或用有效位限定,避免 X 扩散。
常见坑
- valid 没好就先变数据,或握手未完成就改数据。
- ready 直接组合穿过很多级,时序违例。
- 复位不全,X 从 RAM/跨域进入握手链。
- 测试用例只测 ready 恒高,不压反压(ready 拉低)场景。
总结
valid/ready 在两者同拍为高时完成传输,valid 一旦置起必须保持、不能依赖 ready,ready 可按自身空间决定;要避免 valid 与 ready 互相组合依赖造成环路,并给握手信号确定的复位默认值防止 X 沿数据通路传播,跨多级时序紧张时用 skid buffer 解耦并务必验证反压场景。