Skip to content

§ 4.5.3. Decode and Register Read

RV32IBaselineDecodeStage decodes IF/ID and reads the architectural register file. Writes come from the older instruction in Writeback, not from the instruction currently being decoded.

Component Description Structural Behavioral
RV32IBaselineDecodeStage Instruction decoding, two register reads, independent WB write port Yes Yes

IO pins

Pin Direction Width Description
CLK, RST Input 1 each Register-file clock and asynchronous reset
IN_VALID Input 1 IF/ID validity
IN_PC, IN_INSTRUCTION, IN_FETCH_STATUS Input 32 each IF/ID payload
REGISTER_WRITE, WB_RD, WB_VALUE Input 1, 5, 32 Authorized WB write, its destination, its value
OUT_VALID Output 1 Incoming validity
OUT_PC, OUT_INSTRUCTION, OUT_FETCH_STATUS Output 32 each Forwarded packet fields
OUT_RS1_VALUE, OUT_RS2_VALUE, OUT_IMMEDIATE Output 32 each Current source values and sign-extended immediate
OUT_CONTROL, OUT_REGISTER_ADDRESSES Output 32 each Packed control and register addresses
TERMINAL, CONTROL_FLOW Output 1 each Valid packet needs precise stopping; valid branch/JAL/JALR

Behavior

The decoder uses the instruction decoding rules. The register file resets to zero, writes a nonzero WB_RD on an enabled rising edge, and ignores writes to x0. Both source reads are combinational.

There is no writeback bypass. Before a writeback edge the old register value remains on the read port. A consumer therefore stays in IF/ID until its producer has passed Writeback. ID/EX captures source operands only when control releases the dependency stall.

TERMINAL is IN_VALID && (fetch fault || PC misalignment || illegal instruction || halt request || trap request). CONTROL_FLOW is IN_VALID && (nonzero branch type || nonzero jump type). These are requests to pipeline control, not immediate architectural state changes. All ordinary decoder outputs are still computed for an invalid packet.

C++ example

The instruction decoder and control encoder below are the same reusable, non-simulator functions documented in 4.3. Packet fields and packed encodings are defined in 4.5.1. The register update uses WB_RD independently of the decoded RD.

struct Decode {
    std::array<uint32_t,32> registers{};
    bool previous_clock=false;
    StageResult evaluate(Packet p, bool clk, bool reset, bool register_write,
                         unsigned wb_rd, uint32_t wb_value) {
        if(reset) registers.fill(0);
        else if(!previous_clock && clk && register_write && (wb_rd&31))
            registers[wb_rd&31]=wb_value;
        previous_clock=clk;
        const auto d=rv32i::RV32IDecoder::decode(p.instruction);
        const auto c=rv32i::RV32IControl::fromDecoded(d);
        p.control=packControl(c); p.addresses=packAddresses(d.rs1,d.rs2,d.rd);
        p.immediate=uint32_t(d.immediate);
        p.rs1_value=d.rs1?registers[d.rs1]:0;
        p.rs2_value=d.rs2?registers[d.rs2]:0;
        const bool terminal=p.valid&&((p.fetch_status&3)||!c.legal||c.halt||c.trap);
        return {p,terminal,p.valid&&(unsigned(c.branch)||unsigned(c.jump))};
    }
};

Implementation

Structural implementation

CONTROL is RV32IDecodeControlUnit and REGISTER_FILE is the FF-backed RegisterFile32x32. Rewire components form CONTROL, REGISTER_ADDRESSES, and forwarded packet fields. PACKET_STATUS groups the shared terminal/control-flow gates; Decode supplies zero execution status because target calculation has not occurred yet. No forwarding selector or WB_BYPASS component is instantiated.

Behavioral implementation

BehavioralDecode uses the shared BehavioralStage implementation to store the 32 registers and their history, update the WB destination on a known rising edge, then decode and read sources. Both forms expose architectural register-state access for core snapshots and program verification, and share rv32i.baseline.decode. Reset precedes binary equivalence checks.

Examples

The scenario writes x1 while decoding an instruction whose destination is x7, checks old-value reads before the edge, checks x0, and exercises branch/terminal qualification.

