---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 16:04:58 09/24/2009 -- Design Name: -- Module Name: DEBOUNCE - beh -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.all; -- clk and reset needed for DEBOUNCE. button is the input to debounce and button_stable -- is the stable output version of it. entity DEBOUNCE is Port ( clk : in std_logic; reset : in std_logic; button : in std_logic; button_level : out std_logic; button_stable : out std_logic ); end DEBOUNCE; ---------------------------------------------------------------------------------- architecture beh of DEBOUNCE is -- 2^N*10ns = 40ms -- FOR SIMULATIONS, USE 2 here, otherwise use 22 constant N: integer:= 2; -- constant N: integer:= 22; type state_type is (zero, wait0, one, wait1); signal state_reg, state_next: state_type; signal q_reg, q_next: unsigned(N-1 downto 0); signal q_load, q_dec, q_zero: std_logic; begin -- debouncing FSM process (clk, reset) begin if (reset = '1') then state_reg <= zero; q_reg <= (others => '0'); elsif (clk'event and clk='1') then state_reg <= state_next; q_reg <= q_next; end if; end process; -- FSMD data path (counter) next-state logic. Load the count down register with all '1's -- on the request of a load. Or decrement if counting down, else maintain value q_next <= (others => '1') when (q_load = '1') else q_reg - 1 when (q_dec = '1') else q_reg; -- Pulse q_zero when count-down reaches 0. q_zero <= '1' when (q_next = 0) else '0'; -- FSMD control path next-state logic process (state_reg, button, q_zero) begin -- defaults q_load <= '0'; q_dec <= '0'; button_stable <= '0'; state_next <= state_reg; case state_reg is -- wait for button to be pressed (to become 1). Once this occurs, load up the count -- down register (above) when zero => button_level <= '0'; if (button = '1') then state_next <= wait1; q_load <= '1'; end if; -- Decrement as long as button continues to produce a '1', count down -- if at any instance -- (at 100 MHz) it becomes '0', return to the zero state and start the count down -- over again. We don't get to the 'one' state unless we measure '1' for a 40 ms -- consequective interval. On the last cycle of button becoming '1', set the stable version -- of button (button_stable) to a '1' for ONE clock cycle when wait1 => button_level <= '0'; if (button = '1') then q_dec <= '1'; if (q_zero = '1') then state_next <= one; button_stable <= '1'; end if; else state_next <= zero; end if; -- Repeat but look for 40 ms of consequective '0's. Stay here until we see the -- first '0' when one => button_level <= '1'; if (button = '0') then state_next <= wait0; q_load <= '1'; end if; -- Keep monitoring for '0' and counting down. Any '1's from button cause return -- to state 'one', where we start over again when wait0 => button_level <= '1'; if (button = '0') then q_dec <= '1'; if (q_zero = '1') then state_next <= zero; end if; else state_next <= one; end if; end case; end process; end beh;