| 1 |
5 |
jdoin |
-----------------------------------------------------------------------------------------------------------------------
|
| 2 |
12 |
jdoin |
-- Author: Jonny Doin, jdoin@opencores.org, jonnydoin@gmail.com
|
| 3 |
5 |
jdoin |
--
|
| 4 |
|
|
-- Create Date: 09:56:30 07/06/2011
|
| 5 |
|
|
-- Module Name: grp_debouncer - RTL
|
| 6 |
10 |
jdoin |
-- Project Name: basic functions
|
| 7 |
5 |
jdoin |
-- Target Devices: Spartan-6
|
| 8 |
|
|
-- Tool versions: ISE 13.1
|
| 9 |
|
|
-- Description:
|
| 10 |
|
|
--
|
| 11 |
|
|
-- This block is a generic multiple input debouncing circuit.
|
| 12 |
|
|
-- It handles multiple inputs, like mechanical switch inputs, and outputs a debounced, stable registered version of the inputs.
|
| 13 |
|
|
-- A 'new_data' one-cycle strobe is also available, to sync downstream logic.
|
| 14 |
|
|
--
|
| 15 |
|
|
-- CONCEPTUAL CIRCUIT
|
| 16 |
|
|
-- ==================
|
| 17 |
7 |
jdoin |
--
|
| 18 |
|
|
-- W
|
| 19 |
|
|
-- /----------------/----------------\
|
| 20 |
|
|
-- | |
|
| 21 |
|
|
-- | |
|
| 22 |
|
|
-- | ______ ______ | _____
|
| 23 |
|
|
-- | W | | W |fdr | W | W |cmp \
|
| 24 |
|
|
-- \----/---| +1 |---/----| |--/--+----/----| \
|
| 25 |
|
|
-- | | | | | \
|
| 26 |
|
|
-- ------ | | \ |
|
| 27 |
|
|
-- | | | = |-----\
|
| 28 |
|
|
-- |> R | / | |
|
| 29 |
|
|
-- ---+-- | / |
|
| 30 |
|
|
-- | CNT_VAL---| / |
|
| 31 |
|
|
-- | |____/ |
|
| 32 |
|
|
-- | |
|
| 33 |
|
|
-- \------------\ |
|
| 34 |
|
|
-- | |
|
| 35 |
|
|
-- N ____ | |
|
| 36 |
|
|
-- /-------/---)) \ ____ | |
|
| 37 |
|
|
-- | ))XOR |-----) \ | |
|
| 38 |
|
|
-- | /------))___/ )OR |-----/ |
|
| 39 |
|
|
-- | | /---)___/ |
|
| 40 |
|
|
-- | | | |
|
| 41 |
|
|
-- | | \----------\ |
|
| 42 |
|
|
-- | | N | |
|
| 43 |
23 |
jdoin |
-- | \--------/-----------\ +----------------------+---------\
|
| 44 |
|
|
-- | | | |
|
| 45 |
|
|
-- \---\ | | |
|
| 46 |
|
|
-- ______ | ______ | | ______ |
|
| 47 |
|
|
-- | fd | | | fd | | | |fde | |
|
| 48 |
|
|
-- [data_i]----/-----| |---/---+---/----| |---/---+----)---| |---/---+---/-----------)------------------------[data_o]
|
| 49 |
|
|
-- N | | N N | | N | | | | N | N |
|
| 50 |
|
|
-- | | | | | \---|CE | | |
|
| 51 |
|
|
-- | | | | | | | | |
|
| 52 |
|
|
-- [clk_i]----> |> | |> | | |> | | | ____ ______
|
| 53 |
|
|
-- ------ ------ | ------ | N ____ \---| \ | fd |
|
| 54 |
|
|
-- | \---/---)) \ |AND |-----| |----[strb_o]
|
| 55 |
|
|
-- | ))XOR |-----|___/ | |
|
| 56 |
|
|
-- \-------------------------/---))___/ | |
|
| 57 |
|
|
-- N | |
|
| 58 |
|
|
-- |> |
|
| 59 |
|
|
-- ------
|
| 60 |
7 |
jdoin |
--
|
| 61 |
|
|
--
|
| 62 |
5 |
jdoin |
-- PIPELINE LOGIC
|
| 63 |
|
|
-- ==============
|
| 64 |
|
|
--
|
| 65 |
|
|
-- This debouncer circuit detects edges in an input signal, and waits the signal to stabilize for the designated time
|
| 66 |
|
|
-- before transferring the stable signal to the registered output.
|
| 67 |
|
|
-- A one-clock-cyle strobe is pulsed at the output to signalize a new data available.
|
| 68 |
|
|
-- The core clock should be the system clock, to optimize use of global clock resources.
|
| 69 |
|
|
--
|
| 70 |
|
|
-- GROUP DEBOUNCING
|
| 71 |
|
|
-- ================
|
| 72 |
|
|
--
|
| 73 |
|
|
-- A change in state in any bit in the input word causes reload of the delay counter, and the output word is updated only
|
| 74 |
|
|
-- when all bits are stable for the specified period. Therefore, the grouping of signals and delay selection should match
|
| 75 |
|
|
-- behaviour of the selected signals.
|
| 76 |
|
|
--
|
| 77 |
|
|
-- RESOURCES USED
|
| 78 |
|
|
-- ==============
|
| 79 |
|
|
--
|
| 80 |
23 |
jdoin |
-- The number of registers inferred is: 3*N + (LOG(CNT_VAL)/LOG(2)) + 1 registers.
|
| 81 |
5 |
jdoin |
-- The number of LUTs inferred is roughly: ((4*N+2)/6)+2.
|
| 82 |
|
|
-- The slice distribution will vary, and depends on the control set restrictions and LUT-FF pairs resulting from map+p&r.
|
| 83 |
|
|
--
|
| 84 |
|
|
-- This design was originally targeted to a Spartan-6 platform, synthesized with XST and normal constraints.
|
| 85 |
23 |
jdoin |
-- Verification in silicon was done on a Digilent Atlys board with a Spartan-6 FPGA @100MHz clock.
|
| 86 |
5 |
jdoin |
-- The VHDL dialect used is VHDL'93, accepted largely by all synthesis tools.
|
| 87 |
|
|
--
|
| 88 |
|
|
------------------------------ COPYRIGHT NOTICE -----------------------------------------------------------------------
|
| 89 |
|
|
--
|
| 90 |
10 |
jdoin |
--
|
| 91 |
12 |
jdoin |
-- Author(s): Jonny Doin, jdoin@opencores.org, jonnydoin@gmail.com
|
| 92 |
10 |
jdoin |
--
|
| 93 |
23 |
jdoin |
-- Copyright (C) 2011 Jonny Doin
|
| 94 |
|
|
-- -----------------------------
|
| 95 |
10 |
jdoin |
--
|
| 96 |
|
|
-- This source file may be used and distributed without restriction provided that this copyright statement is not
|
| 97 |
5 |
jdoin |
-- removed from the file and that any derivative work contains the original copyright notice and the associated
|
| 98 |
10 |
jdoin |
-- disclaimer.
|
| 99 |
|
|
--
|
| 100 |
5 |
jdoin |
-- This source file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
|
| 101 |
|
|
-- General Public License as published by the Free Software Foundation; either version 2.1 of the License, or
|
| 102 |
10 |
jdoin |
-- (at your option) any later version.
|
| 103 |
|
|
--
|
| 104 |
|
|
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
| 105 |
|
|
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
| 106 |
|
|
-- details.
|
| 107 |
|
|
--
|
| 108 |
5 |
jdoin |
-- You should have received a copy of the GNU Lesser General Public License along with this source; if not, download
|
| 109 |
23 |
jdoin |
-- it from http://www.gnu.org/licenses/lgpl.txt
|
| 110 |
5 |
jdoin |
--
|
| 111 |
|
|
------------------------------ REVISION HISTORY -----------------------------------------------------------------------
|
| 112 |
|
|
--
|
| 113 |
|
|
-- 2011/07/06 v0.01.0010 [JD] started development. verification of synthesis circuit inference.
|
| 114 |
|
|
-- 2011/07/07 v1.00.0020 [JD] verification in silicon. operation at 100MHz, tested on the Atlys board (Spartan-6 LX45).
|
| 115 |
23 |
jdoin |
-- 2011/08/10 v1.01.0025 [JD] added one pipeline delay to new data strobe output.
|
| 116 |
24 |
jdoin |
-- 2011/09/19 v1.01.0030 [JD] changed range for internal counter (cnt_reg, cnt_next) to avoid adder flipover (Altera/ModelSim).
|
| 117 |
5 |
jdoin |
--
|
| 118 |
|
|
-----------------------------------------------------------------------------------------------------------------------
|
| 119 |
|
|
-- TODO
|
| 120 |
|
|
-- ====
|
| 121 |
|
|
--
|
| 122 |
12 |
jdoin |
-- The circuit can easily be extended to have a signature of which inputs changed at the data out port.
|
| 123 |
5 |
jdoin |
--
|
| 124 |
|
|
-----------------------------------------------------------------------------------------------------------------------
|
| 125 |
|
|
library ieee;
|
| 126 |
|
|
use ieee.std_logic_1164.all;
|
| 127 |
|
|
|
| 128 |
|
|
entity grp_debouncer is
|
| 129 |
|
|
Generic (
|
| 130 |
|
|
N : positive := 8; -- input bus width
|
| 131 |
|
|
CNT_VAL : positive := 10000); -- clock counts for debounce period
|
| 132 |
|
|
Port (
|
| 133 |
|
|
clk_i : in std_logic := 'X'; -- system clock
|
| 134 |
|
|
data_i : in std_logic_vector (N-1 downto 0) := (others => 'X'); -- noisy input data
|
| 135 |
|
|
data_o : out std_logic_vector (N-1 downto 0); -- registered stable output data
|
| 136 |
|
|
strb_o : out std_logic -- strobe for new data available
|
| 137 |
|
|
);
|
| 138 |
|
|
end grp_debouncer;
|
| 139 |
|
|
|
| 140 |
|
|
architecture rtl of grp_debouncer is
|
| 141 |
|
|
-- datapath pipeline
|
| 142 |
|
|
signal reg_A, reg_B : std_logic_vector (N-1 downto 0) := (others => '0'); -- debounce edge detectors
|
| 143 |
|
|
signal reg_out : std_logic_vector (N-1 downto 0) := (others => '0'); -- registered output
|
| 144 |
|
|
signal dat_strb : std_logic := '0'; -- data transfer strobe
|
| 145 |
23 |
jdoin |
signal strb_reg : std_logic := '0'; -- registered strobe
|
| 146 |
|
|
signal strb_next : std_logic := '0'; -- lookahead strobe
|
| 147 |
5 |
jdoin |
signal dat_diff : std_logic := '0'; -- edge detector
|
| 148 |
|
|
-- debounce counter
|
| 149 |
24 |
jdoin |
signal cnt_reg : integer range CNT_VAL + 1 downto 0 := 0; -- debounce period counter
|
| 150 |
|
|
signal cnt_next : integer range CNT_VAL + 1 downto 0 := 0; -- combinatorial signal
|
| 151 |
5 |
jdoin |
begin
|
| 152 |
|
|
|
| 153 |
|
|
--=============================================================================================
|
| 154 |
|
|
-- DEBOUNCE COUNTER LOGIC
|
| 155 |
|
|
--=============================================================================================
|
| 156 |
|
|
-- This counter is implemented as a up-counter with reset and final count detection via compare,
|
| 157 |
|
|
-- instead of a down-counter with preset and final count detection via nonzero detection.
|
| 158 |
|
|
-- This is better for Spartan-6 and Virtex-6 CLB architecture, because it uses less control sets.
|
| 159 |
|
|
--
|
| 160 |
|
|
-- cnt_reg register transfer logic
|
| 161 |
|
|
cnt_reg_proc: process (clk_i) is
|
| 162 |
|
|
begin
|
| 163 |
|
|
if clk_i'event and clk_i = '1' then
|
| 164 |
|
|
cnt_reg <= cnt_next;
|
| 165 |
|
|
end if;
|
| 166 |
|
|
end process cnt_reg_proc;
|
| 167 |
|
|
-- cnt_next combinatorial logic
|
| 168 |
|
|
cnt_next_proc: cnt_next <= 0 when dat_diff = '1' or dat_strb = '1' else cnt_reg + 1;
|
| 169 |
|
|
-- final count combinatorial logic
|
| 170 |
|
|
final_cnt_proc: dat_strb <= '1' when cnt_reg = CNT_VAL else '0';
|
| 171 |
|
|
|
| 172 |
|
|
--=============================================================================================
|
| 173 |
|
|
-- DATAPATH SIGNAL PIPELINE
|
| 174 |
|
|
--=============================================================================================
|
| 175 |
|
|
-- input pipeline logic
|
| 176 |
|
|
pipeline_proc: process (clk_i) is
|
| 177 |
|
|
begin
|
| 178 |
|
|
if clk_i'event and clk_i = '1' then
|
| 179 |
23 |
jdoin |
-- edge detection pipeline
|
| 180 |
5 |
jdoin |
reg_A <= data_i;
|
| 181 |
|
|
reg_B <= reg_A;
|
| 182 |
23 |
jdoin |
-- new data strobe pipeline delay
|
| 183 |
|
|
strb_reg <= strb_next;
|
| 184 |
5 |
jdoin |
end if;
|
| 185 |
23 |
jdoin |
-- output data pipeline
|
| 186 |
5 |
jdoin |
if clk_i'event and clk_i = '1' then
|
| 187 |
|
|
if dat_strb = '1' then
|
| 188 |
|
|
reg_out <= reg_B;
|
| 189 |
|
|
end if;
|
| 190 |
|
|
end if;
|
| 191 |
|
|
end process pipeline_proc;
|
| 192 |
|
|
-- edge detector
|
| 193 |
|
|
edge_detector_proc: dat_diff <= '1' when reg_A /= reg_B else '0';
|
| 194 |
23 |
jdoin |
-- lookahead new data strobe
|
| 195 |
|
|
next_strobe_proc: strb_next <= '1' when ((reg_out /= reg_B) and dat_strb = '1') else '0';
|
| 196 |
5 |
jdoin |
|
| 197 |
|
|
--=============================================================================================
|
| 198 |
|
|
-- OUTPUT LOGIC
|
| 199 |
|
|
--=============================================================================================
|
| 200 |
|
|
-- connect output ports
|
| 201 |
|
|
data_o_proc: data_o <= reg_out;
|
| 202 |
23 |
jdoin |
strb_o_proc: strb_o <= strb_reg;
|
| 203 |
5 |
jdoin |
end rtl;
|
| 204 |
|
|
|