What?
$readmemh
is a Verilog directive that allows you to initialize an array. It works differently in simulation compared to synthesis. In simulation, this directive behaves as a “read file into array”. In synthesis, this directive behaves as a repository of initial values for, say, block RAM.
While the purpose of the directive is documented every which way, the correct usage of the directive is woefully under-explained.
How to use it correctly
If you have a file in a directory say:
/some/directory/file.mem
then you must add it to your synthesis project by its entire path. This of course helps your tools locate the file.
However, when you want to use the file, you must refer to it by its base name only:
initial $readmemh("file.mem", data);
Note how in the above example, we have completely omitted the /some/directory/
path bit. I find this non-intuitive, but apparently this is how tools handle the directive. Not doing this makes the tools “simply” ignore the file, and apparently silently so. Which is likely not what you want.
Formats
Other equally not well documented constraints may be applicable. I have not verified all of them, so tread carefully here:
- I think I read somewhere that some tooling will refuse to read files that do not end in
.mem
. I do not know if this is true or not. I also do not think it is worth examining. Just name the file such that its name ends with.mem
and be done with it. - The expected format of the data in the
file.mem
file is somewhat up for debate. It seems that some tooling will ignore the file if the file is not of the size appropriate for the variable used to load the values into. Other tooling will ignore the file if the size of values within it doesn’t exactly match the size of the array that the file should be applied to.
Some tools will report these errors, some will keep silent. It’s a complete clusterduck.
Being equipped with knowledge is the best antidote against losing time and nerves around these issues.