All 16 recorded rows of RV32IBaselineDecodeStageTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.

Default scenario profile: baseline-structural-stages / structural (f72af366c5dca6eb). Changing fidelity or the circuit can change these times.

Checkpointzero-based number · timeline label Timesimulator units CLKInput · 1 bit IN_FETCH_STATUSInput · 32 bit IN_INSTRUCTIONInput · 32 bit IN_PCInput · 32 bit IN_VALIDInput · 1 bit REGISTER_WRITEInput · 1 bit RSTInput · 1 bit WB_RDInput · 5 bit WB_VALUEInput · 32 bit CONTROL_FLOWExpected output · 1 bit OUT_CONTROLExpected output · 32 bit OUT_FETCH_STATUSExpected output · 32 bit OUT_IMMEDIATEExpected output · 32 bit OUT_INSTRUCTIONExpected output · 32 bit OUT_PCExpected output · 32 bit OUT_REGISTER_ADDRESSESExpected output · 32 bit OUT_RS1_VALUEExpected output · 32 bit OUT_RS2_VALUEExpected output · 32 bit OUT_VALIDExpected output · 1 bit TERMINALExpected output · 1 bit
#0initial-inputs16 0 0x00000000 0x00000000 0x00000000 0 0 1 0x00 0x00000000 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#1reset17 0 0x00000000 0x00000000 0x00000000 0 0 1 0x00 0x00000000 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#2independent-write-destination36 0 0x00000000 0x002083B3 0x00000000 1 1 0 0x01 0x00000007 not checked not checked not checked not checked not checked not checked 0x00001C41 0x00000000 not checked not checked 0
#3write-x1-not-decoded-x752 1 0x00000000 0x002083B3 0x00000000 1 1 0 0x01 0x00000007 not checked not checked not checked not checked not checked not checked not checked 0x00000007 0x00000000 not checked not checked
#4no-high-clock-rewrite68 1 0x00000000 0x002083B3 0x00000000 1 1 0 0x01 0x00000009 not checked not checked not checked not checked not checked not checked not checked 0x00000007 not checked not checked not checked
#5x2-setup69 0 0x00000000 0x002083B3 0x00000000 1 1 0 0x02 0x0000000B not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#6write-x285 1 0x00000000 0x002083B3 0x00000000 1 1 0 0x02 0x0000000B not checked not checked not checked not checked not checked not checked not checked not checked 0x0000000B not checked not checked
#7x0-setup101 0 0x00000000 0x00000013 0x00000000 1 1 0 0x00 0x0000000B not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#8x0117 1 0x00000000 0x00000013 0x00000000 1 1 0 0x00 0x0000000B not checked not checked not checked not checked not checked not checked not checked 0x00000000 not checked not checked not checked
#9control-flow-99135 1 0x00000000 0x00000063 0x00000000 1 0 0 0x00 0x0000000B 1 not checked not checked not checked not checked not checked not checked not checked not checked not checked 0
#10control-flow-8388847152 1 0x00000000 0x008000EF 0x00000000 1 0 0 0x00 0x0000000B 1 not checked not checked not checked not checked not checked not checked not checked not checked not checked 0
#11control-flow-32871169 1 0x00000000 0x00008067 0x00000000 1 0 0 0x00 0x0000000B 1 not checked not checked not checked not checked not checked not checked not checked not checked not checked 0
#12halt185 1 0x00000000 0x00100073 0x00000000 1 0 0 0x00 0x0000000B 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked 1
#13invalid-slot187 1 0x00000000 0x00100073 0x00000000 0 0 0 0x00 0x0000000B not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 0
#14fetch-fault203 1 0x00000002 0x00000013 0x00000000 1 0 0 0x00 0x0000000B not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 1
#15reserved-status-ignored208 1 0x80000000 0x00000013 0x00000000 1 0 0 0x00 0x0000000B not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 0

Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.

Open Decode stage

Tests

RV32IBaselineDecodeStageTest compares both implementations. Program tests check the architectural register file at every retirement. Sources: RV32IBaselinePipeline.cpp, RV32IBaselinePipelineBehavioral.cpp.