library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;

entity Debouncer is
     generic(   kHzClkFreq : positive := 50_000;
                mSecMinInWidth : positive := 100;
                inPolarity : std_logic := '0';
                outPolarity : std_logic := '1');
     port(  refClk : in std_logic;
            dirtyIn : in std_logic;
            pulsedOut : out std_logic);
end Debouncer;

architecture Behavioral of Debouncer is
     constant MIN_IN_WIDTH_CYCLES : positive := mSecMinInWidth * kHzClkFreq;
     subtype TCounter is natural range 0 to MIN_IN_WIDTH_CYCLES;
     signal s_debounceCnt : TCounter := 0;
     signal s_dirtyIn, s_previousIn, s_pulsedOut : std_logic;
begin

 in_sync_proc : process(refClk)
 begin
     if (rising_edge(refClk)) then
         if (inPolarity = '1') then
            s_dirtyIn <= dirtyIn;
         else
            s_dirtyIn <= not dirtyIn;
         end if;
            s_previousIn <= s_dirtyIn;
     end if;
 end process;
 
 count_proc : process(refClk)
 begin
     if (rising_edge(refClk)) then
         if ((s_dirtyIn = '0') or
             (s_debounceCnt > MIN_IN_WIDTH_CYCLES)) then
             s_debounceCnt <= 0;
             s_pulsedOut <= '0';
         elsif (s_dirtyIn = '1') then
            if (s_previousIn = '0') then
                s_debounceCnt <= MIN_IN_WIDTH_CYCLES;
                s_pulsedOut <= '0';
            else
                if (s_debounceCnt >= 1) then
                    s_debounceCnt <= s_debounceCnt - 1;
                end if;
                if (s_debounceCnt = 1) then
                    s_pulsedOut <= '1';
                else
                    s_pulsedOut <= '0';
                end if;
            end if;
         end if;
     end if;
 end process;
 
 pulsedOut <= s_pulsedOut when (outPolarity = '1') else not s_pulsedOut;
 
end Behavioral;