Skip to content

§ 4.4.1. Fetch

RV32ISingleCycleFetchStage owns the architectural PC, computes PC+4, and exposes a direct instruction-memory read. It contains neither instruction storage nor a pending request. In the core it is named FETCH.

The direct pins are local to the stage. The complete core's combinational INSTRUCTION_PORT converts them to universal REQ/RSP pins for the external zero-wait FF endpoint. This formatting does not capture a request or add a cycle.

Component Description Structural Behavioral
RV32ISingleCycleFetchStage PC register, sequential address, direct instruction read, alignment/fault status Yes Yes

4.4.1.1. RV32ISingleCycleFetchStage

IO pins

Pin Direction Width Description
CLK, RST Input 1 each Rising-edge PC capture; asynchronous active-high PC reset
ISSUE Input 1 Instruction-memory read enable
PC_WRITE Input 1 Authorize PC capture
NEXT_PC Input 32 Candidate PC
IMEM_READ_DATA Input 32 Current instruction word
IMEM_FAULT Input 1 Native memory access fault
PC, PC_PLUS_4, INSTRUCTION Output 32 each Stored PC, PC+4, directly forwarded instruction
DONE, FAULT, PC_MISALIGNED Output 1 each Constant one; forwarded access fault; PC low bits nonzero
IMEM_WORD_ADDR Output 32 PC/4 word index
IMEM_READ_EN Output 1 Follows ISSUE

Behavior

RST clears PC to zero. A known rising edge with PC_WRITE=1 captures NEXT_PC; otherwise PC holds. Changing NEXT_PC while CLK stays high cannot update PC again.

Instruction data, fault, PC+4, and the word index are available after combinational settling. DONE is constant one: it denotes a direct port without a handshake, not a measured propagation-ready signal. The caller must allow the path to settle before the edge.

PC_MISALIGNED reports the original byte PC's low two bits. Dividing by four for the native word address does not legalize a misaligned fetch; execution status traps it. INSTRUCTION and FAULT are forwarded without qualification. The complete core gates their architectural use through execution status.

C++ example

This binary reference contains the entire PC state transition and direct pin behavior. It has no transaction state. Reset before execution.

#include <cstdint>
namespace single_cycle_example {
struct FetchInputs {
    bool CLK, RST, ISSUE, PC_WRITE;
    uint32_t NEXT_PC, IMEM_READ_DATA;
    bool IMEM_FAULT;
};
struct FetchOutputs {
    uint32_t PC, PC_PLUS_4, INSTRUCTION;
    bool DONE, FAULT, PC_MISALIGNED;
    uint32_t IMEM_WORD_ADDR;
    bool IMEM_READ_EN;
};
class Fetch {
    uint32_t pc=0;
    bool previous_clock=false;
public:
    FetchOutputs observe(const FetchInputs& i) const {
        return {pc,pc+4,i.IMEM_READ_DATA,true,i.IMEM_FAULT,bool(pc&3),pc>>2,i.ISSUE};
    }
    FetchOutputs evaluate(const FetchInputs& i) {
        if(i.RST) pc=0;
        else if(!previous_clock&&i.CLK&&i.PC_WRITE) pc=i.NEXT_PC;
        previous_clock=i.CLK;
        return observe(i);
    }
};
}

Unknown inputs and timing

Equivalence checks cover binary operation after reset. Instruction/fault bits are forwarded directly. The behavioral PC is a four-state register: it starts unknown, resets to zero, and captures NEXT_PC on a known low-to-high CLK edge when PC_WRITE permits it. Captured Z bits become X; unknown reset or write-enable values follow the register's gate rules described in 4.3.3. PC_PLUS_4 and alignment also operate on the four-state PC instead of converting unknown bits to zero. Catalog-selected behavioral outputs use the stage’s gate-derived delay table and, where supported, a delay twin for the current input values; individual gate transitions can still differ. Memory must settle within the CPU period; there is no variable-latency wait mechanism here.

