Question

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:

enter image description here

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

enter image description here

Anyone know what's causing this?

Was it helpful?

Solution

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

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