Search code examples
verilogsystem-verilogquartusrom

How to fill-up a dual port ROM in Quartus


Below is my ROM, and I have binary values in a .txt file, but I'm not sure how to initialize the ROM with those values. I've done some research, and it seems like a .mif file is one way of doing it (but seems a little complicated, procedurally) and I've found $readmemb as another option but it seems like that's only for simulations? Any help/clarification would be appreciated!

module dual_port_rom (clk, addr_1, addr_2, data_1, data_2);
        
    input clk;
    input [7:0] addr_1;
    input [7:0] addr_2; //check address width!!! and also see how to fill -_-
    output [7:0] data_1;
    output [7:0] data_2;
    reg [7:0] rom [5122:0];
    reg [7:0] read_a1;
    reg [7:0] read_a2;
        
    always @(posedge clk) begin
        read_a1 <= addr_1;
        read_a2 <= addr_2;
    end
    
    assign data_1 = rom[read_a1];
    assign data_2 = rom[read_a2];
    
endmodule

Solution

  • You can use $readmemb or $readmemh to initialize the contents of a ROM in Quartus. Look at Section 1.4.2, Example 20 in the Recommended HDL Coding Styles for the suggested Verilog for inferring a dual ported ROM: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug-qpp-design-recommendations.pdf ; for reference heres how your code would look:

    module dual_port_rom (clk, addr_1, addr_2, data_1, data_2);
    
      input clk;
      input [7:0] addr_1;
      input [7:0] addr_2;
      output reg [7:0] data_1; // Can declare these as reg type directly rather than have an intermediate
      output reg [7:0] data_2;
      reg [7:0] rom [5122:0];
    
      // From the example, initialize the ROM with $readmemb; which is compatible with simulation making trying out the ROM easier
      initial begin
        $readmemb("init_file.txt", rom);
      end
    
      always @(posedge clk) begin
        data_1 <= rom[addr_1]; // Following the style from the example, the data should be put into a register once read from the ROM rather than the address. This shouldnt effect the timing of your system since you were putting the address into a register though
        data_2 <= rom[addr_2];
      end
    endmodule
    

    Be sure that your file follows the proper format for files expected by those functions, you can learn more here: How to initialize contents of inferred Block RAM (BRAM) in Verilog