Altifigence Academy

62 / 63 · 概念

暫存器介面與副作用的發生時點

指定地址、位元組寫入與回應暫停,讓每個請求恰好導致一次狀態變更。

定義「寫入暫存器」的行為

先備知識:位址解碼器解碼器啟用與二進位碼對應的輸出線。若有 enable,可在未啟用時將所有輸出設為 0。 詳細內容、ready/valid交握(handshake)規定傳送端的 valid 與接收端的 ready 在同一邊緣皆為 1 時,才確定完成傳輸。等待期間如何保持資料也是契約的一部分。 詳細內容、enable 與狀態更新優先權。

把設定暫存器暫存器儲存多個位元的狀態。本課程中的同步暫存器會在時脈邊緣儲存指定的輸入。 詳細內容接到外部控制器,不能只確認地址正確。還須定義請求接受時點、回應等待時的保持條件,以及寫唯讀地址的處理。此處用同時脈的簡單單請求、單回應介面。

accept=req_valid∧req_ready\mathrm{accept}=\mathrm{req\_valid}\land\mathrm{req\_ready}

下列為位元組地址,採 32 位元對齊。每個請求恰好產生一個成功或錯誤回應。

地址名稱行為
0x0CONFIG可讀寫,套用 byte strobe
0x4STATUS唯讀,回傳接受時的值
0x8COMMAND讀為 0,寫 byte 0 的 bit 0 產生 start pulse
其他未定義錯誤回應,不改狀態

回應槽空或即將清空的邊緣才接受

SystemVerilog
module register_interface (
    input  logic        clk, rst,
    input  logic        req_valid, req_write,
    output logic        req_ready,
    input  logic [3:0]  req_addr,
    input  logic [31:0] req_wdata,
    input  logic [3:0]  req_wstrb,
    output logic        rsp_valid,
    input  logic        rsp_ready,
    output logic [31:0] rsp_rdata,
    output logic        rsp_error,
    input  logic [31:0] status_value,
    output logic [31:0] config_value,
    output logic        start_pulse
);
    assign req_ready = !rsp_valid || rsp_ready;
    always_ff @(posedge clk) begin
        if (rst) begin
            rsp_valid    <= 1'b0;
            config_value <= 32'd0;
            start_pulse  <= 1'b0;
        end else begin
            start_pulse <= 1'b0;
            if (req_ready) begin
                rsp_valid <= req_valid;
                if (req_valid) begin
                    rsp_rdata <= 32'd0;
                    rsp_error <= 1'b0;
                    case (req_addr)
                        4'h0: begin
                            if (req_write) begin
                                for (int i=0; i<4; i++)
                                    if (req_wstrb[i])
                                        config_value[8*i +: 8]
                                            <= req_wdata[8*i +: 8];
                            end else rsp_rdata <= config_value;
                        end
                        4'h4: begin
                            if (req_write) rsp_error <= 1'b1;
                            else rsp_rdata <= status_value;
                        end
                        4'h8: begin
                            if (req_write)
                                start_pulse <= req_wstrb[0] && req_wdata[0];
                        end
                        default: rsp_error <= 1'b1;
                    endcase
                end
            end
        end
    end
endmodule

回應受阻時 req_ready=0,因此 config 寫入與 command pulse 不會再執行。已接受請求的副作用可能已發生,只有回應在等待。若因回應延遲就無條件重送,可能重複執行命令。

計算 byte strobe 的意義

CONFIG=32'h11223344 時寫入 req_wdata=32'hAABBCCDD、req_wstrb=4'b0101,只改 byte 0、byte 2,結果為 32'h11BB33DD。地址對齊、位元位置與記憶體位元組順序應分別確認。wstrb=0000 的寫入成功回應,但不改值。

從 MSBMSB是位權最高的位元。索引編號會隨向量的宣告方向而異,因此不能一律假設它的編號最大。 詳細內容 起為 byte3,2,1,0。Strobe=0101 選 byte2、byte0,因此只寫新 BB、DD。Strobe 是位元組單位 write enable,不是單一位元選擇。

只改變 byte strobe 選中的位元組
  1. 原有 CONFIG: 11 | 22 | 33 | 44
  2. 寫入資料: AA | BB | CC | DD
  3. strobe 0101: 保持 · 替換 · 保持 · 替換
  4. 新的 CONFIG: 11 | BB | 33 | DD

狀態是哪個時點的值

STATUS 的讀取回應會儲存請求接受時的 status_value。之後回應暫停,即使實際 status 改變,rsp_rdata 仍保持。rsp_valid=1、rsp_ready=0 時若直接把組合 status 接到回應,內容會改變,違反協定。

連續邊緣 req_valid、req_ready 都為 1,表示兩個不同請求。請求被接受後,傳送端須降 valid 或更新成下一請求,不能一直保留同一請求卻期待只處理一次。

驗證的三個面向

  1. 位址與權限:檢查有效、未對齊、未定義地址與 STATUS 寫入的錯誤及副作用。
  2. 資料選擇:窮舉四個 strobe 位元,確認未啟用 byte 保留。
  3. 流量控制:阻擋回應多週期時,回應與狀態保持;同時消費回應、接受下個請求時,交易數也須一致。

自己試試看

接受 req_wstrb[0]=1、req_wdata[0]=1 的 COMMAND 寫入後,rsp_ready=0 維持三週期。Start_pulse 應重複三週期嗎?STATUS 寫入可以改 config_value 嗎?

查看解說

Start_pulse 只在請求接受後一週期為 1,之後為 0。回應暫停不是重複執行命令的條件。STATUS 寫入應回錯誤,不改 config_value 等其他狀態。回應完成前的重試政策,也需由收發雙方約定。

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