3
\$\begingroup\$

I wrote VHDL to instantiate some RAM (256 bytes) using BRAM on a Digilent BASYS 3 FPGA development board using Vivado design tools. It takes 8 bits as the data input and outputs 8 bits on the output. A write to RAM is synchronous and performed on the rising edge when store (write) input is high. Read from output port is always performed by forced to zeros if the enable signal is high with AND gates.

My issue is that the RAM output is always zeros. Even if I define all 256 bytes as 0xFF (others => 0xFF) the output is still zeros. Can anyone see the problem here?

Code is as follows with a simulation and :

Code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Random_Access_Memory is
 Port (D_i : in std_ulogic_vector(7 downto 0);
 Addr_i : in std_ulogic_vector(7 downto 0);
 Clock_i : in std_ulogic;
 Store_i : in std_ulogic; --Active low input
 Enable_i : in std_ulogic; --Active low input
 Q_o : out std_ulogic_vector(7 downto 0);
 
 Addr_in_temp_o : out integer range 0 to 255
 );
end Random_Access_Memory;
architecture Behavioral of Random_Access_Memory is
type RAM_ARRAY is array (0 to 255) of std_ulogic_vector(7 downto 0);
signal RAM : RAM_ARRAY := 
(
-- 0 => "00000001", 
-- 1 => "11111111", 
-- 2 => "00010000", 
 others => "11111111"
);
signal Addr_in_temp : integer range 0 to 255;
signal D_in_temp : unsigned(7 downto 0);
signal D_out_temp : std_ulogic_vector(7 downto 0);
begin
 Process(Clock_i, Addr_i)
 begin
 
 if(rising_edge(Clock_i)) then
 if(Store_i = '0') then
 RAM(Addr_in_temp) <= D_i; 
 
 end if;
 
 end if;
 
 end Process;
Addr_in_temp_o <= Addr_in_temp;
Addr_in_temp <= to_integer(unsigned(Addr_i));
D_out_temp <= RAM(Addr_in_temp);
Q_o(0) <= D_out_temp(0) and (not Enable_i);
Q_o(1) <= D_out_temp(1) and (not Enable_i);
Q_o(2) <= D_out_temp(2) and (not Enable_i);
Q_o(3) <= D_out_temp(3) and (not Enable_i);
Q_o(4) <= D_out_temp(4) and (not Enable_i);
Q_o(5) <= D_out_temp(5) and (not Enable_i);
Q_o(6) <= D_out_temp(6) and (not Enable_i);
Q_o(7) <= D_out_temp(7) and (not Enable_i);
end Behavioral;

Testbench


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Top_tb is
end Top_tb;
architecture Behavioral of Top_tb is
component Random_Access_Memory is
 Port (D_i : in std_ulogic_vector(7 downto 0);
 Addr_i : in std_ulogic_vector(7 downto 0);
 Clock_i : in std_ulogic;
 Store_i : in std_ulogic; --Active low input
 Enable_i : in std_ulogic; --Active low input
 Q_o : out std_ulogic_vector(7 downto 0);
 
 Addr_in_temp_o : out integer range 0 to 255
 
 );
end component;
signal D_i_tb : std_ulogic_vector(7 downto 0);
signal Addr_i_tb : std_ulogic_vector(7 downto 0);
signal Clock_i_tb : std_ulogic; 
signal Store_i_tb : std_ulogic;
signal Enable_i_tb : std_ulogic;
signal Q_o_tb : std_ulogic_vector(7 downto 0);
signal Addr_in_temp_o_tb : integer range 0 to 255;
constant clock_period : time := 10 ns;
begin
DUT : Random_Access_Memory
 Port map (D_i => D_i_tb, 
 Addr_i => Addr_i_tb,
 Clock_i => Clock_i_tb,
 Store_i => Store_i_tb,
 Enable_i => Enable_i_tb,
 Q_o => Q_o_tb
 );
Clock_Gen : Process
 begin
 Clock_i_tb <= '0';
 wait for clock_period/2;
 Clock_i_tb <= '1';
 wait for clock_period/2;
 end process; 
D_i_tb <= "00000000";
Addr_i_tb <= "00000001";
Store_i_tb <= '0';
Enable_i_tb <= '0';
end Behavioral;

Simulation Waveform

Simulation Waveform

toolic
10.8k11 gold badges31 silver badges35 bronze badges
asked Feb 4, 2023 at 13:23
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Shouldn't if(Store_i = '0') then check for a 1 instead of a 0? \$\endgroup\$ Commented Feb 4, 2023 at 13:53
  • \$\begingroup\$ Actually I wrote the question wrong, the Store_i input should be active low so I should have had the testbench setting the Store_i input high instead of low and continually writing to RAM. Thanks for pointing that out. \$\endgroup\$ Commented Feb 4, 2023 at 20:27
  • \$\begingroup\$ Why does RAM VHDL simulation output unexpectedly always shows zero? \$\endgroup\$ Commented Feb 8, 2023 at 19:38

2 Answers 2

2
\$\begingroup\$

There are some small problems in your code: The output Addr_in_temp_o of Ramdom_Access_memory is not connected in your testbench. So the simulation always shows the value 0 (default value of integer) at the signal Addr_in_temp_o_tb. The clocked process in Random_Access_Memory is also sensitive to Addr_i which is not needed.

But the real problem is: In your testbench you permanently write (store=0) a 0 into the address 1 and you also read permanently (enable=0) from address 1. So of course you always read 0. If you zoom in at the time 0, you perhaps can see the value FF for 1 clock cycle at the read data output.

toolic
10.8k11 gold badges31 silver badges35 bronze badges
answered Feb 4, 2023 at 14:01
\$\endgroup\$
2
\$\begingroup\$

Assuming you are interested only in simulated behaviour, since this initialization may not be synthesizeable, both types work:

signal RAM : RAM_ARRAY := ( others => (others => '1') );
signal RAM : RAM_ARRAY := ( others => "11111111" );

But, since you are not stopping the simulation, you don't see the first and only cycle when the 0xFF appears. To stop it, you could do the following:

Clock_Gen : Process
begin
 Clock_i_tb <= '0';
 wait for clock_period/2;
 Clock_i_tb <= '1';
 wait for clock_period/2;
 wait; -- Stop the simulation
end process;

enter image description here

answered Feb 4, 2023 at 14:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.