Level 52: Memory by the Rules
Task
Goal: build the data memory DMEM 32×32: a bank of word registers, a write decoder on addr[6:2], and a read mux. This is the load/store architecture: arithmetic lives in registers, memory is only reachable via lw/sw. The Assembler tab has learned the S-format — assemble sw and lw and see how the offset is split into two halves. And check word indexing: the low address bits (addr[1:0]) do not enter the word index, so 0x1002 lands in the same word as 0x1000. The alignment check itself is done not by the memory but by the CPU interface — it appears when the core is integrated.
Until now the processor could get data only from registers and immediates. Now it learns to access a separate data memory, and immediately under load/store rules: arithmetic works only with registers, memory is accessible strictly through two instructions, load lw and store sw.
You will build three things:
- Load/store encoding.
lwtakes a 12-bit offset from the I-format;swuses the S-format, where the offset is split into two pieces:imm[11:5]in the top bits of the word andimm[4:0]separately, in the place of the rd field. The level assembler gains S-encoding: you learn to assemble the offset from two halves. - Data memory
dmem.v— 256 words of 32 bits. - Addressing
rs1 + imm. Both instructions compute the address the same way: base register plus extended offset. The ALU already knows how to add, and the datapath is almost ready.
The difference between the instructions is the direction of data. lw rd, imm(rs1): address → memory → value → rd. sw rs2, imm(rs1): address → memory, data from rs2 → memory; the registers do not change.
The check includes a "swapped offset fields" scenario: if imm[11:5] and imm[4:0] are glued in the wrong order, the address becomes garbage — the test must catch it. Alignment is checked separately: lw/sw work only at addresses divisible by four; an unaligned access in the educational model is the error ERR_DATA_ADDRESS_MISALIGNED.
Solution for self-check
First trace the datapaths of both instructions on paper. The solution below is a checklist.
What you should get: sw and lw write and read DMEM at rs1 + imm: the register value reaches memory and comes back into another register unchanged; a misaligned address is caught as ERR_DATA_ADDRESS_MISALIGNED, and swapped offset halves are caught by the negative test.
Step 1 — glue the offset. Assemble the pieces into one 12-bit number: the top piece lives in bits [31:25], the low piece in bits [11:7], then the sign-extend from level 51 expands the ready 12 bits to 32. Extending the pieces separately is wrong: the sign bit must land at position 11, not at the edge of its half.
Step 2 — compute the address. address = rs1 + imm — ordinary addition in the ALU. A common mistake: adding rs1 to rs2 as if this were an R-instruction. In sw, rs2 is the source of the data, not the address.
Step 3 — connect DMEM. 256×32, combinational read, write on the clock edge with enable MemWrite. RegFile and data memory are different blocks: RegFile holds the processor's working registers, DMEM holds the contents the program works with.
Step 4 — route the result paths. In lw the value read from memory becomes the instruction result and is written to rd. In sw nothing is written to registers — the instruction changes only memory.
Step 5 — test. Write a number to a register, store it to memory, load it into another register — the values must match. Then store two words at addresses four apart and check they do not overwrite each other. And check the negative case: address 2 is an alignment trap.
Check yourself
Why must the sign bit land exactly on position 11?
The offset halves are glued into one 12-bit number before extension: sign-extend a half on its own and the one lands on the half boundary instead of bit 11, producing a garbage address.