Search code examples
initializationvhdlfpgamodelsim

How to initialize std_logic_vector?


I have this code

--RAM module
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;

entity RAM is
  generic(
    address_length, data_length : integer);
  port(
    addr       : in    std_logic_vector(address_length-1 downto 0);
    dat        : inout std_logic_vector(data_length-1 downto 0);
    rd, wr, en : in    bit);
end entity RAM;

architecture RAM_impl of RAM is
  type mem is array(2**address_length-1 downto 0) of std_logic_vector(data_length-1 downto 0);
begin
  process(rd, wr, en)is
    variable cont : mem;
  begin
    if(en = '1')then
      if(wr = '1' and rd = '0')then
        cont(to_integer(unsigned(addr))) := dat;
      end if;
      if(rd = '1' and wr = '0')then
        dat <= cont(to_integer(unsigned(addr)));
      end if;
    end if;
  end process;
end architecture RAM_impl;


--Test module
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;

entity Example4RAM is
end entity Example4RAM;

architecture Tester of Example4RAM is
  signal rd, wr, en : bit;
  signal str        : std_logic_vector(15 downto 0);
  signal ext        : std_logic_vector(7 downto 0);
begin
  module : entity work.RAM(RAM_impl)
    generic map(
      address_length => 16,
      data_length    => 8)
    port map(str, ext, rd, wr, en);
  tt : process is
  begin
    str <= X"0001";
    ext <= "00000000";
    rd  <= '0'; wr <= '1';
    wait for 5 ns;
    en  <= '1';
    wait for 5 ns;
    rd  <= '0'; wr <= '0';
    wait for 10 ns;
    rd  <= '1'; wr <= '0';
  end process;
end architecture Tester;

When i run simulation on this RAM module str vector initializes fine but ext vector stays uninitialized. In RAM module str is in vector and ext is inout vector. Is this somehow making problem and does anyone know the solution? (I did change source since yesterday but it doesn't work still)


Solution

  • I added a RAM module and tinkered with the test stimulus slightly (ext is driven to all 'Z's when wr goes invalid (the behavioral model requires no hold over).

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity RAM is
        generic (
            constant address_length:    natural := 16;
            constant data_length:       natural := 8
        );
        port (
            signal str:     in      std_logic_vector (address_length-1 downto 0);
            signal ext:     inout   std_logic_vector (data_length-1  downto 0);
            signal rd:      in      BIT;
            signal wr:      in      BIT
        );
    end entity; 
    
    architecture RAM_impl of RAM is
        type ram_array is array (natural range address_length-1 downto 0) 
            of std_logic_vector (data_length-1 downto 0);
        signal mem_array: ram_array;
    begin
    
    
    MEMORY:
        process (str, ext, rd, wr)
            variable addr:  natural range 0 to 2**address_length -1 ;
        begin
            addr := TO_INTEGER(UNSIGNED(str));  -- heed the warnings
            if wr = '1' then
                mem_array(addr) <= ext;
            end if;
            if rd = '0' then
                ext <= (others => 'Z');
            else
                ext <= mem_array(addr);
            end if;
        end process;
    
    
    end architecture;
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    -- use IEEE.numeric_std.ALL;
    
    entity Example4RAM is
    end entity Example4RAM;
    
    architecture Tester of Example4RAM is
    signal rd,wr,clk: bit;
    signal str: std_logic_vector(15 downto 0);
    signal ext: std_logic_vector(7 downto 0);
    begin
    
    module: 
        entity work.RAM(RAM_impl) 
            generic map (
                address_length=>16,
                data_length=>8
            )
            port map (
                str,
                ext,
                rd,
                wr
            )
        ;
    
    tt:
        process
        begin
            str<=X"0001";
            ext<="00000000";
            wait for 5 ns;
            rd<='0';wr<='1';
            wait for 5 ns;
            rd<='0';wr<='0';
            ext <= (others => 'Z');  -- ADDED
            wait for 10 ns;
            rd<='1';wr<='0'; 
            wait for 20 ns;  -- ADDED
            str <=X"0002";   -- ADDED
            wait for 20 ns;  -- ADDED
            wait;
        end process;
    end architecture Tester;
    

    The change to the stimulus includes a change to the RAM address showing that reading an uninitialized location returns 'U's (uu on the waveform):

    RAM write followed by RAM read with a subsequent different address

    ghdl -a exampleram.vhdl
    ghdl -r Example4RAM --wave=Example4RAM.ghw
    ../../../../libraries/ieee/numeric_std-body.v93:2098:7:@0ms:(assertion warning):   
    NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
    open *.ghw
    

    Essentially, the process and the RAM drive ext with all 'Z's whenever either one shouldn't be driving a value out. Writing before reading hides the 'U' values from str address X"0001". As you see, if the address is changed to a location that is not initialized, the 'U's show up. Resolution delivers the RAM read data or provides write data to the RAM array on the bidirectional data bus (ext).

    (This was done on a Mac with a ghdl mcode version (direct compile, like for Windows, requiring no explicit elaboration), and displayed using GTKWave).

    The assertion warning (metavalue detected) comes from the default value assigned to str (all 'U's) at time zero (@0ms).