Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
8 years ago

Trouble populating memory from text file

Hello everyone, I need help populating my memory from a text file. Here is my RAM vhdl code:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE STD.TEXTIO.ALL;
-- Add a generic parameter
ENTITY rem_ram IS PORT (
     address             : IN  std_logic_vector(7 DOWNTO 0);
    read_data         : OUT std_logic_vector(31 DOWNTO 0)
  );
END ENTITY rem_ram;
ARCHITECTURE rtl OF rem_ram IS
   TYPE ram_type IS ARRAY(0 TO (2**address'LENGTH)-1) OF std_logic_vector(read_data'RANGE);
    
    FUNCTION init_rom RETURN ram_type IS
        VARIABLE r : ram_type;
        BEGIN
            FOR i IN r'RANGE LOOP
                r(i) := (OTHERS => '0');
            END LOOP;
        RETURN r;
    END FUNCTION;
    
    -- FILL MEMORY FROM TEXT FILE
    
    FUNCTION fill_memory RETURN ram_type IS
        VARIABLE mem : ram_type;
        TYPE HexTable IS ARRAY (CHARACTER RANGE <>) OF INTEGER;
        CONSTANT lookup : HexTable('0' TO 'F'):=
        (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1,
        -1, -1, -1, -1, 10, 11, 12, 13, 14, 15);
        FILE infile: text OPEN read_mode IS "mem_ram.txt";
        VARIABLE buff: LINE;
        VARIABLE addr_s: STRING(2 DOWNTO 1);
        VARIABLE data_s : STRING(8 DOWNTO 1);
        VARIABLE addr1, byte_cnt: INTEGER; 
        VARIABLE data: INTEGER RANGE 4294967295 DOWNTO 0;
        BEGIN
            WHILE (not endfile(infile)) LOOP
                readline(infile, buff);
                read(buff, addr_s);
                read(buff, byte_cnt);
                addr1 := lookup(addr_s(2))*16 + lookup(addr_s(1));
                
                readline (infile, buff);
                FOR i IN 1 TO byte_cnt LOOP
                    read(buff, data_s);
                    data :=    lookup(data_s(8))*268435456 + lookup(data_s(7))*16777216 + lookup(data_s(6))*1048576 +
                                lookup(data_s(5))*65536 + lookup(data_s(4))*4096 + lookup(data_s(3))*256 + 
                                lookup(data_s(2))*16 + lookup(data_s(1));
                    mem(addr1) := CONV_STD_LOGIC_VECTOR(data, 32);
                    addr1 := addr1 + 1;
                END LOOP;
            END LOOP;
            
        RETURN mem;
    END FUNCTION;
    
    SIGNAL ram : ram_type := fill_memory;
BEGIN
    read_data <= ram(CONV_INTEGER(UNSIGNED(address)));
  
END ARCHITECTURE rtl;

and here is the text file:


00
8C020000
04
8C030001
08
00430820
0C
AC010003
10
1022FFFF
14
1021FFFA

I suspect that maybe there's an illegal (outside of the hex range) character in the .txt file but I don't see any. Maybe I need to save the text file in a different encoding format? Like ASCII or UTF-8?

Thanks everyone!

10 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Forgot to specify the exact error I am getting

    
    Error (10385): VHDL error at rem_ram.vhd(46): index value nul is outside the range ('0' to 'F') of object "lookup"
    Error (10658): VHDL Operator error at rem_ram.vhd(46): failed to evaluate call to operator ""*""
    Error (10658): VHDL Operator error at rem_ram.vhd(46): failed to evaluate call to operator ""+""
    Error (12153): Can't elaborate top-level user hierarchy
    Error: Quartus Prime Analysis & Synthesis was unsuccessful. 4 errors, 1 warning
    	Error: Peak virtual memory: 696 megabytes
    	Error: Processing ended: Fri Mar 09 15:50:18 2018
    	Error: Elapsed time: 00:00:15
    	Error: Total CPU time (on all processors): 00:00:34
    Error (293001): Quartus Prime Full Compilation was unsuccessful. 6 errors, 1 warning
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Is this for simulation? Altera doesn't support initialisation of ram from text file during synthesis.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Even if it was possible, there are other issues with the code. For a start, this seems like a terribly complicated way to initialise the ram. Whats wrong with just reading the values straight to a std_logic_vector? non-standard std_logic_textio package has the hread function to do just that. (in VHDL 2008, this is included in std_logic_1164 package).

    Then there is the problem that most implementations limit integer to 2**31-1. So integer cannot be given a value of 2**32.

    Also, Strings are usually declared (1 to N) by convention, rather than (N downto 1).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Instead of doing it in code, you could use a .hex or .mif file to initialize the RAM.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    So instead of using .txt file, i just need to change it to .mif?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    No, you have to use an attribute to populate the ram with a .mif/.hex:

    http://quartushelp.altera.com/15.0/mergedprojects/hdl/vhdl/vhdl_file_dir_ram_init.htm

    Be aware though, that this will NOT initialise the ram during simulation. You will need to read in the text file and parse it manually. If you use a ram from the megafunctions library, you can specify the .mif as a generic and this block will parse the file for you, populating the contents in both simulation and synthesis.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Firefox. But I disabled HTTPS-Everywhere and it works fine now.