31 / 37 · 概念
乘加管線與資料對齊
以暫存器邊界切分運算,讓資料、valid 與輔助運算元屬於同一交易。
單元可免費閱讀,註冊課程即可儲存學習進度。
從運算式切成兩級
先備知識:signed 算術、nonblocking非阻塞賦值(nonblocking)在循序 RTL 中以 <= 表示。它先求右側運算式的值,再排程更新,讓同一邊緣的暫存器都能依據先前狀態計算。 詳細內容 指定、setup建立時間(setup)是輸入資料在時脈擷取邊緣之前,必須保持穩定的最短時間。若違反此條件,便無法保證儲存結果。 詳細內容 與 valid 訊號。
每筆交易包含 signed 8 位元 a、b 與 signed 16 位元 c,結果如下。這是各交易獨立的 multiply-add,不是累加器。
8 位元乘積的精確結果需要 16 位元。加 c 時若先用 16 位元運算再擴展,無法恢復已失去的高位。必須先把兩運算元符號擴展為 17 位元再相加。
第一級一起存乘積與 c,第二級相加同一交易的兩值。若不延遲 c,會把上一交易乘積與目前交易 c 混用。
module multiply_add_pipeline (
input logic clk, rst, in_valid,
input logic signed [7:0] a, b,
input logic signed [15:0] c,
output logic out_valid,
output logic signed [16:0] y
);
logic v1;
logic signed [15:0] p1, c1;
logic signed [16:0] p_ext, c_ext;
assign p_ext = {p1[15], p1};
assign c_ext = {c1[15], c1};
always_ff @(posedge clk) begin
if (rst) begin
v1 <= 1'b0;
out_valid <= 1'b0;
end else begin
v1 <= in_valid;
out_valid <= v1;
if (in_valid) begin
p1 <= a * b;
c1 <= c;
end
if (v1) y <= p_ext + c_ext;
end
end
endmodule此介面每邊緣可接輸入,也假設接收端永遠能接輸出。Out_valid=0 的 y 不比較。即使不重設重設將狀態回復至規格指定的初始值。必須一併定義它是同步或非同步,以及是否優先於其他控制訊號。 詳細內容資料暫存器暫存器儲存多個位元的狀態。本課程中的同步暫存器會在時脈邊緣儲存指定的輸入。 詳細內容,只初始化 valid 也能分辨未使用資料。
區分「兩級」與觀察時點
下表在各邊緣接受輸入,記錄邊緣後的暫存器狀態。A、B 是不同交易。
| 邊緣 | 接受輸入 | 第一級 | 輸出暫存器 |
|---|---|---|---|
| E0 | A | A 的乘積與 c | invalid |
| E1 | B | B 的乘積與 c | A 結果、valid |
| E2 | 無 | invalid | B 結果、valid |
| E3 | 無 | invalid | invalid |
A 結果在 E1 後準備好,同時脈的下級於 E2 取樣。因此輸入接受 E0 到輸出接收 E2 為兩週期。說明延遲時,不要混淆輸出暫存器變動與下級接收的時點。
每欄是一次上升緣上升緣是時脈由 0 變成 1 的瞬間。它與表示整段 CLK=1 期間的高準位不同。 詳細內容的觀察紀錄。輸入為邊緣前值,名稱含「後」的狀態為更新後值。欄位對齊表示取樣順序,並未繪出實體傳播延遲傳播延遲是輸入改變後,輸出穩定至正確值所需的時間。邏輯式是否等價與時間特性是兩個不同問題。 詳細內容。
交易 A=(2,3,10)、B=(4,5,100)。第一級一起儲存乘積與 c,下一邊緣將舊級的兩值相加。破折號為 invalid 區間。
查看波形資料
| 訊號 | 波形 | 匯流排值 |
|---|---|---|
| 邊緣 | 2345 | E0 → E1 → E2 → E3 |
| 已接受 | 234. | A → B → - |
| product1 後 | 234. | 6 → 20 → - |
| c1 後 | 234. | 10 → 100 → - |
| y 後 | 2345 | - → 16 → 120 → - |
| out_valid 後 | 01.0 |
分割管線能快多少
用簡化模型:乘法延遲 3.2 ns、加法 1.1 ns、暫存器額外成本 0.2 ns,這些都是計算假設。
最大頻率上限約由 222 MHz 變成 294 MHz。兩級不一定讓吞吐量加倍,最慢級與暫存器成本才決定週期。實際結果依合成、配置與約束而變。
以交易為單位驗證
接受輸入時,將整數參考模型 a×b+c 放入佇列;接收輸出 valid 的邊緣,取出頭部期待值比較。插入 in_valid=0 的區段,確認 bubble 隨資料一起移動。每筆交易大幅改變 c,特別容易揭露漏延遲問題。
自己試試看
連續輸入 A=(a=3,b=−4,c=10)、B=(a=2,b=5,c=100)。求正確輸出順序,以及 c 不延遲、直接加目前 c 時,A 可能產生的錯誤結果。
查看解說
正確為 A:−12+10=−2,B:10+100=110。A 乘積在第二級時若加到 B 的目前 c=100,就得到 88。即使 valid 正確延遲,運算元資料未對齊仍會錯。