I designed a RAM module, and I need multiple instances of this module each with a different memory initialization file.
The Quartus manual says that Quartus supports the $readmemh()
function to initialize RAM. So I added two parameters to this module and pass different parameters to each instance, in order to specify which files each instance will read.
My code below works in Modelsim, but when fails when synthesizing. Quartus crashes, and after I remove it, Quartus synthesizes successfully.
module cell_module
#(
parameter X_ID = "1",
parameter Y_ID = "1",
parameter DIR_ID = {X_ID, "_", Y_ID}
)
...
reg [15:0] Mem_1 [0:31];
reg [15:0] Mem_2 [0:31];
`ifdef SIM_MEM_INIT
initial begin
$readmemh ({"../data", DIR_ID, "/file1.txt"},Mem_1);
$readmemh ({"../data", DIR_ID, "/file2.txt"},Mem_2);
end
`endif
The above module is instantiated in the top level like this:
cell_module #(.X_ID("1"), .Y_ID("1")) cell_module1 (...)
cell_module #(.X_ID("1"), .Y_ID("2")) cell_module2 (...)
cell_module #(.X_ID("2"), .Y_ID("1")) cell_module3 (...)
cell_module #(.X_ID("2"), .Y_ID("2")) cell_module4 (...)
The parameters specify which folder contains the initial memory for that cell. This code works in Modelsim, and Quartus analysis and elaborate successfully completes.
But it causes quartus_map to crash when synthesizing. I can't find any information about this error message.
If this isn't possible, are there any good methods to initialize multiple instance's RAM with different contents? Thanks
EDIT:
I built a small Quartus project to test whether this could be done. I followed the Quartus manual and wrote a standard RAM module with two extra parameters to define the folder of the initialization memory file. This is code of ram,
module mem_init
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6, parameter X_ID = "1", Y_ID = "1", DIR_ID = {X_ID,"_", Y_ID})
(input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] addr,
input we, clk,
output [(DATA_WIDTH-1):0] q);
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0] addr_reg;
initial
begin : INIT
$readmemh ("../data", DIR_ID, "/file.txt", ram);
end
always @ (posedge clk)
begin
if (we)
ram[addr] <= data;
addr_reg <= addr;
end
assign q = ram[addr_reg];
endmodule
And its initialization:
mem_init #(.DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH), .X_ID("1"), .Y_ID("1"))
mem1 (.data(data1), .addr(add1), .we(we), .clk(clk), .q(q1));
mem_init #(.DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH), .X_ID("1"), .Y_ID("2"))
mem2 ( .data(data2),.addr(add2),.we(we), .clk(clk), .q(q2));
This works in simulation and Quartus successfully synthesizes this design.