VHDL Fpga debouncing

fpgavhdl

I had some troubles with debouncing on one button, so i searched on Google to find a solution for my debouncing problem.

I found this code:

http://eewiki.net/pages/viewpage.action?pageId=4980758#DebounceLogicCircuit(withVHDLexample)-TheoryofOperation

Which seem to do the trick, but i am having a hard time understanding the code, and it works.

Could someone clarify how this code works, and how/where i can modify it so i turn on and off an LED.

i tried to change it a bit here

LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

ENTITY debounce IS
  GENERIC(
    counter_size  :  INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
  PORT(
    clk     : IN  STD_LOGIC;  --input clock
    button  : IN  STD_LOGIC;  --input signal to be debounced
    result  : OUT STD_LOGIC; --debounced signal
     LED        : out std_logic_vector(3 downto 0);
     Segment: out std_logic_vector (7 downto 0); 
     AN: out std_logic
     );
END debounce;

ARCHITECTURE logic OF debounce IS
  SIGNAL flipflops   : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
  SIGNAL counter_set : STD_LOGIC;                    --sync reset to zero
  SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
  signal counter_10:            integer range 0 to 9 := 0;
  signal counter_10r:  std_logic_vector(7 downto 0);
BEGIN

  counter_set <= flipflops(0) xor flipflops(1);   --determine when to start/reset counter
  An <= '1';

  PROCESS(clk)
BEGIN
        IF(clk'EVENT and clk = '1') THEN
            flipflops(0) <= button;
            flipflops(1) <= flipflops(0);
                If(counter_set = '1') THEN --reset counter because input is changing
                    counter_out <= (OTHERS => '0');
                ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
                    counter_out <= counter_out + 1;
            ELSE --stable input time is met
                result <= flipflops(1);
                counter_10 <= counter_10 + 1;
                case counter_10 is 
                    when 0 => counter_10r <= "01000000";
                    when 1 => counter_10r <= "01111001";
                    when 2 => counter_10r <= "00100100";
                    when 3 => counter_10r <= "00110000";
                    when 4 => counter_10r <= "00011001";
                    when 5 => counter_10r <= "00010010";
                    when 6 => counter_10r <= "00000010";
                    when 7 => counter_10r <= "01111000";
                    when 8 => counter_10r <= "00000000";
                    when 9 => counter_10r <= "00010000";
                    when others => counter_10r <= "00000000";
                end case;
                LEd <= conv_std_logic_vector(counter_10,4);
                segment <= counter_10r;

END IF; 
END IF;
END PROCESS;
END logic;

But it does not seem to work, the LED is constantly lid…

Best Answer

Since you didn't identify any specific difficulties, here's a quick run-through. If there are points you still don't understand, ask followup questions in the comments below.

flipflops is used to create an edge detector; counter_set pulses high every time there's an input transition. (Note that this is poor design — since button is an asynchronous input, there should be at least one more flipflop to reduce the chance of metastability.)

Every time counter_set pulses high, counter_out is cleared; otherwise it counts up until the MSB gets set, at which time result is set to the same state as button.

As a demo, the code increments counter_10 on every debounced transition (both low-to-high and high-to-low), which then gets decoded for a 7-segment display. In place of this, you could toggle your LED. If you want the LED to only toggle on one edge and not the other, make it conditional on result.