Altifigence Academy

61 / 63 · 概念

可暂停流水线与背压

逐级计算 ready,在暂停与同时移动过程中防止数据丢失、重复和重复计算。

如果接收方不能每次都接收

先修知识:单槽 ready/valid握手 发送端 valid 与接收端 ready 在同一边沿均为 1 时,确认传输的约定,也包括等待期间的数据保持规则。了解更多 缓冲区与流水线流水线 用寄存器把计算划分为多个阶段,使多个输入能够重叠处理的结构。数据、valid 与控制信号必须在各级对齐。了解更多数据对齐。

给固定速率流水线只加一个 out_ready 来阻止输出还不够。末级已满而停住时,前一级也不能覆盖数据。必须设计把暂停请求传向输入端的背压背压 接收方通知发送方暂时无法接收,从而暂停数据流的机制。暂停期间必须保留尚未传输的数据。了解更多。

两级各用一项数据和一位 valid 表示。第二级为空,或当前输出能送出时,就能接收新值;对第一级应用同样规则。

r2=¬v2∨out_ready,r1=¬v1∨r2r_2=\neg v_2\lor\mathrm{out\_ready},\qquad r_1=\neg v_1\lor r_2

外部 in_ready 等于 r1。即使 r2=0,只要第一级为空,仍能接收一个新输入。相比“输出暂停就无条件拒绝所有输入”,这能更充分利用存储空间。

各级只在允许移动时更新

下例对 unsignedunsigned 将位串解释为非负整数的规则。n 位范围为 0 到 2^n−1,可能与同一位串的 signed 解释不同。了解更多 八位 x 计算 y=2(x+1)。第一级用九位存储 x+1,第二级在十位范围内左移一位,能精确表示最大输入 255 对应的结果 512。

SystemVerilog
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_readyin_ready边沿上的行为
00保持 A、B,不接受 C
00保持 A、B,不接受 C
11传出 A,B 移至第二级,接受 C

发送方必须保持 C 与 in_valid,直到 C 被接受。若误以为第一个暂停边沿已发送 C,并换成下一数据,C 就会丢失。

每列表示上升沿上升沿 时钟从 0 变为 1 的瞬间。它不同于表示整个 CLK=1 区间的电平。了解更多之前的值。初始末级有 A、第一级有 B,C 在输入端等待。E2 传出 A 并接受 C 后,E3 之前输出已变为 B。

两级都满时的背压
查看波形数据
波形数据:每个字符表示一个区间,点表示保持前一状态,p 表示一个时钟周期。
信号波形总线值
edge2345E0 → E1 → E2 → E3
out_ready0.1.
out_valid1...
out_data2..3A → B
in_valid1...
in_ready0.1.
in_data2..3C → D

需要验证的守恒关系

设复位后接受输入次数为 Nin、输出传输次数为 Nout,则存储量满足下式。复位边沿不计传输。

Nin−Nout=v1+v2,0≤Nin−Nout≤2N_{\mathrm{in}}-N_{\mathrm{out}}=v_1+v_2,\qquad 0\le N_{\mathrm{in}}-N_{\mathrm{out}}\le2

仅检查计数,可能漏掉重复输出 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,不能再接受。这一区别正是实际利用两个存储槽位的条件。

你的选择适用于此浏览器,可随时在页脚更改。