0
votes

this is my code in vhdl

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;

entity inst_mem is
    port(
        load: in std_logic;
        address: in std_logic_vector (5 downto 0); 

        dataout: out std_logic_vector (10 downto 0)
        );
end entity;

architecture arch_inst_mem of inst_mem is
    TYPE inst_mem is array (0 to 32) of std_logic_vector(10 downto 0);

    procedure init_mem(variable memory : out inst_mem; 
                                    constant datafile : string) is
        file stddata: text;
        variable l: line;
        variable data: std_logic_vector (10 downto 0);
    begin
        file_open (stddata, datafile, READ_MODE);
        for i in memory'range(1) loop
            readline (stddata, l);
            read (l, data);
            memory(i):= data;
        end LOOP;
    end procedure;


begin
  process (load , address)
    variable memory: inst_mem;
  begin
    if (load = '1') then
        init_mem (memory, "inst_mem.txt");
        dataout <= memory (conv_integer(address));
    end if;
  end process;
end arch_inst_mem;

in compilation i have no error bud when i simulate it modelsim i have this error, (# Fatal error in ForLoop loop at C:/Users/Bana/Desktop/Q1/inst_mem.vhd line 29) why? thanks, bana.

1
At least add file_close call at end of init_memory procedure, to match the file_open. Check that the "inst_mem.txt" file has the correct number of entries, since it is odd that the address port has 6 bits thus making 64 (2 ** 6) entries while 33 entries (0 to 32) are read. Also, consider using only ieee.numeric_std package, since IEEE.STD_LOGIC_UNSIGNED and ieee.std_logic_arith are non standard, and can be substituted by ieee.numeric_std. - Morten Zilmer
Use only one arithmetic library as Morten suggested. Why has your RAM 33 entries? You should add an EOF test into your for loop to prevent errors. - Paebbels
Line 29 is "readline" ... the fatal error appears to happen when reading the file we don't have. Effort answering question stops here. - user_1818839
I'd support Brian's comment, there are only 3 statements in the for loop. It sounds like you have a problem with your stddata file. As Patrick Lehmann notes You could test for EOF (ENDFILE), which would allow you note if your file were short. inst_mem is array (0 to 32), 33 entries as Morten Zilmer notes. - user1155120

1 Answers

4
votes

I'd support Brian's comment, there are only 3 statements in the for loop. It sounds like you have a problem with your stddata file. As Patrick Lehmann notes You could test for EOF (ENDFILE), which would allow you note if your file were short. inst_mem is array (0 to 32), 33 entries as Morten Zilmer notes.

I instantiated your model (with changes to support a -1993 compliant VHDL tool, and switching from conv_integer to to_integer in package numeric_std, you can ignore the extra stuff in the architecture declarative region):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
-- USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;

entity inst_mem is
    port(
        load: in std_logic;
        address: in std_logic_vector (5 downto 0); 

        dataout: out std_logic_vector (10 downto 0)
        );
end entity;

architecture arch_inst_mem of inst_mem is
    TYPE inst_mem is array (0 to 32) of std_logic_vector(10 downto 0);

    type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR);
    type MVL9_indexed_by_char is array (character) of STD_ULOGIC;
    type MVL9plus_indexed_by_char is array (character) of MVL9plus;

    constant char_to_MVL9: MVL9_indexed_by_char :=
        ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
         'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U');

    constant char_to_MVL9plus: MVL9plus_indexed_by_char := 
        ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
         'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR);

    procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is
        variable m:  STD_ULOGIC;
        variable c:  character;
        variable s:  string(1 to value'length-1);
        variable mv: STD_LOGIC_VECTOR(0 to value'length-1);
        constant allU: STD_LOGIC_VECTOR(0 to value'length-1)
                        := (others => 'U');
        variable GOOD: boolean;
    begin
        loop                    -- skip white space
            read(l,c);
            exit when ((c /= ' ') and (c /= CR) and (c /= HT));
        end loop;

        if (char_to_MVL9plus(c) = ERROR) then
            value := allU;
            good := FALSE;
            return;
        end if;

        read(l, s);
            for i in integer range 1 to value'length-1 loop
            if (char_to_MVL9plus(s(i)) = ERROR) then
                value := allU;
                good := FALSE;
                    return;
            end if;
        end loop;

        mv(0) := char_to_MVL9(c);
            for i in integer range 1 to value'length-1 loop
            mv(i) := char_to_MVL9(s(i));
            end loop;
        value := mv;
        good := TRUE;
    end READ;


    procedure init_mem(variable memory : out inst_mem; 
                                    constant datafile : string) is
        file stddata: text;
        variable l: line;
        variable data: std_logic_vector (10 downto 0);
    begin
        file_open (stddata, datafile, READ_MODE);
        for i in memory'range(1) loop
            readline (stddata, l);
            read (l, data);
            memory(i):= data;
        end LOOP;
    end procedure;


begin
  process (load , address)
    variable memory: inst_mem;
  begin
    if (load = '1') then
        init_mem (memory, "inst_mem.txt");
        dataout <= memory (to_integer(unsigned(address))); -- (conv_integer(address));
    end if;
  end process;
end arch_inst_mem;

And generated at inst_mem.txt file with 33 entries:

00000000000
00000000001
00000000010
00000000011
00000000100
00000000101
00000000110
00000000111
00000001000
00000001001
00000001010
00000001011
00000001100
00000001101
00000001110
00000001111
00000010000
00000010001
00000010010
00000010011
00000010100
00000010101
00000010110
00000010111
00000011000
00000011001
00000011010
00000011011
00000011100
00000011101
00000011110
00000011111
00000100000

And the model successfully ran under ghdl (0.31, -1993 compliant).

By doing some very ugly stuff in ghdl (which doesn't support variable display in waveforms) I can demonstrate that inst_mem memory is initialized by the init_mem sequential procedure call: inst_mem.png (clickable)

Which says more than likely, you have the wrong number of entries in inst_mem.txt, which gives a failure because ENDFILE isn't used to detect EOF:

ghdl -r inst_mem --wave=inst_mem.ghw
../../../src/std/textio_body.v93:558:5:@1ns:(assertion failure): character read failure
./inst_mem:error: assertion failed
./inst_mem:error: simulation failed
ghdl: compilation error

For only 32 entries.

(And you notice ghdl doesn't back trace into the design specification.)

If there were an illegal entry you would have gotten a bunch of un-defines in a particular memory location.

So it looks like you should have either defined:

TYPE inst_mem is array (0 to 31) of std_logic_vector(10 downto 0);

type inst_mem as a 32 entry array, or insured your inst_mem.txt file had the proper number of entries, or used an ENDFILE test and simply not initialized any remaining array elements.

And addding an ENDFILE test:

procedure init_mem(signal memory : out inst_mem; 
                                constant datafile : string) is
    file stddata: text;
    variable l: line;
    variable data: std_logic_vector (10 downto 0);
begin
    file_open (stddata, datafile, READ_MODE);
    for i in memory'range(1) loop
        if not ENDFILE(stddata) then
            readline (stddata, l);
            read (l, data);
            memory(i) <= data;
        end if;
    end LOOP;
    FILE_CLOSE(stddata);
end procedure;

eliminates the above error. It's also got the side effect of leaving any remaining array elements uninitialized.

You'd also notice I added the FILE_CLOSE procedure Morten recommends, under the theory that you could reinitialize the memory array anytime you have an event on either load or address and load = '1'.

And that also tells you that you should detect load going high and not the level:

  process (load , address)
    variable memory: inst_mem;
  begin
    if load'event and load = '1' then
        init_mem (memory, "inst_mem.txt");
        dataout <= memory (conv_integer(address));
    end if;
  end process;

Assuming this is in a test bench or not a synthesis target.

If you were intending to supply an initialization file to be embedded in an FPGA bitstream, you'd want to adhere to the vendors process for doing so.

You're trying to use the same process because you've declared memory as a variable. It could be a shared variable. and you could have two separate processes one to initialize, one to read.

Implementing memory as a signal is a bit easier and wouldn't incur any performance penalty in this case.

(I have an interest in textio issues.)