Question

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)

Was it helpful?

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top