I want to use four push buttons as inputs and three seven-segment LED displays as outputs. Two push buttons should step up and down through the sixteen RAM locations; the other two should increment and decrement the contents of the currently-displayed memory location. I have the following two entities:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DE2_TOP is
port (
KEY : in std_logic_vector(3 downto 0); -- Push button
CLOCK_50: in std_logic;
);
end DE2_TOP;
architecture datapath of DE2_TOP is
begin
U1: entity work.lab1 port map (
key => key,
clock => clock_50,
);
end datapath;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity raminfr is -STANDARD RAM INFERENCE
port (
clock: in std_logic;
we : in std_logic;
a : in unsigned(3 downto 0);
di : in unsigned(7 downto 0);
do : out unsigned(7 downto 0)
);
end raminfr;
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
begin
process (clock)
begin
if rising_edge(clock) then
if we = '1' then
RAM(to_integer(a)) <= di;
end if;
read_a <= a;
end if;
end process;
do <= RAM(to_integer(read_a));
end rtl;
and
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lab1 is
port(
clock : in std_logic;
key : in std_logic_vector(3 downto 0);
);
end lab1;
architecture up_and_down of lab1 is
signal value_in_ram : unsigned(7 downto 0);
signal we : std_logic;
signal value_counter : unsigned(7 downto 0) ;
signal register_counter : unsigned(3 downto 0);
begin
U1: entity work.raminfr port map (
a => register_counter,
di => value_counter,
do => value_in_ram,
clock => clock,
we => we
);
process(clock)
begin
if rising_edge(clock) then
if (key(3)='0' and key(2)='0' and key(1)='1' and key(0)='0') then
value_counter <= value_counter + "1";
elsif (key(3)='0' and key(2)='0' and key(1)='0' and key(0)='1') then
value_counter <= value_counter - "1";
elsif (key(3)='1' and key(2)='0' and key(1)='0' and key(0)='0') then
register_counter<= register_counter + "1";
value_counter <= value_in_ram;
elsif (key(3)='0' and key(2)='1' and key(1)='0' and key(0)='0') then
register_counter<= register_counter - "1";
value_counter <= value_in_ram;
end if;
end if;
end process;
end architecture up_and_down;
I also have the following test bench, where I try to simulate buttons being pressed via KEY:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DE2_TOP_TEST is
end;
architecture BENCH of DE2_TOP_TEST is
signal KEY : std_logic_vector(3 downto 0);
signal CLOCK_50 : std_logic := '0';
signal hex4, hex5, hex6 : std_logic_vector(6 downto 0);
begin
clock_50 <= not clock_50 after 50 ns;
process
begin
KEY<="0010";
wait for 1 us;
KEY<="0000";
end process;
uut:work.DE2_TOP port map (
KEY=>key,
CLOCK_50=>clock_50,
hex4=>hex4,
hex5=>hex5,
hex6=>hex6
);
end BENCH;
My test bench set up looks like this:
To simulate, I compile all three of the above files, and then simulate DE2_TOP_TEST, but am met with the result that my "KEY" is still undefined, as below (although CLOCK_50 does get the default value that I set):
Anyone know what's causing this?
(1) You have unconnected ports on the entity you are typing to test. The test results are as expected for those inputs - specifically, clk, being undriven.
(2) Having connected clk, you will need to drive it.
signal clk : std_logic := '0';
and
clk <= not clk after 50 ns;
should give a 10MHz clock, check this in the simulator
(3) Drive "KEY" with a specific sequence of values
subtype keys is std_logic_vector(3 downto 0);
constant count_up : keys := "0001";
constant count_dn : keys := "0010";
constant idle : keys := "0000";
-- etc
process
begin
KEY <= count_up;
wait for 1 us;
KEY <= idle;
wait for ...
-- etc
end process;
(4) Bring the OUTPUTS back out into the testbench so that you can check their values. You need to bring them out as ports in the top level (design) entity anyway, if you are going to connect them to a display!
Then (later, once things have started going to plan) you can test them in the testbench process...
wait for 100 ns;
-- after the last press, we should have "07" on the display
assert digit(1) = "0111111" report "Left digit has wrong value" severity ERROR;
assert digit(0) = "0000111" report "Left digit has wrong value" severity ERROR;
A self-checking testbench like this saves debugging by staring at waveforms. You only need the waveforms when the tests are failing...