Altifigence Academy

56 / 63 · 概念

雙讀單寫暫存器檔案與旁路

實作獨立雙讀埠與同步寫入,核對各位址碰撞的旁路、初始化及 valid 政策。

同時取出兩個值的儲存結構

運算器計算 A+B 時,需要同週期取得兩運算元。2-read/1-write 暫存器暫存器儲存多個位元的狀態。本課程中的同步暫存器會在時脈邊緣儲存指定的輸入。 詳細內容檔案提供兩個讀位址與一個寫位址。此處存八個 16 位元字,兩個讀取都在上升緣暫存。位址寬 3 位元、容量 8×16=128 位元,位址 0 也是一般儲存,沒有特殊常數暫存器規則。

各讀埠有獨立 enable、valid。一埠休息不影響另一埠,也可同時讀同址。同時讀兩個不同位址的能力,成本不同於單純增加容量。小電路可用正反器正反器在指定的時脈邊緣儲存輸入,並保持至下一個邊緣。輸入須滿足 setup 與 hold 條件。 詳細內容陣列與兩組選擇網路;採特定 RAM 時,也可能複製儲存體並同步送寫入以取得讀埠數。不能只憑 RTL 宣告確定合成資源。

正在寫的值也是現在要讀的值

本契約規定同邊緣讀寫同址時,回應新寫入資料。Bypass 直接將 wr_data 送到讀取輸出暫存器的輸入端,不等陣列更新。埠 ii 的碰撞條件為:

Hi=wr_en∧(wr_addr=rd_addri)H_i=\mathrm{wr\_en}\land(\mathrm{wr\_addr}=\mathrm{rd\_addr}_i)

rd_eni=1\mathrm{rd\_en}_i=1 時,回應為:

Ri+={wr_data,Hi=1M−[rd_addri],Hi=0R_i^{+}=\begin{cases} \mathrm{wr\_data}, & H_i=1\\ M^{-}[\mathrm{rd\_addr}_i], & H_i=0 \end{cases}

M−M^{-} 是邊緣前儲存值,HiH_i 必須分別比較各讀位址。不能因一埠碰撞,就把寫資料送給兩埠,否則另一位址運算元也被改掉。若漏了 wr_en,即使沒有實際寫入,也可能因 wr_addr 恰好相同而錯誤旁路。

SystemVerilog
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
endmodule

Bypass 改變輸入選擇,但不移除輸出暫存級。位址、請求在邊緣前提出,回應在後觀察,下游暫存器於下一上升緣取得。改成組合讀取會連地址到輸出的路徑與延遲契約一起改變,不能只當程式縮寫。

範例:只有一個埠碰撞

預先存 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。

同一次寫入下,兩個埠仍各自獨立選擇
查看波形資料
波形資料:每個字元表示一個區間;句點保持先前狀態;p 表示一個時脈週期。
訊號波形匯流排值
邊緣234E0 → E1 → E2
wr_en1.0
wr_data23420 → 30 → 99
rd_addr02..2
rd_addr123.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 也與其他位址相同,可正常讀寫。

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