Skip to content

§ 4.5.5. Memory Access

RV32IBaselineMemoryStage adapts the EX/MEM packet to stage-local word-addressed memory pins. The complete core's combinational DATA_PORT converts these pins to the universal interface of an external zero-wait FF endpoint. The stage contains neither storage nor a pending transaction. EX/MEM and MEM/WB are the only surrounding instruction buffers.

Component Description Structural Behavioral
RV32IBaselineMemoryStage Direct load/store lanes, access qualification, MEM/WB packet Yes Yes

IO pins

Pin Direction Width Description
IN_VALID Input 1 EX/MEM validity
IN_PC, IN_INSTRUCTION, IN_ALU_RESULT, IN_STORE_DATA, IN_PC_PLUS_4, IN_NEXT_PC, IN_CONTROL, IN_REGISTER_ADDRESSES, IN_FETCH_STATUS, IN_EXECUTION_STATUS Input 32 each EX/MEM payload
MEMORY_ENABLE Input 1 Global execution and older-WB-terminal permission
DMEM_READ_DATA, DMEM_FAULT Input 32, 1 Native word and combinational access fault
DMEM_WORD_ADDR, DMEM_WRITE_DATA Output 32 each Word index and aligned write lanes
DMEM_WRITE_MASK Output 4 Byte enables
DMEM_READ_EN, DMEM_WE Output 1 each Direct read enable; authorize store at memory's next rising edge
OUT_VALID Output 1 Forwarded validity
OUT_<field> Output 32 each All EX/MEM fields above forwarded under the OUT prefix
OUT_MEMORY_DATA, OUT_MEMORY_STATUS Output 32 each Extended load data; bit 0 misalignment, bit 1 access fault
TERMINAL Output 1 Valid incoming terminal reason or eligible memory error

Behavior

A memory operation is eligible only when IN_VALID is one, decode requests a load/store, and no earlier terminal reason accompanies that instruction. READ_EN is MEMORY_ENABLE && eligible. Stores also enable the read/access check so range faults are known before the write edge.

Byte addressing becomes WORD_ADDR=ALU_RESULT>>2. Byte offset selects and extends load lanes, shifts STORE_DATA, and forms WRITE_MASK. Loads support signed/unsigned bytes and halfwords, plus words. Misaligned halfword/word accesses and reserved size 3 are rejected. The original byte address remains in the packet for retirement.

WE additionally requires a store and valid alignment/size. It denotes the requested operation, not successful completion: the endpoint rejects an invalid store without modifying memory. Response faults affect terminal status but never feed back into WE or the request opcode. MEMORY_ENABLE=0 suppresses both read and write enables. Packet forwarding and lane calculation remain combinational; this input is not a request handshake or a packet register enable.

MEMORY_STATUS qualifies data errors by operation eligibility. A prior instruction fault takes precedence and suppresses the memory operation. The stage reports terminal status immediately to pipeline control; the fault becomes architectural only when this instruction reaches Writeback.

Memory compatibility

Use MemoryEndpoint<ff,32>, either fused behavioral or a visible FF controller plus native FF storage. The latter can use scalable MemoryContainer<ff,32> or a small cell-expanded FFMemory<32>. The complete-core memory table lists the supported assemblies and construction restrictions.

The surrounding EX/MEM and MEM/WB registers do not by themselves add memory-wait support. This baseline's control stalls for register dependencies and branches, not delayed REQ_READY/RSP_VALID. The current SRAM, DRAM, ROM, and NOR-flash endpoints are therefore unsuitable: a delayed load could reach MEM/WB with stale data if custom wiring bypassed the program root's non-FF guard. Use the transaction-capable RV32IFiveStageCore for those endpoints.

C++ example

early_terminal is the shared check for valid fetch/decode/target faults and halt. The returned packet forwards all incoming fields and adds loaded data/status. An endpoint stores bytes on its own rising edge only when we requests a valid, accepted store; an error response performs no write. This function itself stores nothing.

struct MemoryResult {
    Packet packet; bool terminal;
    uint32_t word_addr, write_data; unsigned write_mask;
    bool read_en, we;
};
inline MemoryResult memory(Packet p,bool enable,uint32_t read_word,bool fault) {
    const bool early=early_terminal(p);
    const bool read=bits(p.control,2,1),write=bits(p.control,3,1),sign=bits(p.control,4,1);
    const auto size=bits(p.control,11,3),offset=p.alu_result&3;
    const bool eligible=p.valid&&!early&&(read||write);
    const bool bad=size==3||(size==1&&(offset&1))||(size==2&&offset);
    uint32_t value=read_word>>(8*offset);
    if(size==0) {value&=255; if(sign&&(value&128)) value|=0xffffff00u;}
    else if(size==1) {value&=65535; if(sign&&(value&32768)) value|=0xffff0000u;}
    else if(size==3) value=0;
    p.memory_data=value;
    p.memory_status=eligible?(uint32_t(bad)|(uint32_t(fault)<<1)):0;
    const unsigned mask=size==0?1u<<offset:size==1?(3u<<offset)&15:size==2?15:0;
    return {p,early||(eligible&&(bad||fault)),p.alu_result>>2,p.store_data<<(8*offset),mask,
            enable&&eligible,enable&&eligible&&write&&!bad};
}

