0
\$\begingroup\$

I am describing a very simple ram memory in VHDL and observing strange behaviour which I do not understand nor am able to debug. I have similar code written elsewhere and I suspect that rewriting it would do the trick, but I am now very eager to find out what is wrong (having spent a fair amount of time on it).

Main code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;
use ieee.NUMERIC_STD_UNSIGNED.all;

entity data_memory is

    port(
         data_address: in std_logic_vector(4 downto 0); -- data address
         clk : in std_logic;
         we : in std_logic;
         write_data : in std_logic_vector(31 downto 0);
         data : out std_logic_vector(31 downto 0)
        );

end data_memory;

architecture data_arc of data_memory is


    type ram_32x32 is array (31 downto 0) of std_logic_vector(31 downto 0);

    signal mem: ram_32x32;

    begin

      

        write: process(clk) -- o processo eh sensivel apenas ao clock
        begin

        if rising_edge(clk) then  
            if (we = '1') then e
                mem(to_integer(data_address)) <= write_data ; 
            end if;
        end if; 

        end process write;

        read: process(data_address, clk, we, write_data)      -- sensivel a todos os sinais

        begin

            data <= mem(to_integer(data_address));

        end process read;

end data_arc;

Testbench:

library IEEE;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;

entity tb_data_memory is
end tb_data_memory;

architecture tb of tb_data_memory is

    component data_memory is -- registrador de 32 palavras
        port(
        data_address : in std_logic_vector(4 downto 0);
        clk : in std_logic;
        we : in std_logic;
        write_data : in std_logic_vector(31 downto 0);
        data : out std_logic_vector(31 downto 0)
        );
    end component;

    constant clock_frequency : integer := 10e6; -- 10Mhz
    constant clock_period : time := 1000 ms /clock_frequency;

    signal we : std_logic := '1';
    signal clk : std_logic := '1';
    signal data_address : std_logic_vector(4 downto 0) := (others => '0');
    signal write_data : std_logic_vector(31 downto 0) := (others => '0');

    signal data : std_logic_vector(31 downto 0);

    begin

        uut: data_memory port map(
                                     data_address => data_address,
                                     clk => clk,
                                     we => we,
                                     write_data => write_data,
                                     data => data
                                   );

        clk <= not clk after clock_period / 2;

        test_bench: process

        constant period: time := 200 ns;

            begin
                
                data <= "00000000000000000000000000000000";

                wait for period;

                we <= '1';
                write_data <= "00000000000000000000000000000100";
                data_address <= "00001";

                wait for period;

                write_data <= "00000000000000000000000000000001";
                data_address <= "00010";

                wait for period;

                we <= '0';
                data_address <= "00001";

                wait for period;

                data_address <= "00010";

                wait for period;

        end process test_bench;
end tb;

.do file:

view wave
delete wave *
add wave *
run 1 us
property wave -radix unsigned *

current behaviour:

enter image description here

I have tried without driving the data output and obtained similar (altough slightly better looking) results.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Check the read process sensitivity list. Too many signals in there, should just be data_address. Also why are you assigning data <= "00000000000000000000000000000000"; in your testbench. That's an output port driven from the memory. You should not assign anything to it in the testbench. You initialize the memory in the memory module. \$\endgroup\$
    – mrbean
    Commented Mar 5, 2021 at 2:31
  • 1
    \$\begingroup\$ What stops you from simply scrapping the erratic read process and simply write data <= mem (....) ; inside the architecture ????? \$\endgroup\$
    – Mitu Raj
    Commented Mar 5, 2021 at 4:11
  • \$\begingroup\$ thank you guys for the comments. this is my first week into vhdl, so these observations were not trivial to me :) \$\endgroup\$
    – Lara
    Commented Mar 5, 2021 at 12:04

1 Answer 1

0
\$\begingroup\$

As the commenters to the question observe, there are a few things that don't make much sense in this code. First of all, the data <= "00000000000000000000000000000000"; drive should not happen, as the signal is an output. What this drive intends to do should be achieved by initializing the memory in its architecture.

Also the read process sensitivity list is to long, it should only contain data address.

With these changes it works:

main code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;
use ieee.NUMERIC_STD_UNSIGNED.all;

entity data_memory is

    port(
         data_address: in std_logic_vector(4 downto 0);
         clk : in std_logic;
         we : in std_logic;
         write_data : in std_logic_vector(31 downto 0);
         data : out std_logic_vector(31 downto 0)
        );

end data_memory;

architecture data_arc of data_memory is
   
    type ram_32x32 is array (31 downto 0) of std_logic_vector(31 downto 0);

    signal mem: ram_32x32 := (others => (others => '0')); -- initializes memory to zeros
    begin


        write: process(clk)
        begin

        if rising_edge(clk) then
            if (we = '1') then
                mem(to_integer(data_address)) <= write_data ; 
            end if;
        end if; clausulas catch all

        end process write;


        read: process(data_address)

        begin

            data <= mem(to_integer(data_address));

        end process read;

end data_arc;

testbench:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;

entity tb_data_memory is
end tb_data_memory;

architecture tb of tb_data_memory is


    component data_memory is -- registrador de 32 palavras
        port(
        data_address : in std_logic_vector(4 downto 0);
        clk : in std_logic;
        we : in std_logic;
        write_data : in std_logic_vector(31 downto 0);
        data : out std_logic_vector(31 downto 0)
        );
    end component;


    constant clock_frequency : integer := 10e6; -- 10Mhz
    constant clock_period : time := 1000 ms /clock_frequency;

    -- inputs

    signal we : std_logic := '0';
    signal clk : std_logic := '0';
    signal data_address : std_logic_vector(4 downto 0) := (others => '0');
    signal write_data : std_logic_vector(31 downto 0) := (others => '0');

    signal data : std_logic_vector(31 downto 0);

    begin


        uut: data_memory port map(
                                     data_address => data_address,
                                     clk => clk,
                                     we => we,
                                     write_data => write_data,
                                     data => data
                                   );

        clk <= not clk after clock_period / 2;

        test_bench: process

        constant period: time := 200 ns;

            begin

                wait for period;

                we <= '1';
                write_data <= "00000000000000000000000000000100";
                data_address <= "00001";

                wait for period;

                write_data <= "00000000000000000000000000000001";
                data_address <= "00010";

                wait for period;

                we <= '0';
                data_address <= "00001";

                wait for period;

                data_address <= "00010";

                wait for period;

        end process test_bench;
end tb;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.