library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity debouncer is
	port (  --INPUTS
	        button                                               : in STD_LOGIC;
			clk                                                  : in STD_LOGIC;
			--OUTPUTS
			continuous_output                                    : out STD_LOGIC;
			pulse_output                                         : out STD_LOGIC);
end debouncer;

architecture Behavioral of debouncer is
type STATE is (S0, S1, S2, S3, S4, S5);
signal SOUCASNY_STAV, DALSI_STAV                                : STATE;

signal divider_pulse                                            : STD_LOGIC;

 component clk_divider
    generic (MAX : positive); 
	Port(   --INPUTS
	        clk                                                 : in STD_LOGIC;
	        divider_clock_multiplier                            : in STD_LOGIC_VECTOR(7 downto 0);
	        --OUTPUTS
            divider_clock_output                                : out STD_LOGIC; 
            divider_pulse_output                                : out STD_LOGIC);
	end component;

begin

        buttons_speed : clk_divider  --sets how fast when pressing button values change
        GENERIC MAP (max => 1000000) --100Hz
        PORT MAP( clk                                           => clk,
                  divider_clock_multiplier                      => "00000001",
                  divider_clock_output                          => open,
                  divider_pulse_output                          => divider_pulse);

PROCESS (clk)
BEGIN
	IF (clk'event and clk = '1')THEN
	     SOUCASNY_STAV <= DALSI_STAV;
          END IF;
 	END PROCESS;

PROCESS( SOUCASNY_STAV, divider_pulse, button)
BEGIN 
		CASE SOUCASNY_STAV IS
		WHEN S0 =>
		     continuous_output <= '0';
			 pulse_output <= '0';
	  	     if (button = '1' and divider_pulse = '1') then
 			    DALSI_STAV <= S1;
		     else
 			    DALSI_STAV <= S0;
		     end if;
			  
		WHEN S1 =>
		     continuous_output <= '0';
	         pulse_output <= '0';
	  	     if (button = '1' and divider_pulse = '1') then
 			    DALSI_STAV <= S2;
		     elsif (button = '0' and divider_pulse = '1') then
 			    DALSI_STAV <= S0;
			 else
			    DALSI_STAV <= S1;                                --stay in loop 
		     end if;
			  
		WHEN S2 =>
		     continuous_output <= '0';
			 pulse_output <= '0';
	  	     if (button = '1' and divider_pulse = '1') then
 			    DALSI_STAV <= S3;
		     elsif (button = '0' and divider_pulse = '1') then
 			    DALSI_STAV <= S0;
			 else
			     DALSI_STAV <= S2;                               --stay in loop
		     end if; 
			  
		WHEN S3 =>
		     continuous_output <= '0';
			 pulse_output <= '0';
	  	     if (button = '1' and divider_pulse = '1') then
 			    DALSI_STAV <= S4;
		     elsif (button = '0' and divider_pulse = '1') then
 			    DALSI_STAV <= S0;
		     else
			    DALSI_STAV <= S3;                               --stay in loop  
		     end if;
		    
		--state that activates continuous_output and makes a pulse on output_pulse	 	  
		WHEN S4 =>
		     continuous_output <= '1';
			 pulse_output <= '1';
	  	     if (button = '0') then
 			    DALSI_STAV <= S0;
		     else
 			    DALSI_STAV <= S5;
		     end if;
			  
		WHEN S5 =>
		     continuous_output <= '1';
			 pulse_output <= '0';
	  	     if (button = '0' and divider_pulse = '1') then
 			    DALSI_STAV <= S0;
		     else
 			    DALSI_STAV <= S5;
		     end if;	  
	   end case;
END PROCESS;
 
 
end Behavioral;

