Search code examples
vhdl

Unexpected value when reading ROM in the first clock pulse


I'm trying to create a ROM where a number of values is stored and, after receiving a clock pulse, one of its values is read and then sent to the output while the counter that keeps track of the current position in the ROM is increased by 1. The problem that i found is that the ROM value is not retrieved as it should be in the first clock event.

Entity code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity memoria is
    Port ( clock, reset :in STD_LOGIC;
              valor : out  STD_LOGIC_VECTOR(7 downto 0);
           vazia : out  STD_LOGIC);
end memoria;

architecture Behavioral of memoria is

    type ROM is array (0 to 4) of STD_LOGIC_VECTOR(7 downto 0); --Read only memory

    constant mem : ROM := (b"00000000", b"00000001", b"00000010", b"00000011", b"11111111"); --"11111111" is the stop value
    signal mem_value : STD_LOGIC_VECTOR(7 downto 0);

begin
    process(clock, reset)
        variable counter : integer := 0;
    begin

        if reset = '1' then
            valor <= "11111111";
            vazia <= '1';

        elsif clock'event and clock = '1' then
            mem_value <= mem(counter);  --gets the current memory value

            if mem_value = "11111111" then --checks if the value read is the stop one
                vazia <= '1';
            else
                vazia <= '0';
            end if;

            valor <= mem_value;             --sends the memory value read to the output
            if counter < 4 then
                counter := counter + 1; --increases counter by one
            end if;
        else
            valor <= "11111111";
            vazia <= '0';
        end if;
    end process;
end Behavioral;

Test Bench

ENTITY memoria_tb IS
END memoria_tb;

ARCHITECTURE behavior OF memoria_tb IS 

   --Inputs
   signal clock : std_logic;-- := '0';
    signal reset : std_logic := '0';

    --Outputs
   signal valor : std_logic_vector(7 downto 0);
   signal vazia : std_logic;

   -- Clock period definitions
   constant clock_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: entity work.memoria PORT MAP (
          clock => clock,
             reset => reset,
          valor => valor,
          vazia => vazia
        );

   -- Clock process definitions
   clock_process :process
   begin
        clock <= '0';
        wait for clock_period/2;
        clock <= '1';
        wait for clock_period/2;
   end process;  
END;

Image of the error enter image description here

I would like to know how to get the first ROM value in the first clock pulse instead of UUUUUUUU. Thanks for the help.


Solution

  • The problem was that the outputs should always be assigned after the process as noted in this post https://forums.xilinx.com/t5/General-Technical-Discussion/Counter-implementation-in-vhdl/td-p/570433.

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    
    entity memoria is
        Port ( clock, reset :in STD_LOGIC;
                  valor : out  STD_LOGIC_VECTOR(7 downto 0);
               vazia : out  STD_LOGIC);
    end memoria;
    
    architecture Behavioral of memoria is
    
        type ROM is array (0 to 4) of STD_LOGIC_VECTOR(7 downto 0); --Read only memory
    
        constant mem : ROM := (b"00000000", b"00000001", b"00000010", b"00000011", b"11111111"); --"11111111" is the stop value
        signal mem_value : STD_LOGIC_VECTOR(7 downto 0);
        signal empty : STD_LOGIC;
    
    begin
        process(clock, reset)
            variable counter : integer := 0;
        begin
    
            if reset = '1' then
                mem_value <= "11111111";
                empty <= '1';
    
            elsif clock'event and clock = '1' then
                mem_value <= mem(counter);  --gets the current memory value
    
                if mem_value = "11111111" then --checks if the value read is the stop one
                    empty <= '1';
                else
                    empty <= '0';
                end if;
    
    
                if counter < 4 then
                    counter := counter + 1; --increases counter by one
                end if;
            else
                mem_value <= "11111111";
                empty <= '0';
            end if;
        end process;
    
        valor <= mem_value;             --sends the memory value read to the output
        vazia <= empty;
    end Behavioral;