-- filename:          debouncer.vhd
-- kind:              vhdl file
-- first created:     05.03.2012
-- created by:        zas
--------------------------------------------------------------------------------
-- History:
-- v0.1 : zas 05.03.2012 -- Initial Version
-- v0.2 : cof 22.01.2013 -- synchronization to clock
--------------------------------------------------------------------------------
-- Description: 
-- Debounces a button on both edges.
--             _   _   ____________________   _   _
-- input  ____/ \_/ \_/                    \_/ \_/ \______
--              _____________________________
-- output _____/                             \____________
--
--------------------------------------------------------------------------------

ARCHITECTURE rtl OF debouncerULogicVector IS
 
  signal inputNormal : std_ulogic_vector(input'range);
  signal inputSynch, inputDelayed, inputChanged : std_ulogic;
  signal debounceCounter : unsigned(counterBitNb-1 downto 0);
 
BEGIN
  ------------------------------------------------------------------------------
                                                               -- adapt polarity
  adaptPolarity: process(input)
  begin
    for index in input'range loop
      inputNormal(index) <= input(index) xor invertInput;
    end loop;
  end process adaptPolarity;

  ------------------------------------------------------------------------------
                                                   -- Synchronize input to clock
  synchInput: process(reset, clock)
    variable inputOr : std_ulogic;
  begin
    if reset = '1' then
      inputSynch <= '0';
    elsif rising_edge(clock) then
      inputOr := '0';
      for index in input'range loop
        inputOr := inputOr or inputNormal(index);
      end loop;
      inputSynch <= inputOr;
    end if;
  end process synchInput;

  ------------------------------------------------------------------------------
                                                           -- Find edge on input
  delayInput: process(reset, clock)
  begin
    if reset = '1' then
      inputDelayed <= '0';
    elsif rising_edge(clock) then
      inputDelayed <= inputSynch;
    end if;
  end process delayInput;

  inputChanged <= '1' when inputDelayed /= inputSynch
    else '0';

  ------------------------------------------------------------------------------
                                                             -- Debounce counter
  countDeadTime: process(reset, clock)
  begin
    if reset = '1' then
      debounceCounter <= (others => '0');
    elsif rising_edge(clock) then
      if debounceCounter = 0 then
        if inputChanged = '1' then
          debounceCounter <= debounceCounter - 1;
        end if;
      else
        debounceCounter <= debounceCounter - 1;
      end if;
    end if;
  end process countDeadTime;

  ------------------------------------------------------------------------------
                                                                -- Update output
  updateOutput: process(reset, clock)
  begin
    if reset = '1' then
      debounced <= (others => '0');
    elsif rising_edge(clock) then
      if (inputChanged = '1') and (debounceCounter = 0) then
        debounced <= inputNormal;
      elsif debounceCounter = 1 then
        debounced <= inputNormal;
      end if;
    end if;
  end process updateOutput;
 
END ARCHITECTURE rtl;