icicle/ram.sv
Graham Edgecombe b73a0155dd Swap byte order in the ram module
Although the processor uses little-endian addressing, the memory bus
itself is big-endian. (This simplifies the implementation of
memory-mapped registers.)

However, this does mean the contents of the RAM need to be in big-endian
order, rather than little-endian order. $readmemh does not provide any
control over byte order, so we previously swapped the byte order of
progmem.hex with srec_cat in the Makefile.

This commit changes the ram module to swap the byte order upon
reading/writing. This removes the need to use srec_cat in the Makefile.
Swapping the byte order in hardware shouldn't cause any performance
impact as it just involves re-arranging wires.
2017-12-26 14:15:12 +00:00

41 lines
1 KiB
Systemverilog

`ifndef RAM
`define RAM
module ram (
input clk,
/* memory bus */
input [31:0] address_in,
input sel_in,
output logic [31:0] read_value_out,
input [3:0] write_mask_in,
input [31:0] write_value_in
);
logic [31:0] mem [2047:0];
logic [31:0] read_value;
initial
$readmemh("progmem_syn.hex", mem);
assign read_value_out = sel_in ? read_value : 0;
always_ff @(negedge clk) begin
read_value <= {mem[address_in[31:2]][7:0], mem[address_in[31:2]][15:8], mem[address_in[31:2]][23:16], mem[address_in[31:2]][31:24]};
if (sel_in) begin
if (write_mask_in[3])
mem[address_in[31:2]][7:0] <= write_value_in[31:24];
if (write_mask_in[2])
mem[address_in[31:2]][15:8] <= write_value_in[23:16];
if (write_mask_in[1])
mem[address_in[31:2]][23:16] <= write_value_in[15:8];
if (write_mask_in[0])
mem[address_in[31:2]][31:24] <= write_value_in[7:0];
end
end
endmodule
`endif