Replace separate memory modules with single unified memory module#22
Replace separate memory modules with single unified memory module#22spr4bhu wants to merge 6 commits intoSRA-VJTI:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Replaces separate instruction and data memory modules with a single unified dual-port memory, updating the top-level wiring and related address/memory-map logic.
Changes:
- Added
unified_memoryRTL module implementing instruction fetch + data read/write in one memory. - Updated
top.vto instantiateunified_memoryand translate instruction/data addresses into a unified address space. - Simplified/renamed pipeline stall wiring in
riscv_cpu.vand removed legacyinstr_mem.v/data_mem.v.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| rtl/unified_memory.v | New unified dual-port memory with init + hex loading + data load formatting |
| rtl/top.v | Swaps old memories for unified_memory and adds address translation/control wiring |
| rtl/riscv_cpu.v | Renames stall wiring and adjusts IF/ID stall/flush interaction |
| rtl/include/memory_map.vh | Updates IS_INSTR_MEM macro to use INSTR_MEM_END |
| rtl/instr_mem.v | Removed legacy instruction memory module |
| rtl/data_mem.v | Removed legacy data memory module |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Read program as words | ||
| $readmemh(`INSTR_HEX_FILE, word_mem); | ||
|
|
||
| // Unpack words into byte array (little-endian) | ||
| for (i = 0; i < MEM_SIZE/4; i = i + 1) begin | ||
| ram[i*4 + 0] = word_mem[i][7:0]; | ||
| ram[i*4 + 1] = word_mem[i][15:8]; | ||
| ram[i*4 + 2] = word_mem[i][23:16]; | ||
| ram[i*4 + 3] = word_mem[i][31:24]; | ||
| end |
There was a problem hiding this comment.
word_mem is never initialized before $readmemh, and the unpack loop copies every entry into ram. For addresses not present in the hex file, word_mem[i] can remain X/undefined, which then overwrites the earlier NOP initialization in ram and can poison instruction/data reads beyond the loaded program. Initialize word_mem to NOPs (or another defined value) before $readmemh, or only unpack the range actually loaded.
rtl/top.v
Outdated
| .MEM_SIZE(1048576) // 1MB in bytes | ||
| ) data_mem_inst ( | ||
| .DATA_WIDTH(32), | ||
| .MEM_SIZE(1572864) // 1.5MB in bytes (instr + data) |
There was a problem hiding this comment.
UNIFIED_MEM_SIZE is computed but not used, while MEM_SIZE is hard-coded to 1572864. This risks silent mismatches if INSTR_MEM_SIZE / DATA_MEM_SIZE change. Use UNIFIED_MEM_SIZE when setting the unified_memory parameter.
| .MEM_SIZE(1572864) // 1.5MB in bytes (instr + data) | |
| .MEM_SIZE(UNIFIED_MEM_SIZE) // unified size = instr + data |
rtl/unified_memory.v
Outdated
| reg [7:0] ram [0:MEM_SIZE-1]; | ||
| reg [31:0] word_mem [0:MEM_SIZE/4-1]; |
There was a problem hiding this comment.
word_mem is a second large memory array used only for initialization/loading. Depending on toolchain, this can increase compile/synthesis time and memory usage (and may not always be optimized away cleanly). Consider guarding word_mem under a simulation-only define (e.g., ifndef SYNTHESIS) or restructuring the hex load to avoid a second full-sized array.
rtl/unified_memory.v
Outdated
| reg [7:0] ram [0:MEM_SIZE-1]; | ||
| reg [31:0] word_mem [0:MEM_SIZE/4-1]; |
rtl/top.v
Outdated
| assign instr_addr = cpu_pc_out; | ||
| assign data_addr = instr_mem_access ? (data_mem_addr - `INSTR_MEM_BASE) : | ||
| (data_mem_addr - `DATA_MEM_BASE + `INSTR_MEM_SIZE); | ||
| assign data_we = cpu_mem_write_en && data_mem_access; |
There was a problem hiding this comment.
data_we should include instr_mem_access imo.
this allows for later bootloader firmware that copies code to instruction memory
rtl/riscv_cpu.v
Outdated
| wire [31:0] pc_inst0_jump; | ||
| wire stall_pipeline; // For load-use hazards | ||
| wire load_use_stall; // For load-use hazards | ||
| wire pipeline_stall; |
There was a problem hiding this comment.
This stall/flush refactoring is functionally independent of the memory unification. These are good changes but could be a separate PR for cleaner history.
|
@5iri check pls |
5iri
left a comment
There was a problem hiding this comment.
I have suggested some changes in the unified_memory.v file. Please fix them!
rtl/top.v
Outdated
| data_mem_access ? data_mem_read_data : | ||
| uart_access ? uart_read_data : | ||
| instr_mem_access ? instr_read_data : 32'h00000000; | ||
| instr_mem_access ? data_mem_read_data : 32'h00000000; |
There was a problem hiding this comment.
I feel the naming here feels incorrect;
Do change this to something generic like just mem_read_data so that people reading through the code understands.
rtl/unified_memory.v
Outdated
| $display("Loading unified memory from file: %s", `INSTR_HEX_FILE); | ||
|
|
||
| // Read program as words | ||
| for (i = 0; i < MEM_SIZE/4; i = i + 1) begin |
There was a problem hiding this comment.
uhhh why are you writing the entire memory space with NOPs?
There was a problem hiding this comment.
I think this can be fixed alongside the INSTR_MEM_SIZE fix below.
rtl/unified_memory.v
Outdated
| assign aligned_instr_addr = {addr_instr[ADDR_WIDTH-1:2], 2'b00}; | ||
|
|
||
| always @(*) begin | ||
| if (aligned_instr_addr < MEM_SIZE - 3) begin |
There was a problem hiding this comment.
MEM_SIZE is now the entire size of both instructions as well as data; and instr addr length should depend on INSTR_MEM_SIZE not MEM_SIZE even now
removed separate instr_mem and data_mem modules and added a single unified_memory module