ELEC50010-IAC-CW/rtl/mips_cpu_memory.v

83 lines
2.7 KiB
Coq
Raw Normal View History

/*
Memory for Harvard Interface
- RAM Size: 32 x 2^32 = 32 x 4294967296
- Instructions in binaries or hex -> RAM_INIT_FILE
- combinatorial read/fetch of instruction via instr_ port
- combinatorial read and single cycle write of data via data_ port
Constraints
read write
0 0 -> nothing
0 1 -> write
1 0 -> read
1 1 -> read ????? probs should never occur?
Instantiation of Memory Module
- mips_cpu_memory #(RAM_INIT_FILE) ramInst(clk, data_address, data_write, data_read, data_writedata, data_readdata, instr_address, instr_readdata);
Special Memory Locations
- Whether a particular address maps to RAM, ROM, or something else is entirely down to the top-level circuit outside your CPU.
- special memory locations: 0x00000000 (CPU halt), 0xBFC00000 (start execution after reset)
- PC should be 0xBFC00000 at the start and 0x00000000 at the end
Needs checking with:
-- clk or clk_enable?
-- constraint on not being able to read and write in the same cycle
-- whether there is a more efficient way of initialising memory to zero (line 32)
*/
module mips_cpu_memory(
input logic clk_enable,
//Data Memory
input logic[31:0] data_address,
input logic data_write,
input logic data_read,
input logic[31:0] data_writedata,
output logic[31:0] data_readdata,
//Instruction Memory
input logic[31:0] instr_address,
output logic[31:0] instr_readdata
);
parameter RAM_INIT_FILE = "";
reg [31:0] memory [4294967295:0]; // 2^32 memory locations of 32 bits size
initial begin
integer i;
//Initialise to zero by default
for (i=0; i<4294967296; i++) begin
memory[i]=0;
end
//Load contents from file if specified
if (RAM_INIT_FILE != "") begin
$display("RAM : INIT : Loading RAM contents from %s", RAM_INIT_FILE);
$readmemh(RAM_INIT_FILE, memory);
end
end
//Combinatorial read path for data and instruction.
if (clk_enable == 1) begin
assign data_readdata = data_read ? memory[data_address] : 16'hxxxx;
assign instr_readdata = memory[instr_address];
end
else begin
assign data_readdata = data_readdata;
assign instr_readdata = instr_address;
end
//Synchronous write path
always_ff @(posedge clk_enable) begin
//$display("RAM : INFO : data_read=%h, data_address = %h, mem=%h", data_read, data_address, memory[data_address]);
if (!data_read & data_write) begin //cannot read and write to memory in the same cycle
if (instr_address != data_address) begin //cannot modify the instruction being read
memory[data_address] <= data_writedata;
end
end
end
endmodule