Implementation

Structural implementation

PC_STATE is Register<32>, PC_PLUS_4_ADD is a structural IncrementBy4, and ALIGNMENT checks the byte PC. The incrementer passes bits 1:0 through and uses a parallel carry-prefix network for bits 31:2; it needs no general second operand, carry-in, or unused carry-out. MEMORY_PORT is a zero-delay Rewire: it drops the address's two low bits for word indexing and forwards data, fault, and enable. The only architectural storage is PC_STATE. There is no REQUEST child.

Behavioral implementation

The Fetch branch of BehavioralStage stores PC and previous clock, then publishes the same direct outputs. Both forms are registered as rv32i.single-cycle.fetch.

Examples

The scenario reads without a clock, holds PC before commit, captures NEXT_PC once per rising edge, checks enable/fault forwarding, and resets PC.

All 11 recorded rows of RV32ISingleCycleFetchStageTest, 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: canonical-default-preview / structural (43fcd22eec4d3066). Changing fidelity or the circuit can change these times.

Checkpointzero-based number · timeline label Timesimulator units CLKInput · 1 bit IMEM_FAULTInput · 1 bit IMEM_READ_DATAInput · 32 bit ISSUEInput · 1 bit NEXT_PCInput · 32 bit PC_WRITEInput · 1 bit RSTInput · 1 bit DONEExpected output · 1 bit FAULTExpected output · 1 bit IMEM_READ_ENExpected output · 1 bit IMEM_WORD_ADDRExpected output · 32 bit INSTRUCTIONExpected output · 32 bit PCExpected output · 32 bit PC_MISALIGNEDExpected output · 1 bit PC_PLUS_4Expected output · 32 bit
#0reset10 0 0 0x00000000 0 0x00000010 0 1 not checked not checked 0 not checked not checked 0x00000000 not checked 0x00000004
#1read-without-clock11 0 0 0x01000093 1 0x00000010 0 0 1 not checked not checked 0x00000000 0x01000093 not checked not checked not checked
#2next-pc-not-yet-committed12 0 0 0x01000093 1 0x00000010 1 0 not checked not checked not checked not checked not checked 0x00000000 not checked not checked
#3commit19 1 0 0x01000093 1 0x00000010 1 0 not checked not checked not checked 0x00000004 not checked 0x00000010 not checked 0x00000014
#4high-clock-holds-pc20 1 0 0x01000093 1 0x00000018 1 0 not checked not checked not checked not checked not checked 0x00000010 not checked not checked
#5falling-edge21 0 0 0x01000093 1 0x00000018 1 0 not checked not checked not checked not checked not checked 0x00000010 not checked not checked
#6second-commit29 1 0 0x01000093 1 0x00000018 1 0 not checked not checked not checked not checked not checked 0x00000018 not checked not checked
#7disabled30 0 0 0x01000093 0 0x00000018 0 0 not checked not checked 0 not checked not checked not checked not checked not checked
#8hold35 1 0 0x01000093 0 0x00000018 0 0 not checked not checked not checked not checked not checked 0x00000018 not checked not checked
#9fault-propagates36 1 1 0x01000093 0 0x00000018 0 0 not checked 1 not checked not checked not checked not checked not checked not checked
#10reset-pc44 1 1 0x01000093 0 0x00000018 0 1 not checked not checked not checked not checked not checked 0x00000000 not checked not checked

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.

Embedded simulation

Open Fetch stage

Tests

RV32ISingleCycleFetchStageTest compares both implementations. RV32ISingleCycleStageIntegrationTest checks one-cycle completion and old-state operand use. RV32ISingleCycleDocumentationTest.py checks every pin and executes this exact C++ example. Sources: RV32ISingleCycleStages.cpp, RV32ISingleCycleStagesBehavioral.cpp, and RV32ISingleCycleStageTests.cpp.