library ieee; use ieee.std_logic_1164.all; entity debounce is port( clk: in std_logic; key_in: in std_logic_vector(7 downto 0); key_pressed_out: out std_logic_vector(7 downto 0); key_down_out: out std_logic_vector(7 downto 0); key_up_out: out std_logic_vector(7 downto 0) ); end debounce; architecture RTL of debounce is -- registers signal state0, state1, state2: std_logic_vector(7 downto 0) := (others => '0'); signal key_pressed_old: std_logic_vector(7 downto 0) := (others => '0'); signal key_pressed: std_logic_vector(7 downto 0) := (others => '0'); begin process(clk) begin if rising_edge(clk) then -- and ce = '1' state0 <= key_in; state1 <= state0; state2 <= state1; end if; end process; process(clk) variable state: std_logic_vector(2 downto 0); begin if rising_edge(clk) then for i in state0'range loop state := state2(i) & state1(i) & state0(i); case state is when "000" => key_pressed(i) <= '0'; when "001" => key_pressed(i) <= '0'; when "010" => key_pressed(i) <= '0'; when "100" => key_pressed(i) <= '0'; when others => key_pressed(i) <= '1'; end case; end loop; key_pressed_old <= key_pressed; end if; end process; process(key_pressed, key_pressed_old) begin key_down_out <= key_pressed and (not key_pressed_old); key_up_out <= (not key_pressed) and key_pressed_old; key_pressed_out <= key_pressed; end process; end RTL; library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity debounce_tb is end debounce_tb; architecture tb of debounce_tb is component debounce is port( clk: in std_logic; key_in: in std_logic_vector(7 downto 0); key_pressed_out: out std_logic_vector(7 downto 0); key_down_out: out std_logic_vector(7 downto 0); key_up_out: out std_logic_vector(7 downto 0) ); end component; signal clk: std_logic := '0'; signal key_in: std_logic_vector(7 downto 0); signal key_pressed: std_logic_vector(7 downto 0); signal key_down: std_logic_vector(7 downto 0); signal key_up: std_logic_vector(7 downto 0); begin debounce_inst: debounce port map( clk => clk, key_in => key_in, key_pressed_out => key_pressed, key_down_out => key_down, key_up_out => key_up ); process begin -- key pressed key_in <= "10000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "00000000"; assert key_down = "00000000"; assert key_up = "00000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "10000000"; assert key_down = "10000000"; assert key_up = "00000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "10000000"; assert key_down = "00000000"; assert key_up = "00000000"; -- short low-pulse should not change anything key_in <= "00000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "10000000"; assert key_down = "00000000"; assert key_up = "00000000"; key_in <= "10000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "10000000"; assert key_down = "00000000"; assert key_up = "00000000"; -- key released key_in <= "00000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "00000000"; assert key_down = "00000000"; assert key_up = "10000000"; clk <= '1'; wait for 1 us; clk <= '0'; wait for 1 us; assert key_pressed = "00000000"; assert key_down = "00000000"; assert key_up = "00000000"; report "finished" severity failure; end process; end tb;