61 / 63 · 概念
可暫停管線與背壓
計算各級 ready,在暫停與同時移動時避免資料遺失、重複或重新計算。
單元可免費閱讀,註冊課程即可儲存學習進度。
接收端無法每次都接受時
先備知識:單格 ready/valid交握(handshake)規定傳送端的 valid 與接收端的 ready 在同一邊緣皆為 1 時,才確定完成傳輸。等待期間如何保持資料也是契約的一部分。 詳細內容 緩衝區與管線管線以暫存器將計算分為多個階段,讓多筆輸入重疊處理。資料、valid 與控制訊號必須在各階段對齊。 詳細內容資料對齊。
固定速率管線只加 out_ready 阻擋輸出並不足夠。最後一級滿而停住時,前級也不能被覆寫,必須設計往輸入方向傳遞停頓的背壓背壓(backpressure)由接收端通知傳送端暫時無法接收,藉此停止資料流。停止期間必須保存尚未傳出的資料。 詳細內容。
兩級各用一筆資料與一個 valid 位元表示。第二級在空或本邊緣可送出目前資料時能接新值,第一級也用同規則。
外部 in_ready 為 r1。即使 r2=0,只要第一級空,就能再接一筆,比「輸出停就拒絕所有輸入」更能利用空間。
各級只在允許移動時更新
範例對 unsigned無符號(unsigned)將位元序列解讀為非負整數。n 位元範圍為 0 至 2^n−1;相同位元序列的帶符號解讀可能得到不同數值。 詳細內容 8 位元 x 計算 y=2(x+1)。第一級以 9 位元存 x+1,第二級擴至 10 位元左移一位,可精確表示最大輸入 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因 nonblocking非阻塞賦值(nonblocking)在循序 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 就會遺失。
下圖各欄為上升緣上升緣是時脈由 0 變成 1 的瞬間。它與表示整段 CLK=1 期間的高準位不同。 詳細內容前值。起初最後級 A、第一級 B、輸入 C 等待。E2 傳 A 並接 C,E3 前輸出變成 B。
查看波形資料
| 訊號 | 波形 | 匯流排值 |
|---|---|---|
| 邊緣 | 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 |
需要驗證的守恆關係
Reset 後輸入接受數為 Nin、輸出傳送數為 Nout,儲存量如下。Reset 邊緣不計傳送。
數量正確仍可能漏掉「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,便不能再接。這個差別讓兩格儲存空間真正被使用。