56 / 63 · 概念
雙讀單寫暫存器檔案與旁路
實作獨立雙讀埠與同步寫入,核對各位址碰撞的旁路、初始化及 valid 政策。
單元可免費閱讀,註冊課程即可儲存學習進度。
同時取出兩個值的儲存結構
運算器計算 A+B 時,需要同週期取得兩運算元。2-read/1-write 暫存器暫存器儲存多個位元的狀態。本課程中的同步暫存器會在時脈邊緣儲存指定的輸入。 詳細內容檔案提供兩個讀位址與一個寫位址。此處存八個 16 位元字,兩個讀取都在上升緣暫存。位址寬 3 位元、容量 8×16=128 位元,位址 0 也是一般儲存,沒有特殊常數暫存器規則。
各讀埠有獨立 enable、valid。一埠休息不影響另一埠,也可同時讀同址。同時讀兩個不同位址的能力,成本不同於單純增加容量。小電路可用正反器正反器在指定的時脈邊緣儲存輸入,並保持至下一個邊緣。輸入須滿足 setup 與 hold 條件。 詳細內容陣列與兩組選擇網路;採特定 RAM 時,也可能複製儲存體並同步送寫入以取得讀埠數。不能只憑 RTL 宣告確定合成資源。
正在寫的值也是現在要讀的值
本契約規定同邊緣讀寫同址時,回應新寫入資料。Bypass 直接將 wr_data 送到讀取輸出暫存器的輸入端,不等陣列更新。埠 的碰撞條件為:
時,回應為:
是邊緣前儲存值, 必須分別比較各讀位址。不能因一埠碰撞,就把寫資料送給兩埠,否則另一位址運算元也被改掉。若漏了 wr_en,即使沒有實際寫入,也可能因 wr_addr 恰好相同而錯誤旁路。
module regfile8x16_2r1w (
input logic clk, rst, wr_en,
input logic [2:0] wr_addr,
input logic [15:0] wr_data,
input logic rd_en0, rd_en1,
input logic [2:0] rd_addr0, rd_addr1,
output logic [15:0] rd_data0, rd_data1,
output logic rd_valid0, rd_valid1
);
timeunit 1ns;
timeprecision 1ps;
logic [15:0] mem [0:7];
always_ff @(posedge clk) begin
if (rst) begin
rd_valid0 <= 1'b0;
rd_valid1 <= 1'b0;
end else begin
rd_valid0 <= rd_en0;
rd_valid1 <= rd_en1;
if (wr_en)
mem[wr_addr] <= wr_data;
if (rd_en0)
rd_data0 <= (wr_en && wr_addr == rd_addr0)
? wr_data : mem[rd_addr0];
if (rd_en1)
rd_data1 <= (wr_en && wr_addr == rd_addr1)
? wr_data : mem[rd_addr1];
end
end
endmoduleBypass 改變輸入選擇,但不移除輸出暫存級。位址、請求在邊緣前提出,回應在後觀察,下游暫存器於下一上升緣取得。改成組合讀取會連地址到輸出的路徑與延遲契約一起改變,不能只當程式縮寫。
範例:只有一個埠碰撞
預先存 M[2]=12、M[5]=7。E0 前開啟兩讀取,設 rd_addr0=2、rd_addr1=5、wr_en=1、wr_addr=2、wr_data=20。E0 後埠 0 回應旁路 20,埠 1 回應儲存的 7,兩個有效回應相加得 27,不同於無旁路 read-first 的 19。
E1 兩讀位址都設 2,同址寫 30,兩輸出都是 30。E2 設 wr_en=0、wr_addr=2、wr_data=99,讀 2 時兩輸出都應為 30,這一週期便可揭露只比地址的旁路錯誤。E3 若 rd_en0=0、rd_en1=1,埠 0 valid=0,埠 1 valid=1。
每欄是一次上升緣上升緣是時脈由 0 變成 1 的瞬間。它與表示整段 CLK=1 期間的高準位不同。 詳細內容的觀察紀錄。輸入為邊緣前值,名稱含「後」的狀態為更新後值。欄位對齊表示取樣順序,並未繪出實體傳播延遲傳播延遲是輸入改變後,輸出穩定至正確值所需的時間。邏輯式是否等價與時間特性是兩個不同問題。 詳細內容。
已預存 M[2]=12、M[5]=7,兩讀 enable 永遠 1,寫位址為 2。最後一欄 wr_en=0,不能旁路 wr_data=99。
查看波形資料
| 訊號 | 波形 | 匯流排值 |
|---|---|---|
| 邊緣 | 234 | E0 → E1 → E2 |
| wr_en | 1.0 | |
| wr_data | 234 | 20 → 30 → 99 |
| rd_addr0 | 2.. | 2 |
| rd_addr1 | 23. | 5 → 2 |
| out0 後 | 23. | 20 → 30 |
| out1 後 | 23. | 7 → 30 |
需要初始化哪些內容
高有效同步 reset 阻止寫入,並將兩個 valid 清零,但不重設陣列與輸出資料。因此 reset 後輸出匯流排仍保留舊值,只要 valid=0 就正常。此 RTL 不會清除既有陣列內容;若系統 reset 後只允許新工作,應另定該工作的初始化順序。
第一次寫某地址並同邊緣讀取,此實作可透過 bypass 定義新值。但沒有寫入而讀從未初始化的位址,仍為未定。Rd_valid 是請求回應時點,不是位址 initialized 位元。驗證器建立一般讀預期值前,須確認該地址已知,並另外處理同邊緣 bypass。
驗證包括兩讀 enable 四組、同址或異址、寫入碰撞無埠/埠 0/埠 1/兩埠、連續寫入及 reset 優先權。多寫埠超出本課範圍;若增加,須先重新定義同址雙寫的優先權。埠數改變,功能契約與資源成本都會改變。
自己試試看
M[1]=4、M[4]=9,兩讀取 enable=1、位址為 1 與 4,同時向 4 寫 13,輸出對為何?下一邊緣 wr_en=0、wr_addr=1、wr_data=99、兩讀位址都為 1 呢?最後只關閉埠 0 enable,說明 valid 與資料消費規則。
查看解說
第一組回應為 (4,13),只有埠 1 與寫位址碰撞,旁路新值 13。下一組為 (4,4),wr_en=0,不能用 99。最後 rd_valid0=0、rd_valid1=1;埠 0 資料暫存器保持舊值,但不得當有效回應消費。位址 0 也與其他位址相同,可正常讀寫。