Altifigence Academy

61 / 63 · 概念

可暫停管線與背壓

計算各級 ready,在暫停與同時移動時避免資料遺失、重複或重新計算。

接收端無法每次都接受時

先備知識:單格 ready/valid交握(handshake)規定傳送端的 valid 與接收端的 ready 在同一邊緣皆為 1 時,才確定完成傳輸。等待期間如何保持資料也是契約的一部分。 詳細內容 緩衝區與管線管線以暫存器將計算分為多個階段,讓多筆輸入重疊處理。資料、valid 與控制訊號必須在各階段對齊。 詳細內容資料對齊。

固定速率管線只加 out_ready 阻擋輸出並不足夠。最後一級滿而停住時,前級也不能被覆寫,必須設計往輸入方向傳遞停頓的背壓背壓(backpressure)由接收端通知傳送端暫時無法接收,藉此停止資料流。停止期間必須保存尚未傳出的資料。 詳細內容。

兩級各用一筆資料與一個 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,只要第一級空,就能再接一筆,比「輸出停就拒絕所有輸入」更能利用空間。

各級只在允許移動時更新

範例對 unsigned無符號(unsigned)將位元序列解讀為非負整數。n 位元範圍為 0 至 2^n−1;相同位元序列的帶符號解讀可能得到不同數值。 詳細內容 8 位元 x 計算 y=2(x+1)。第一級以 9 位元存 x+1,第二級擴至 10 位元左移一位,可精確表示最大輸入 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

因 nonblocking非阻塞賦值(nonblocking)在循序 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 就會遺失。

下圖各欄為上升緣上升緣是時脈由 0 變成 1 的瞬間。它與表示整段 CLK=1 期間的高準位不同。 詳細內容前值。起初最後級 A、第一級 B、輸入 C 等待。E2 傳 A 並接 C,E3 前輸出變成 B。

兩個階段都滿時的背壓
查看波形資料
波形資料:每個字元表示一個區間;句點保持先前狀態;p 表示一個時脈週期。
訊號波形匯流排值
邊緣2345E0 → E1 → E2 → E3
out_ready0.1.
out_valid1...
out_data2..3A → B
in_valid1...
in_ready0.1.
in_data2..3C → D

需要驗證的守恆關係

Reset 後輸入接受數為 Nin、輸出傳送數為 Nout,儲存量如下。Reset 邊緣不計傳送。

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,涵蓋長時間暫停、連續處理與 reset 清空。

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,便不能再接。這個差別讓兩格儲存空間真正被使用。

此選擇適用於本瀏覽器,隨時可從頁尾變更。