As well as the other answers, you can also do the initialisation from a single parameter. Something like this Verilog example should suffice:
module paramInitialisedROM #(
parameter WIDTH = 1,
parameter DEPTH = 256,
parameter MEM_INIT = 256'd120310230123 //Or whatever, key thing is to make it the correct size (WIDTH*DEPTH).
)(
input clock,
input [DEPTH-1:0] address,
output reg [WIDTH-1:0] data
);
localparam WORDS = 1<<DEPTH; //Number of words in ROM.
// Create an inferred ROM of the correct size
reg [WIDTH-1:0] rom [WORDS-1:0]; //It is possible to add an altera derective
//to this to specify BRAM or MLAB, but I forget
//the syntax of that.
// ROM Initialisation
integer idx;
integer offset;
initial begin
for (idx = 0; idx < WORDS; idx=idx+1) begin //Count through each word in the rom
offset = idx * WIDTH; //The offset into the parameter is the current index times the with
rom[idx] = MEM_INIT[offset+:WIDTH]; //Set the current rom word to the correct chunk in the parameter
end
end
//Clocked Read from ROM
always @ (posedge clock) begin
data <= rom[address];
end
endmodule
Basically when you instantiate the module, make sure to provide a parameter of the correct size. For example if you make it 16x4b ROM, you would need the parameter to be specified as 64bit or larger, e.g.:
paramInitialisedROM aRomInstance #(
.WIDTH(4),
.DEPTH(4),
.MEM_INIT(64'd120310230123)
)(
.clock(clock),
.address(address),
.data(data)
);
The data in the parameter is organised so that the WIDTH
LSBs are used for the first word. The next WIDTH
chunk is the next word, and so on until all words are filled.
The for
loop during initialisation will be fully optimised out by the compiler, so it doesn't cost any logic. In fact the whole initial
block is converted to be the initial value of the memory.
As it is inferred memory, it should work perfectly well in both Altera and Xilinx tools.
Note: I haven't test compiled this, but the principle should work fine. If you find any syntax errors, feel free to edit in corrections.