Saturday, December 31, 2011

Memory Initialization Methods

Questions on how to initialize a ROM or RAM come up quite often on FPGA discussion boards and forums. Several methods can be used to initialize memory in RTL, during implementation, and post-implementation when targeting Xilinx FPGA devices. Some of the methods are covered in this blog.

Verilog "initial" block with $readmemb or $readmemh
Memories can be initialized using $readmemb or $readmemh system tasks with a memory initialization file (.mif) (download complete example here):

reg [DATA_WIDTH-1:0] mem[0:2**ADDR_WIDTH-1];

initial begin
    $readmemh("mem_init_vlog.mif", mem, 0, 255);
end

XST  has two different Verilog parsers depending on the target device. The old parser is used for Virtex5/Spartan3 and older devices. For Virtex6/Spartan6 and newer devices, the new parser will be used. The old parser has a few restrictions on the memory initialization:
  • The entire memory array must be initialized. For example, if the memory has 256 words, all 256 words must be explicitly initialized. Otherwise the initialization will be ignored with this warning message: WARNING:Xst:2319 - "rom_vlog.v" line 21: Signal mem in initial block is partially initialized. The initialization will be ignored.
  • Make sure the .mif file does NOT have any unnecessary white spaces (especially "tab") anywhere. Or it will issue some obscure error message like this: ERROR:Xst:2354 - "rom_vlog_mif.v" line 18: Value 262025260 found at line 256 is not hexadecimal in call of system task $readmemh.
  • Starting address (@hh), Verilog comments (// or /* */), and multiple values per line are not supported in the .mif file. Or as you guessed it, it will issue other weird errors.
It is very unlikely that these restrictions will removed from the old parser because workarounds exist by following the rules above. The good news is that the new Verilog parser supports all valid formats in a memory initialization file as describe in Verilog LRM. i.e. the restrictions no longer exist in the new Verilog parser. An even better news is that the switch "-use_new_parser yes" can be manually added to the XST command line to enable the new parser for older devices if you insist on using full features of the memory initialization file.

VHDL functions
Memory can be initialized in VHDL by using a function at signal declaration. Functions like sin(), cos()in the IEEE math_real library are supported by XST for initializing memories. The code snippet below shows how to generate a look up table with a cosine wave (download complete example here):

constant MEM_DEPTH : integer := 2**ADDR_WIDTH;
type mem_type is array (0 to MEM_DEPTH-1) of signed(DATA_WIDTH-1 downto 0);

function init_mem return mem_type is
    constant SCALE : real := 2**(real(DATA_WIDTH-2));
    constant STEP  : real := 1.0/real(MEM_DEPTH);
    variable temp_mem : mem_type;
begin
    for i in 0 to MEM_DEPTH-1 loop
        temp_mem(i) := to_signed(integer(cos(2.0*MATH_PI*real(i)*STEP)*SCALE), DATA_WIDTH);
    end loop;
    return temp_mem;
end;

constant mem : mem_type := init_mem;

VHDL with external data files
XST User Guide has VHDL examples of initializing block RAMs with external data files. It's listed here so that you are aware of this option. The XST UG should always be your first stop for coding styles and techniques. I would like to point out two things highlighted in red in the code snippet below (download complete example here):
  •  The "file" declaration in XST UG uses VHDL-87 syntax. The code snippet below uses VHDL-93 syntax because that is the default VHDL starndard XST uses.
  •   The second argument for the "read" function needs to be a bit_vector. std_logic_vector or signed types are not supported by the "read" function in IEEE std.textio package.

constant MEM_DEPTH : integer := 2**ADDR_WIDTH;
type mem_type is array (0 to MEM_DEPTH-1) of signed(DATA_WIDTH-1 downto 0);

impure function init_mem(mif_file_name : in string) return mem_type is
    file mif_file : text open read_mode is mif_file_name;
    variable mif_line : line;
    variable temp_bv : bit_vector(DATA_WIDTH-1 downto 0);
    variable temp_mem : mem_type;
begin
    for i in mem_type'range loop
        readline(mif_file, mif_line);
        read(mif_line, temp_bv);
        temp_mem(i) := signed(to_stdlogicvector(temp_bv));
    end loop;
    return temp_mem;
end function;

constant mem : mem_type := init_mem("mem_init_vhd.mif");


Verify Memory Content in Synthesized Netlist

There are a couple of ways to verify that the memory is correctly initialized by the synthesis tool:
  • The values of INIT_xx attributes of the block RAM can be examined in PlanAhead by opening the netlist design in PlanAhead, selecting the instance for the memory, and selecting the "Attributes" tab of the "Instance Properties" window. 
 
  • A post-synthesis simulation model can be generated for the synthesized netlist in Project Navigator or by using netgen tool. This simulation model can be used in the existing testbench to check if the initialization data made into the netlist correctly. The waveform below shows the correct outputs from the ROMs created in the Verilog .mif (counter) and VHDL function (sine wave) methods.


17 comments:

  1. According to UG687, XST supports specifying initial memory contents using an external data file. Here is the corresponding VHDL code snippet:

    type RamType is array(0 to 127) of bit_vector(31 downto 0);

    impure function InitRamFromFile(RamFileName : in string) return RamType is
    file RamFile : text is in RamFileName;
    variable RamFileLine : line;
    variable RAM : RamType;
    begin
    for I in RamType'range loop
    readline(RamFile, RamFileLine);
    read(RamFileLine, RAM(I));
    end loop;
    return RAM;
    end function;

    signal RAM : RamType := InitRamFromFile("rams_20c.data");

    ReplyDelete
  2. @Guy Eschemann, thanks a lot for posting this code snippiet. My main intention is to talk about things not directly covered in the UGs, especially XST UG, which should be the first stop for coding styles and techniques. Having said that, I will add a complete example using external file in VHDL.

    ReplyDelete
  3. hello jim,

    I have a simple question. Will this work. I dun want to initialize my memory. Basically zero values is fine for me.
    will this code work?

    module register_file_behav(clk,write,r1_addr,r2_addr,wr_addr,wr_data,r1_data,r2_data);

    input clk;
    input write;
    input [4:0] r1_addr;
    input [4:0] r2_addr;
    input [4:0] wr_addr;
    input [31:0] wr_data;
    output reg[31:0] r1_data;
    output reg[31:0] r2_data;
    integer i;
    reg [31:0]out_reg [31:0];

    always @(posedge clk)
    begin
    r1_data<= out_reg[r1_addr];
    r2_data<= out_reg[r2_addr];

    if(write)
    begin

    out_reg[wr_addr]<= wr_data;
    end
    end

    endmodule

    regards,
    sid

    ReplyDelete
  4. @sid If you only read a memory location after you write to it, your code looks fine to me.

    ReplyDelete
  5. Hello Jim.

    Thank you for your wonderful post.

    I have used for my LUT to read values from a text file and assign them to the address in the LUT. I need to write a test bench for my VHDL code, but I am having difficulties due to the FOR loop and reading from a text file in the test bench itself.

    Can you please help me? or show me how I can use the FOR loop in my case (NB. my code is very similar to yours above).

    Here’s my VHDL code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    use STD.TEXTIO.ALL;
    use IEEE.STD_LOGIC_TEXTIO.ALL;

    Entity ROM_ent is
    Port(
    ADDR: IN std_logic_VECTOR(7 downto 0);
    CLK: IN std_logic;
    DATA: OUT std_logic_VECTOR(7 downto 0)
    );
    end ROM_ent;

    Architecture Behavioral of ROM_ent is

    type rom_type is array (255 downto 0) of std_logic_vector (7 downto 0);

    impure function InitRomFromFile (RomFileName : in string) return rom_type is

    FILE romfile : text is in RomFileName;
    variable RomFileLine : line;
    variable ROM : rom_type;
    begin

    for i in rom_type'range loop

    readline(romfile, RomFileLine);
    read(RomFileLine, ROM(i));

    end loop;
    return ROM;
    end function;

    Constant ROM : rom_type := InitRomFromFile("Doc1.Txt");

    begin

    process (CLK)
    begin
    if(CLK'event and CLK = '1') then
    DATA <= ROM(to_integer(unsigned(ADDR)));
    end if;
    end process;


    end Behavioral;

    Thank you !!!

    Kind Regards,

    Ahmed

    ReplyDelete
  6. *** I need to use a FOR loop in my test bench ***

    ReplyDelete
  7. hello friends
    i am new to xilinx ise
    i have xilinx 12.3
    ver-m.70d
    i am getting error in behavioural model simulation
    'INFO:ProjectMgmt - The selected process was not run because a prior process failed.'
    my rtl logic is also done,and implementaion view is fully done.plz help

    ReplyDelete
  8. hello friends
    i am new to xilinx ise
    i have xilinx 12.3
    ver-m.70d
    i am getting error in behavioural model simulation
    'INFO:ProjectMgmt - The selected process was not run because a prior process failed.'
    my rtl logic is also done,and implementaion view is fully done.plz help

    ReplyDelete
  9. @Ashwani Since your question has nothing to do with the post, please open a webcase with Xilinx tech support or post the question to the simulation board on Xilinx forums: http://forums.xilinx.com/t5/Simulation-and-Verification/bd-p/SIMANDVERIBD

    ReplyDelete
  10. Hello friends,
    I have a question.I want to store fixed point numbers(integer+fraction) on fpga.I was unable to do with above discussed code by jim.Could u help me

    ReplyDelete
  11. Thanks for this nice article.

    Could you please let me know if there has been any update regarding this or it is still the same.
    Moreover, is there any way to initialize memory with floating numbers?

    Thanks!

    ReplyDelete
  12. Thank you,
    Please any one help me how to read the mif file in VHDL , Itried the code here output still 0s

    ReplyDelete
  13. Hi Jim, it is still not clear to me if this method is synthesisable or just good for simulation. Thanks, Yacine

    ReplyDelete
  14. hello friends,
    i am trying to use vga interface with nexys4 board.
    but i am facing the problem with block ram .
    i have tried two ways to store the file into bram but not working very well , may be i am missing some steps but which steps , i don't know. can you please share the steps for storing the image hex codes into the block ram

    ReplyDelete
  15. My name is Clifford John from USA taxes, I want to share a testimony of how Dr_Ogodo1 herbal mixture cream saves me from shame and disgrace, my penis was a big problem to me as the size was really so embarrassing,and i was also having weak erection problem. I can't make love to my wife and my penis was just too small a full grown man like me having 4 inches penis and to worsen it i don't last in sex i can't even last two minutes it was really a thing of shame to me. My wife was really tired of me because my sex life was very poor,she never enjoyed sex,i was always thinking and searching for solutions everywhere until when i saw a testimony of how Dr_Ogodo1 herbal mixture cream have been helping people regarding their sex life, so i decided to give him a try and to my greatest surprise in less than one week of taking the herbs my penis grow to 8 inches i couldn't believe my eyes and as i speak now my penis is now 8 inches and i do not have week erection again. I can make love to my wife longer in bed. And my marriage is now stable,my wife now enjoy me very well in bed.
    * He can also bring back your Ex
    *Love spell
    * Herpes virus diseases
    *Diabetes
    *Aid virus
    *STD/HSV
    *Cancer/typhoid E.t.c you contact him through the mail. Ogodoherbalhomesolution@gmail.com
    You can also WhatsApp him on +2349044680467

    ReplyDelete
  16. i will never ever in my life stop telling the whole entire world the great Job Dr. Abolo whose contact details is Abolospell@gmail.com did for me by making my relationship the best and the perfect one i wished for with his powerful love spell that works beyond human oh my goodness his spells is so effective and secondly there is know side effect and most importantly he is very legit what ever he says that is what he dose. now this was how meant with him that change my love life all of a sudden. I saw a comment here a few weeks ago about Dr Abolo and i decided to contact him as instructed, thanks to this man for bringing joy to me as wished for. i followed instructions which he gave in other to get my lover back who left me and the kids for 3years now, but thanks to Dr Abolo because they are back to me now for good and we are happy together. please do contact him for help too if in relationship problem via email at: ( Abolospell@gmail.com ) And testify for yourself.

    ReplyDelete
  17. We can always make our relationship the best for us, life or career a successful as we desire, it only take you to put in the right effort and if you feel you need help then look for help. After my man left me heartbroken. I was lonely, devastated and sad luckily I was directed to a very kind and powerful man (Dr Akhigbe) who helped me brought back my man and now he loves me far more than ever am so happy with life now thank you so much drakhigbespellhome7@gmail.com or Whatsapp +2349021374574

    ReplyDelete