Forum Discussion

efe373's avatar
efe373
Icon for New Contributor rankNew Contributor
3 years ago

Initializing inferred RAM from a text file

Hello,

I have written a simple dual-port RAM in VHDL following the single-port RAM example from Quartus, and I want to initialize this RAM using an external text file containing binary values. However, when I compile the design and check the contents of the RAM, everything is 0. What can be the problem? I am posting my dual-port RAM code and initialization text file.

Also, how can I use the In-System Memory Content Editor if I infer memory using HDL? Is there even a way to do that?

-- Quartus Prime VHDL Template
-- Single-port RAM with single read/write address and initial contents  

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

entity dual_port_ram is

    generic
        (
            FILE_PATH  : string  := "ram_content_bin.txt";
            DATA_WIDTH : natural := 8;
            ADDR_WIDTH : natural := 6
            );

    port
        (
            clk    : in  std_logic;
            addr_a : in  std_logic_vector((ADDR_WIDTH - 1) downto 0);
            addr_b : in  std_logic_vector((ADDR_WIDTH - 1) downto 0);
            data_a : in  std_logic_vector((DATA_WIDTH-1) downto 0);
            data_b : in  std_logic_vector((DATA_WIDTH-1) downto 0);
            wren_a : in  std_logic;
            wren_b : in  std_logic;
            q_a    : out std_logic_vector((DATA_WIDTH -1) downto 0);
            q_b    : out std_logic_vector((DATA_WIDTH -1) downto 0)
            );

end dual_port_ram;


architecture rtl of dual_port_ram is

    -- Build a 2-D array type for the RAM
    subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;

    impure function init_ram_bin return memory_t is
        file text_file       : text open read_mode is FILE_PATH;
        variable text_line   : line;
        variable ram_content : memory_t;
        variable bv          : bit_vector(ram_content(0)'range);
    begin
        for i in 0 to 2**ADDR_WIDTH - 1 loop
            readline(text_file, text_line);
            read(text_line, bv);
            ram_content(i) := To_StdLogicVector(bv);
        end loop;
        return ram_content;
    end function;
    
    -- Declare the RAM signal and specify a default value.  Quartus Prime
    -- will create a memory initialization file (.mif) based on the 
    -- default value.
    signal ram : memory_t := init_ram_bin;

begin

    process(clk)
    begin
        if(rising_edge(clk)) then
            if(wren_a = '1') then
                ram(to_integer(unsigned(addr_a))) <= data_a;
            end if;
        end if;
    end process;

    q_a <= ram(to_integer(unsigned(addr_a)));

    process(clk)
    begin
        if(rising_edge(clk)) then
            if(wren_b = '1') then
                ram(to_integer(unsigned(addr_b))) <= data_b;
            end if;
        end if;
    end process;

    q_b <= ram(to_integer(unsigned(addr_b)));

end rtl;
000000000
100000010
011110000
000000000
101001100
001001011
101000000
011000011
100000001
100000010
000000000
010010000
000000000
000000000
000000000
010010011

Thanks,

Efe

4 Replies