61 / 63 · 概念
可暂停流水线与背压
逐级计算 ready,在暂停与同时移动过程中防止数据丢失、重复和重复计算。
课时内容可免费阅读,选课后可保存学习进度。
如果接收方不能每次都接收
先修知识:单槽 ready/valid握手 发送端 valid 与接收端 ready 在同一边沿均为 1 时,确认传输的约定,也包括等待期间的数据保持规则。了解更多 缓冲区与流水线流水线 用寄存器把计算划分为多个阶段,使多个输入能够重叠处理的结构。数据、valid 与控制信号必须在各级对齐。了解更多数据对齐。
给固定速率流水线只加一个 out_ready 来阻止输出还不够。末级已满而停住时,前一级也不能覆盖数据。必须设计把暂停请求传向输入端的背压背压 接收方通知发送方暂时无法接收,从而暂停数据流的机制。暂停期间必须保留尚未传输的数据。了解更多。
两级各用一项数据和一位 valid 表示。第二级为空,或当前输出能送出时,就能接收新值;对第一级应用同样规则。
外部 in_ready 等于 r1。即使 r2=0,只要第一级为空,仍能接收一个新输入。相比“输出暂停就无条件拒绝所有输入”,这能更充分利用存储空间。
各级只在允许移动时更新
下例对 unsignedunsigned 将位串解释为非负整数的规则。n 位范围为 0 到 2^n−1,可能与同一位串的 signed 解释不同。了解更多 八位 x 计算 y=2(x+1)。第一级用九位存储 x+1,第二级在十位范围内左移一位,能精确表示最大输入 255 对应的结果 512。
module stallable_pipeline (
input logic clk, rst,
input logic in_valid,
output logic in_ready,
input logic [7:0] in_data,
output logic out_valid,
input logic out_ready,
output logic [9:0] out_data
);
logic v1, v2, r1, r2;
logic [8:0] d1;
logic [9:0] d2;
assign r2 = !v2 || out_ready;
assign r1 = !v1 || r2;
assign in_ready = r1;
assign out_valid = v2;
assign out_data = d2;
always_ff @(posedge clk) begin
if (rst) begin
v1 <= 1'b0;
v2 <= 1'b0;
end else begin
if (r2) begin
v2 <= v1;
if (v1) d2 <= {d1, 1'b0};
end
if (r1) begin
v1 <= in_valid;
if (in_valid) d1 <= {1'b0, in_data} + 9'd1;
end
end
end
endmodule由于使用非阻塞非阻塞赋值 时序 RTL 中以 <= 表示的赋值。先计算右侧,再预约更新,使同一边沿的各寄存器能够依据旧状态计算。了解更多赋值,第二级接收旧 d1,而不是同一边沿刚计算的新 d1。r1=0 时保持 v1、d1,r2=0 时保持 v2、d2。只保持 valid,却继续更新数据,是错误实现。
两级都满时的追踪
假设 v2 中是 A 的结果,v1 中是 B 的中间值,输入 C 正在等待。
| out_ready | in_ready | 边沿上的行为 |
|---|---|---|
| 0 | 0 | 保持 A、B,不接受 C |
| 0 | 0 | 保持 A、B,不接受 C |
| 1 | 1 | 传出 A,B 移至第二级,接受 C |
发送方必须保持 C 与 in_valid,直到 C 被接受。若误以为第一个暂停边沿已发送 C,并换成下一数据,C 就会丢失。
每列表示上升沿上升沿 时钟从 0 变为 1 的瞬间。它不同于表示整个 CLK=1 区间的电平。了解更多之前的值。初始末级有 A、第一级有 B,C 在输入端等待。E2 传出 A 并接受 C 后,E3 之前输出已变为 B。
查看波形数据
| 信号 | 波形 | 总线值 |
|---|---|---|
| edge | 2345 | E0 → E1 → E2 → E3 |
| out_ready | 0.1. | |
| out_valid | 1... | |
| out_data | 2..3 | A → B |
| in_valid | 1... | |
| in_ready | 0.1. | |
| in_data | 2..3 | C → D |
需要验证的守恒关系
设复位后接受输入次数为 Nin、输出传输次数为 Nout,则存储量满足下式。复位边沿不计传输。
仅检查计数,可能漏掉重复输出 A 而丢掉 B 的错误,因此还要用参考队列检查数值与顺序。让输入 valid 与输出 ready 独立变化,包含长时间暂停、连续处理和复位清空。
ready 路径也是时序路径
连接很多级时,r2→r1 这样的反向组合路径也会变长。若用一个寄存器延迟 ready,可能需要额外空间保存这段延迟期间已经承诺接收的输入。不考虑存储空间与协议,只给 ready 加一个触发器,并不是安全的时序优化。
自己试试
v1=0、v2=1、out_ready=0 时,能否接受 in_valid=1 的输入?下一周期 out_ready 仍为 0,能否继续接收更多输入?
阅读解释
起初 r2=0,但 r1=1,所以可接受一个数据填满第一级。边沿后若 v1=v2=1,则 r1=r2=0,不能再接受。这一区别正是实际利用两个存储槽位的条件。