2026-06-09 08:33:18 +02:00

118 lines
4.5 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
// *********************************************************************************************
module main_mem #(
parameter int ABits = 3 // 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] drTmp; // Temporary register to hold the data read from RAM.
// 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
if (DWE) begin
// RAM[DAddr[(ABits-1):2]] <= DWData;
case (DWidth)
_word:
RAM[DAddr[(ABits-1):2]] <= DWData;
_half:
case (DAddr[1])
1'b0: RAM[DAddr[(ABits-1):2]][31:16] <= DWData[15:0];
1'b1: RAM[DAddr[(ABits-1):2]][15: 0] <= DWData[15:0];
endcase
_byte:
case (DAddr[1:0])
2'b00: RAM[DAddr[(ABits-1):2]][31:24] <= DWData[7:0];
2'b01: RAM[DAddr[(ABits-1):2]][23:16] <= DWData[7:0];
2'b10: RAM[DAddr[(ABits-1):2]][15: 8] <= DWData[7:0];
2'b11: RAM[DAddr[(ABits-1):2]][ 7: 0] <= DWData[7:0];
endcase
default: ;
endcase
end
end
end
//---------------------------------------------------------------------------//
//--------------------------- DATA READ LOGIC ----------------------------//
//---------------------------------------------------------------------------//
always_ff @(negedge clk) begin
drTmp <= RAM[DAddr[(ABits-1):2]];
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)
IRData <= RAM[0];
else
IRData <= RAM[IAddr[(ABits-1):2]];
end
endmodule