----------------------------------------------------------------------------------------------------------------------- -- Author: Jonny Doin, jdoin@opencores.org, jonnydoin@gmail.com -- -- Create Date: 09:56:30 07/06/2011 -- Module Name: grp_debouncer - RTL -- Project Name: basic functions -- Target Devices: Spartan-6 -- Tool versions: ISE 13.1 -- Description: -- -- This block is a generic multiple input debouncing circuit. -- It handles multiple inputs, like mechanical switch inputs, and outputs a debounced, stable registered version of the inputs. -- A 'new_data' one-cycle strobe is also available, to sync downstream logic. -- -- CONCEPTUAL CIRCUIT -- ================== -- -- W -- /----------------/----------------\ -- | | -- | | -- | ______ ______ | _____ -- | W | | W |fdr | W | W |cmp \ -- \----/---| +1 |---/----| |--/--+----/----| \ -- | | | | | \ -- ------ | | \ | -- | | | = |-----\ -- |> R | / | | -- ---+-- | / | -- | CNT_VAL---| / | -- | |____/ | -- | | -- \------------\ | -- | | -- N ____ | | -- /-------/---)) \ ____ | | -- | ))XOR |-----) \ | | -- | /------))___/ )OR |-----/ | -- | | /---)___/ | -- | | | | -- | | \----------\ | -- | | N | | -- | \--------/-----------\ +----------------------+---------\ -- | | | | -- \---\ | | | -- ______ | ______ | | ______ | -- | fd | | | fd | | | |fde | | -- [data_i]----/-----| |---/---+---/----| |---/---+----)---| |---/---+---/-----------)------------------------[data_o] -- N | | N N | | N | | | | N | N | -- | | | | | \---|CE | | | -- | | | | | | | | | -- [clk_i]----> |> | |> | | |> | | | ____ ______ -- ------ ------ | ------ | N ____ \---| \ | fd | -- | \---/---)) \ |AND |-----| |----[strb_o] -- | ))XOR |-----|___/ | | -- \-------------------------/---))___/ | | -- N | | -- |> | -- ------ -- -- -- PIPELINE LOGIC -- ============== -- -- This debouncer circuit detects edges in an input signal, and waits the signal to stabilize for the designated time -- before transferring the stable signal to the registered output. -- A one-clock-cyle strobe is pulsed at the output to signalize a new data available. -- The core clock should be the system clock, to optimize use of global clock resources. -- -- GROUP DEBOUNCING -- ================ -- -- A change in state in any bit in the input word causes reload of the delay counter, and the output word is updated only -- when all bits are stable for the specified period. Therefore, the grouping of signals and delay selection should match -- behaviour of the selected signals. -- -- RESOURCES USED -- ============== -- -- The number of registers inferred is: 3*N + (LOG(CNT_VAL)/LOG(2)) + 1 registers. -- The number of LUTs inferred is roughly: ((4*N+2)/6)+2. -- The slice distribution will vary, and depends on the control set restrictions and LUT-FF pairs resulting from map+p&r. -- -- This design was originally targeted to a Spartan-6 platform, synthesized with XST and normal constraints. -- Verification in silicon was done on a Digilent Atlys board with a Spartan-6 FPGA @100MHz clock. -- The VHDL dialect used is VHDL'93, accepted largely by all synthesis tools. -- ------------------------------ COPYRIGHT NOTICE ----------------------------------------------------------------------- -- -- -- Author(s): Jonny Doin, jdoin@opencores.org, jonnydoin@gmail.com -- -- Copyright (C) 2011 Jonny Doin -- ----------------------------- -- -- This source file may be used and distributed without restriction provided that this copyright statement is not -- removed from the file and that any derivative work contains the original copyright notice and the associated -- disclaimer. -- -- This source file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser -- General Public License as published by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -- details. -- -- You should have received a copy of the GNU Lesser General Public License along with this source; if not, download -- it from http://www.gnu.org/licenses/lgpl.txt -- ------------------------------ REVISION HISTORY ----------------------------------------------------------------------- -- -- 2011/07/06 v0.01.0010 [JD] started development. verification of synthesis circuit inference. -- 2011/07/07 v1.00.0020 [JD] verification in silicon. operation at 100MHz, tested on the Atlys board (Spartan-6 LX45). -- 2011/08/10 v1.01.0025 [JD] added one pipeline delay to new data strobe output. -- 2011/09/19 v1.01.0030 [JD] changed range for internal counter (cnt_reg, cnt_next) to avoid adder flipover (Altera/ModelSim). -- ----------------------------------------------------------------------------------------------------------------------- -- TODO -- ==== -- -- The circuit can easily be extended to have a signature of which inputs changed at the data out port. -- ----------------------------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; entity grp_debouncer is Generic ( N : positive := 8; -- input bus width CNT_VAL : positive := 10000); -- clock counts for debounce period Port ( clk_i : in std_logic := 'X'; -- system clock data_i : in std_logic_vector (N-1 downto 0) := (others => 'X'); -- noisy input data data_o : out std_logic_vector (N-1 downto 0); -- registered stable output data strb_o : out std_logic -- strobe for new data available ); end grp_debouncer; architecture rtl of grp_debouncer is -- datapath pipeline signal reg_A, reg_B : std_logic_vector (N-1 downto 0) := (others => '0'); -- debounce edge detectors signal reg_out : std_logic_vector (N-1 downto 0) := (others => '0'); -- registered output signal dat_strb : std_logic := '0'; -- data transfer strobe signal strb_reg : std_logic := '0'; -- registered strobe signal strb_next : std_logic := '0'; -- lookahead strobe signal dat_diff : std_logic := '0'; -- edge detector -- debounce counter signal cnt_reg : integer range CNT_VAL + 1 downto 0 := 0; -- debounce period counter signal cnt_next : integer range CNT_VAL + 1 downto 0 := 0; -- combinatorial signal begin --============================================================================================= -- DEBOUNCE COUNTER LOGIC --============================================================================================= -- This counter is implemented as a up-counter with reset and final count detection via compare, -- instead of a down-counter with preset and final count detection via nonzero detection. -- This is better for Spartan-6 and Virtex-6 CLB architecture, because it uses less control sets. -- -- cnt_reg register transfer logic cnt_reg_proc: process (clk_i) is begin if clk_i'event and clk_i = '1' then cnt_reg <= cnt_next; end if; end process cnt_reg_proc; -- cnt_next combinatorial logic cnt_next_proc: cnt_next <= 0 when dat_diff = '1' or dat_strb = '1' else cnt_reg + 1; -- final count combinatorial logic final_cnt_proc: dat_strb <= '1' when cnt_reg = CNT_VAL else '0'; --============================================================================================= -- DATAPATH SIGNAL PIPELINE --============================================================================================= -- input pipeline logic pipeline_proc: process (clk_i) is begin if clk_i'event and clk_i = '1' then -- edge detection pipeline reg_A <= data_i; reg_B <= reg_A; -- new data strobe pipeline delay strb_reg <= strb_next; end if; -- output data pipeline if clk_i'event and clk_i = '1' then if dat_strb = '1' then reg_out <= reg_B; end if; end if; end process pipeline_proc; -- edge detector edge_detector_proc: dat_diff <= '1' when reg_A /= reg_B else '0'; -- lookahead new data strobe next_strobe_proc: strb_next <= '1' when ((reg_out /= reg_B) and dat_strb = '1') else '0'; --============================================================================================= -- OUTPUT LOGIC --============================================================================================= -- connect output ports data_o_proc: data_o <= reg_out; strb_o_proc: strb_o <= strb_reg; end rtl;