DfT/riscv_rtl/hw/rtl/main_mem.sv
2026-05-29 10:19:13 +02:00

143 lines
4.9 KiB
Systemverilog

// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Aliakbar Merchant [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- ---------- -------------------------------------------------
// 22.Oct.2025 A.Merchant Added reset handling condition for Instr. read logic
// 22.Oct.2025 A.Merchant Added reset handling condition for data write logic
// *********************************************************************************************
`default_nettype wire
module main_mem #(
parameter int ABits = 13 // Number of address bits
//parameter string MEM_INIT_FILE = "" // Optional memory initializations file
) (
input logic clk, // Clock
input logic reset, // Active high sync reset
input logic[31:0] DAddr, // Data Address
input logic[31:0] IAddr, // Instruction Address
input logic[31:0] DWData, // Data to write
output logic[31:0] DRData, // Data read
output logic[31:0] IRData, // Instruction read
input logic DWE, // Data write enable, 1=Write
input logic [1:0] DWidth // Access width (byte, half word, word)
);
// Local Parameter
localparam logic[1:0] _byte = 2'b00; // byte: 8 bits
localparam logic[1:0] _half = 2'b01; // half: 16 bits
localparam logic[1:0] _word = 2'b10; // word: 32 bits
// Local Signals
//logic[31:0] RAM[2**(ABits-2)-1:0]; // Memory array 8KB(8192): ignores lowest 2 bits as 32bit-word
logic [31:0] irTmp;
logic[31:0] drTmp; // Temporary register to hold the data read from RAM.
logic [10:0] mem_addr; // 11-bit word address for MemGen_32_11
logic [31:0] mem_wdata; // 32-bit data bus for MemGen_32_11
logic [31:0] mem_rdata; // 32-bit data bus for MemGen_32_11
MemGen_32_11 RAM (
.chip_en (1'b1),
.clock (clk),
.addr (mem_addr),
.rd_en (!DWE),
.rd_data (mem_rdata),
.wr_en (DWE),
.wr_data (mem_wdata)
);
// memory initilizations
// initial begin
//if (MEM_INIT_FILE != "") begin
// $readmemh(MEM_INIT_FILE, RAM);
// end
// end
//---------------------------------------------------------------------------//
//--------------------------- DATA WRITE LOGIC ---------------------------//
//---------------------------------------------------------------------------//
always_ff @(negedge clk) begin
if (reset) begin
mem_addr <= 0;
end else begin
if (DWE) begin
mem_addr <= DAddr[(ABits-1):2];
// RAM[DAddr[(ABits-1):2]] <= DWData;
case (DWidth)
_word:
mem_wdata <= DWData;
_half:
case (DAddr[1])
1'b0: mem_wdata [31:16] <= DWData[15:0];
1'b1: mem_wdata [15: 0] <= DWData[15:0];
endcase
_byte:
case (DAddr[1:0])
2'b00: mem_wdata [31:24] <= DWData[7:0];
2'b01: mem_wdata [23:16] <= DWData[7:0];
2'b10: mem_wdata [15: 8] <= DWData[7:0];
2'b11: mem_wdata [ 7: 0] <= DWData[7:0];
endcase
default: ;
endcase
end else begin
mem_addr <= IAddr[(ABits-1):2];
end
end
end
//---------------------------------------------------------------------------//
//--------------------------- DATA READ LOGIC ----------------------------//
//---------------------------------------------------------------------------//
always_ff @(negedge clk) begin
drTmp <= mem_rdata;
end
always_comb begin
case (DWidth)
_word:
DRData = drTmp;
_half:
case (DAddr[1])
1'b0: DRData = {16'b0, drTmp[31:16]};
1'b1: DRData = {16'b0, drTmp[15: 0]};
endcase
_byte:
case (DAddr[1:0])
2'b00: DRData = {24'b0, drTmp[31:24]};
2'b01: DRData = {24'b0, drTmp[23:16]};
2'b10: DRData = {24'b0, drTmp[15: 8]};
2'b11: DRData = {24'b0, drTmp[ 7: 0]};
endcase
default: ;
endcase
end
//---------------------------------------------------------------------------//
//----------------------- INSTRUCTION READ LOGIC -------------------------//
//---------------------------------------------------------------------------//
//
//fetch intrcution from memory into IRData
always_ff @(posedge clk) begin
if (reset) begin
IRData <= mem_rdata;
end
else begin
IRData <= mem_rdata;
end
end
endmodule