Implementation

Structural implementation

ACCESS reuses RV32ISingleCycleMemoryStage, which groups RV32IMemoryLanes and alignment checking. PACKET_STATUS groups incoming terminal-reason checks. Packet/status rewires and eligibility/fault gates surround the combinational access path. There is no REQUEST, pending flag, or duplicate memory device.

Behavioral implementation

memoryPacket computes the same binary lane mappings, permission signals, and status. The registered family is rv32i.baseline.memory. The complete core connects to an external FF endpoint: an FF controller plus a native FF device, or their fused behavioral implementation. It shares the CPU clock and adds no wait cycle.

Examples

The test includes signed byte extraction, byte/word stores, alignment/access faults, an older terminal instruction disabling memory, and invalid packet suppression.

All 9 recorded rows of RV32IBaselineMemoryStageTest, 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 DMEM_FAULTInput · 1 bit DMEM_READ_DATAInput · 32 bit IN_ALU_RESULTInput · 32 bit IN_CONTROLInput · 32 bit IN_EXECUTION_STATUSInput · 32 bit IN_FETCH_STATUSInput · 32 bit IN_INSTRUCTIONInput · 32 bit IN_NEXT_PCInput · 32 bit IN_PCInput · 32 bit IN_PC_PLUS_4Input · 32 bit IN_REGISTER_ADDRESSESInput · 32 bit IN_STORE_DATAInput · 32 bit IN_VALIDInput · 1 bit MEMORY_ENABLEInput · 1 bit DMEM_READ_ENExpected output · 1 bit DMEM_WEExpected output · 1 bit DMEM_WORD_ADDRExpected output · 32 bit DMEM_WRITE_DATAExpected output · 32 bit DMEM_WRITE_MASKExpected output · 4 bit OUT_ALU_RESULTExpected output · 32 bit OUT_CONTROLExpected output · 32 bit OUT_EXECUTION_STATUSExpected output · 32 bit OUT_FETCH_STATUSExpected output · 32 bit OUT_INSTRUCTIONExpected output · 32 bit OUT_MEMORY_DATAExpected output · 32 bit OUT_MEMORY_STATUSExpected output · 32 bit OUT_NEXT_PCExpected output · 32 bit OUT_PCExpected output · 32 bit OUT_PC_PLUS_4Expected output · 32 bit OUT_REGISTER_ADDRESSESExpected output · 32 bit OUT_STORE_DATAExpected output · 32 bit OUT_VALIDExpected output · 1 bit TERMINALExpected output · 1 bit
#0initial-inputs9 0 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#1lb20 0 0x00008000 0x00000101 0x20000497 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 1 1 1 0 0x00000040 not checked not checked not checked not checked not checked not checked not checked 0xFFFFFF80 not checked not checked not checked not checked not checked not checked not checked 0
#2sb26 0 0x00008000 0x00000101 0x20000189 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 1 1 not checked 1 not checked 0x0000A500 0x2 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#3endpoint-rejects-write29 1 0x00008000 0x00000101 0x20000189 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 1 1 not checked 1 not checked not checked not checked not checked not checked not checked not checked not checked not checked 0x00000002 not checked not checked not checked not checked not checked not checked 1
#4misaligned-sw37 0 0x00008000 0x00000101 0x20001189 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 1 1 not checked 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked 0x00000001 not checked not checked not checked not checked not checked not checked 1
#5aligned-sw48 0 0x00008000 0x00000100 0x20001189 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 1 1 not checked 1 not checked not checked not checked not checked not checked not checked not checked not checked not checked 0x00000000 not checked not checked not checked not checked not checked not checked 0
#6older-terminal-blocks-store52 0 0x00008000 0x00000100 0x20001189 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 1 0 0 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#7fetch-fault-blocks-memory63 0 0x00008000 0x00000100 0x20001189 0x00000000 0x00000002 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 1 1 0 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 1
#8bubble-has-no-effects67 0 0x00008000 0x00000100 0x20001189 0x00000000 0x00000002 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000000A5 0 1 0 0 not checked not checked not checked not checked not checked not checked 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 Memory stage

Tests

RV32IBaselineMemoryStageTest compares both implementations. Program tests check retired memory effects against the instruction reference and independently verify the physical write history. Sources: RV32IBaselinePipeline.cpp, RV32IBaselinePipelineBehavioral.cpp.