What?
$readmemh
is a Verilog directive that allows you to initialize an array. 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.
Formats
Other, not very 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. - 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 it is not appropriately sized. 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.