--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--------------------------------------------------------------------------------
ENTITY Debouncer IS
  PORT(
    clk             : IN  STD_LOGIC;
    clk_en          : IN  STD_LOGIC;
    Btn_in          : IN  STD_LOGIC;
    Btn_debounced   : OUT STD_LOGIC);
END Debouncer;
--------------------------------------------------------------------------------
ARCHITECTURE Behavioral OF Debouncer IS
  SIGNAL   shift_reg    : STD_LOGIC_VECTOR(3 DOWNTO 0)      := (OTHERS => '0');
  CONSTANT all_ones     : STD_LOGIC_VECTOR(shift_reg'range) := (OTHERS => '1');
  CONSTANT all_zeros    : STD_LOGIC_VECTOR(shift_reg'range) := (OTHERS => '0');
BEGIN
--------------------------------------------------------------------------------
  debounce_proc: PROCESS(clk) BEGIN
    IF rising_edge(clk) THEN
      IF clk_en = '1' THEN

        -- shift register (delay)
        shift_reg <= shift_reg(shift_reg'HIGH-1 DOWNTO 0) & Btn_in;

        -- rising edge
        -- all previos values are '0' and Btn_in = '1' is now detected
        IF shift_reg = all_zeros AND Btn_in = '1' THEN
          Btn_debounced <= '1';
        END IF;

        -- falling edge
        -- all previos values are '1' and Btn_in = '0' is now detected
        IF shift_reg = all_ones  AND Btn_in = '0' THEN
          Btn_debounced <= '0';
        END IF;

      END IF;
    END IF;
  END PROCESS debounce_proc;

--------------------------------------------------------------------------------
END Behavioral;
--------------------------------------------------------------------------------
