----------------------------------------------------------------------------------
-- Company:        CERN, BE-CO-HT
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    11:11:43 10/25/2011 
-- Design Name: 
-- Module Name:    i2c_debounce - Behavioral 
-- Project Name:   CTDAH
-- Target Devices: Spartan 6
-- Tool versions: 
-- Description:    This is a I2C debouncer. The main difference is that it is 
--                 intended to filter out low glitches. That means the oppositive
--                 from the previous version --debouncer.vhd.
--                 This behaviour makes more sense compared on how I2C definition
--                 resolves arbitration --conceptually the same as this module.
--
--                 A '1' in the glitch_mask means that the bit should be studied.
-- Dependencies:   None
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
library work;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.ctdah_pkg.ALL;

entity i2c_debouncer is
   generic (
      g_LENGTH    : UNSIGNED(3 downto 0) := "0110";
      g_outputONrise : BOOLEAN := TRUE
      );
   port (
      rst         : IN   std_logic;
      
      clk         : IN   std_logic;
				
      input       : IN   std_logic;
      output      : OUT  std_logic;

      glitch_mask : IN  std_logic_vector(to_integer(g_LENGTH)-1 downto 0)
      );
end i2c_debouncer;

architecture Behavioral of i2c_debouncer is
-- Signals

signal meta_ff1   : std_logic;
signal delay_s    : std_logic_vector(to_integer(g_LENGTH)-1 downto 0);

signal output_s   : std_logic;

begin


   ff1: gc_ff
      port map(
         Q  => meta_ff1,
         C  => clk,
         CLR  => rst,
         D  => input
         );

   ff2: gc_ff
      port map(
         Q  => delay_s(0),
         C  => clk,
         CLR  => rst,
         D  => meta_ff1
         );

-- Metastability solved here

   delay_line: for i in 1 to to_integer(g_LENGTH)-1 generate
      D_Flip_Flop : gc_ff
         port map (
            Q   => delay_s(i),
            C   => clk,
            CLR => rst,
            D   => delay_s(i-1));
    end generate delay_line;

-- This is not VHDL 2008 to support backwards compatibility
outputFalling: if not(g_outputONrise) generate

   process (clk)
      begin
      if rising_edge(clk) then
         if rst = '1' then
            output_s  <= '1';
         elsif ( (delay_s and glitch_mask) = glitch_mask or (not(delay_s)and glitch_mask) = glitch_mask) then
            output_s   <= delay_s(0);
         else
            output_s  <= '1';
         end if;
      else 
         output     <= output_s;
      end if;
   end process;
end generate outputFalling;

outputRising: if g_outputONrise generate

   process (clk)
   begin
      if rising_edge(clk) then
         if rst = '1' then
            output  <= '1';
         elsif ( (delay_s and glitch_mask) = glitch_mask or (not(delay_s)and glitch_mask) = glitch_mask) then
            output  <= delay_s(0);
         else
	    -- Internall pull-up of the pin
	      output <= '1';
         end if;
      else
      end if;
   end process;
end generate outputRising;
end Behavioral;
