I am having trouble initializing the contents of an inferred ram in Verilog. The code for the ram is as below:
module ram(
input clock, // System clock
input we, // When high RAM sets data in input lines to given address
input [13:0] data_in, // Data lines to write to memory
input [10:0] addr_in, // Address lines for saving data to memory
input [10:0] addr_out, // Address for reading from ram
output reg data_out // Data out
);
reg [13:0] ram[2047:0];
// Initialize RAM from file
// WHAT SHOULD GO HERE?
always @(posedge clock) begin
// Save data to RAM
if (we) begin
ram[addr_in] <= data_in;
end
// Place data from RAM
data_out <= ram[addr_out];
end
endmodule
I have run into the command $readmemh. However, documentation for it seems sparse. How should I format the file that contains the data? Also, how can I pass the file as argument when instantiating this module so that I can have different instances of this module load from different files?
I want the initialized content to be available for both simulation and actual implementation. So that the FPGA already boots with this content in RAM.
I am using Vivado 2015.4 to program a Kintex xc7k70 FPGA.
This might be easy in case of debug, where the value of a location is its location number.
Also, I would suggest you to not initialize the RAMs. It will help you in catching bugs, if any, in simulation as the data driven will be 'x if RAM is un-intialized and can be caught easily.
Apart from @Unn's excellent ans, I want to add that, If you just want to initialize your memory with either all bits to
1'b1
or1'b0
, then you can just put following code,For your case, WIDTH=14, and MEM_INIT_VAL may be
1'b1
or1'b0
.You are correct that you should use
$readmemh
inside an initial block. In order to make it so different instances of the module can have different initialization files, you should use a parameter like so:The format is described in Section 21.4 of the IEEE1800-2012 specification; typically the file is just a bunch of lines containing hex numbers of the correct bit-length, like so:
Note that there is no "0x" prefix and each line represents an adjacent address (or any separating whitespace). In the example above,
$readmemh
would put14'h0001
intoram[0]
,14'h1234
intoram[1]
,14'h3FFF
intoram[2]
and so on. You can also include comments in the hex file using//
or/* */
. Finally, you can use the@
symbol to designate an address for the following numbers to be located at, like so:In the above file,
ram[0]
andram[1]
would be uninitialized andram[2]
would get14'h0101
. Those are all the major constructs of the hex file format, though you can also use_
,x
andz
as you would in other Verilog numbers and theres a few more rules you can read in the section sited above.