Altifigence Academy

62 / 63 · Concept

Register interfaces and the timing of side effects

Specify addresses, byte writes, and response stalls so each request causes exactly one state-changing action.

Define what “writing a register” means

Prerequisites: address decodersDecoder A circuit that activates the output line corresponding to a binary code. With an enable input, all outputs can be set to 0 when disabled. Learn more, ready/validHandshake A contract that accepts a transfer when the sender's valid and the receiver's ready are both 1 at the same edge. It also defines how data must be held while waiting. Learn more, enable, and state-update priorities.

Connecting configuration registersRegister A circuit that stores multiple bits of state. The synchronous registers in this course store their specified inputs at a clock edge. Learn more to an external controller requires more than checking an address match. Define when a request is accepted, what must remain stable while a response waits, and what happens on a write to a read-only address. Here we use a simple single-request/single-response interface in one clock domain.

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

The addresses below are byte addresses with 32-bit alignment. Every request produces exactly one success or error response.

AddressNameBehavior
0x0CONFIGRead/write, with byte strobes
0x4STATUSRead-only; return the value at acceptance
0x8COMMANDReads return 0; writing bit 0 of byte 0 produces a start pulse
OtherUndefinedError response; no state change

Accept when the response slot is empty or becomes empty at the edge

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

When the response stalls, req_ready=0, so the configuration write or command pulse is not executed again. The side effect of an accepted request may already have occurred while only its response remains pending. Unconditionally resending a request because its response is delayed can execute a command twice.

Work out the meaning of byte strobes

With CONFIG=32'h11223344, a write of req_wdata=32'hAABBCCDD and req_wstrb=4'b0101 changes only bytes 0 and 2. The result is 32'h11BB33DD. Check address alignment, bit positions, and memory byte order separately. A write with wstrb=0000 succeeds but changes no value.

From the MSBMSB The bit with the highest place value. Its index depends on the vector's declaration direction, so do not assume it always has the largest index. Learn more, the order is byte 3, 2, 1, 0. strobe=0101 selects bytes 2 and 0, so only BB and DD are newly written. A strobe is a byte-wide write enable, not an enable for a single data bit.

Change only the bytes selected by byte strobes
  1. Old CONFIG: 11 | 22 | 33 | 44
  2. Write data: AA | BB | CC | DD
  3. strobe 0101: Keep | replace | keep | replace
  4. New CONFIG: 11 | BB | 33 | DD

Which instant does a status value represent?

A STATUS read response stores status_value at request acceptance. Even if the actual status changes while the response is stalled afterward, rsp_rdata holds. Directly connecting combinational status to the response while rsp_valid=1 and rsp_ready=0 would change the response contents and violate the protocol.

If req_valid and req_ready are both 1 at consecutive edges, these are two separate requests. After acceptance, the sender must lower valid or update to the next request. It must not hold the same request continuously and expect it to be processed only once.

Three axes of verification

  1. Addresses and permissions: check errors and side effects for valid addresses, unaligned addresses, STATUS writes, and undefined addresses.
  2. Data selection: exhaustively test the four strobe bits and check preservation of inactive bytes.
  3. Flow control: block responses for multiple cycles and check that responses and state hold. Check matching transaction counts when response consumption overlaps acceptance of the next request.

Try it yourself

After a COMMAND write with req_wstrb[0]=1 and req_wdata[0]=1 is accepted, rsp_ready remains 0 for three cycles. Should start_pulse repeat for those three cycles? May a STATUS write change config_value?

Read the explanation

start_pulse is 1 for only one cycle immediately after request acceptance, then returns to 0. A stalled response does not trigger command re-execution. A STATUS write returns an error without changing other state, including config_value. The sender and receiver must also agree on a retry policy before response completion.

Your choice applies to this browser. Change it any time using the footer.