A generic SystemVerilog ROM with content initialisation from a file

This post describes how to code a technology-independent SystemVerilog ROM memory with parameters to set the data width and memory depth (i.e. number of locations) and the use of an external file for setting the initial contents.

  1. module spROM
  2.  #(parameter int unsigned width = 8,
  3.  parameter int unsigned depth = 8,
  4.  parameter intFile = "dummy.mif",
  5.  localparam int unsigned addrBits = $clog2(depth)
  6.  )
  7. (
  8.  input logic CLK,
  9.  input logic [addrBits-1:0] ADDRESS,
  10.  output logic [width-1:0] DATAOUT
  11. );
  12.  logic [width-1:0] rom [0:depth-1];
  13.  // initialise ROM contents
  14.  initial begin
  15.   $readmemh(intFile,rom);
  16.  end
  17.  always_ff @ (posedge CLK)
  18.  begin
  19.   DATAOUT <= rom[ADDRESS];
  20.  end
  21. endmodule : spROM

Listing 2

The $readmemh task reads a hex file to the rom array which is effectively the memory. The name of the hex file is passed to the spROM module as a parameter. The number of bits required for the address bus is calculated from the depth parameter using the $clog2 function.


The spROM module can then be instantiated in a higher-level SystemVerilog file like this:

  1. module top_mem (
  2.  input logic CLK,
  3.  input logic [3:0] ADDRESS,
  4.  output logic [15:0] DATA
  5. );
  6.  /*----------------------------------------------------
  7.   Single port ROM: 16 words x 16bit
  8.  ----------------------------------------------------*/
  9.  spROM #(16, 16, "my_init_file.mif") U0 (
  10.   .CLK (CLK ),
  11.   .ADDRESS (ADDRESS ),
  12.   .DATAOUT (DATA )
  13.  );
  14. endmodule : top_mem

Listing 3

A zip archive that includes the SystemVerilog source files and an example memory initialisation file is available here.