EmbDev.net

Forum: FPGA, VHDL & Verilog VHDL Button Debouncing


Author: Matt (Guest)
Posted on:

Rate this post
0 useful
not useful
Hello all,

I am currently writing a program to debounce a push button input. The 
circuit(vhdl code) should debounce the buttons input after 20ms. The 
problem I am facing, is the clock that i have to use is operating at 
5MHZ which will debounce the button in a matter of microseconds if using 
the tradition flip-flop debouncing technique. How can I obtain a clean 
output after the button has been pushed for 20ms? Thanks!

Author: flip flopper (Guest)
Posted on:

Rate this post
0 useful
not useful
you will have to use a counter to create the 20ms tick and use it as an 
enable for the sampling FF.

the counter will be set to start with the very first button move

Author: Matt (Guest)
Posted on:

Rate this post
0 useful
not useful
This sounds like a good method, however, I do not implement this in 
vhdl. Do you have time to give me a quick example, or method in psuedo 
code? Thanks

Author: 132 (Guest)
Posted on:

Rate this post
0 useful
not useful
Matt wrote:
> This sounds like a good method, however, I do not implement this in
> vhdl.

Why do you the ask for VHDL code?

> Do you have time to give me a quick example, or method in psuedo
> code? Thanks

Take google.com, type vhdl debounce and find about 9000 hits.

http://www.deathbylogic.com/2011/03/vhdl-debounce/
http://zawiki.praxis-arbor.ch/doku.php/tschinz:vhd...
http://eewiki.net/pages/viewpage.action?pageId=4980758

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
1 useful
not useful
132 wrote:
> Take google.com, type vhdl debounce and find about 9000 hits.
Lets take the first one:
  process (CLK, x)
    variable SDC : integer;
    constant Delay : integer := 50000;
  begin
    if CLK'Event and CLK = '1' then 
      ...
This looks like beginner style because x is not necessary in the 
sensitivity list and is not a really good style to use variables in such 
an extensive manner.
Additionally it is not good to load a couter with a given value and 
count it down to 0 afterwards:
    :
          SDC := Delay;
 
          State <= S1;
        when S1 =>
          SDC := SDC - 1;
 
          if SDC = 0 then
            State <= S0;
    :
This probably needs more ressources, because the reset inputs of a 
flipflop inside the FPGA cannot be used for loading the counter. The 
better way is to reset a counter and compare it with the uppermost 
value.

The third link is the best code, but it uses the old obsolete 
std_logic_unsigned lib. And to size the counter is far to difficult. Of 
course it is/seems very efficient to size the counter a way that the 
overflow of it can be used to trigger the sampling event, but in real 
life it is much easier and straight away just to spend a little bit 
logic and let the synthesizer do the timing calculations...

Matt wrote:
> How can I obtain a clean output after the button has been pushed for
> 20ms? Thanks!
Implement a counter counting up to 20ms.
Reset this counter whenever you detect a change in the input signal.
Sample the input the counter reaches 20ms.
Done.

Now lets take the code from the last link and transform it to a kind of 
"up-to-date" style using the fancy new numeric_std lib instead of the 
old synopsis libs:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

ENTITY debounce IS
  PORT( clk     : IN  STD_LOGIC;  --input clock
        button  : IN  STD_LOGIC;  --input signal to be debounced
        result  : OUT STD_LOGIC); --debounced signal
END debounce;

ARCHITECTURE behave OF debounce IS
  SIGNAL   inff    : STD_LOGIC_VECTOR(1 DOWNTO 0); -- input flip flops
  CONSTANT cnt_max : INTEGER := (33000000/50)-1 :  -- 33MHz and 1/20ms=50Hz
  SIGNAL   count   : INTEGER range 0 to cnt_max := 0; 
BEGIN
  PROCESS(clk)
  BEGIN
    IF(clk'EVENT and clk = '1') THEN
      inff <= inff(0) & button;  -- sync in the input
      IF(inff(0)/=inff(1)) THEN  -- reset counter because input is changing
        count <= 0;
      ELSIF(count<cnt_max) THEN  -- stable input time is not yet met
        count <= count + 1;
      ELSE                       -- stable input time is met
        result <= inff(1);
      END IF;    
    END IF;
  END PROCESS;
END behave;

> Thanks!
Youre welcome!

: Edited by Moderator
Author: Matt (Guest)
Posted on:

Rate this post
0 useful
not useful
I looked over this code and it looks good. I tryed to run it and got a 
few errors I cannot seem to get rid of. The error in question is on the 
2nd if statement. Could you please check this out for me if you have 
time? Thanks

Author: guest (Guest)
Posted on:

Rate this post
0 useful
not useful
try /= instead of !=

But that was probably a test from Lothar ;)

Also note to write the exact error message next time, it was a easy one 
here though...

Author: Matt Smith (mauromj)
Posted on:

Rate this post
0 useful
not useful
I did not even notice that! I have been so used to C and assembly I have 
lost most of my vhdl know how. I appreciate the help guys!

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
guest wrote:
> try /= instead of !=
Thx, I changed the code according to your hint. Just as a try to excuse 
that excessive bug: I'm doing a little bit C at the moment...

> But that was probably a test from Lothar ;)
For sure it was! ;-)

: Edited by Moderator
Author: hoffbegone (Guest)
Posted on:

Rate this post
0 useful
not useful
Would have been nice if this solution actually worked. Spent all day on 
it till I finally figured out the race condition. Whew!

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
hoffbegone wrote:
> Spent all day on it till I finally figured out the race condition.
Glad to hear that you solved a problem. And now you simply keep your 
little secret? You copy something from somewhere, but if there's a 
problem and YOU solved it, then you keep it for yourself? Whow! Thumbs 
up!

I can't see no "traditional" race condition up to now...
What particular problem did you have in what case?
And how did you solve it?

: Edited by Moderator
Author: Zuschauer (Guest)
Posted on:

Rate this post
0 useful
not useful
I'm curious as well. Sounds like an unconstrained design.

Author: hoffbegone (Guest)
Posted on:

Rate this post
0 useful
not useful
Sorry for my erroneous post. My evaluation demonstrated a race condition 
but then I found I made a coding error.

In addition, there is one syntax mistake:

ELSIF(cnt<cnt_max) THEN    -- stable input time is not yet met

should be

ELSIF(count<cnt_max) THEN    -- stable input time is not yet met

I demonstrated this routine worked as promised and verified it to my 
satisfaction. Even my boss says this is a more "elegant" solution than 
what he has used in the past.

BTW, I am a beginner and not an expert. Don't know what "unconstrained 
design" means.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
hoffbegone wrote:
> In addition, there is one syntax mistake:
> ELSIF(cnt<cnt_max) THEN    -- stable input time is not yet met
> should be
> ELSIF(count<cnt_max) THEN    -- stable input time is not yet met
Thx for the response. I'll correct that.

> Don't know what "unconstrained design" means.
When you assign a output or input pin, thats a constraint. When you tell 
the toochain to achieve at least 50MHz clock frequency (because your 
crystal oscillator has that frequency) thats a constraint also.

> My evaluation demonstrated a race condition but then I found I made a
> coding error
Lets try a few guesses: usually thats due to a unsych'ed input signal. 
Or it was a async reset generated out of combinatoric logic. Or it was a 
simple combinatorial loop.
With those 3 guesses I will get the actual problem in 99% of the cases.

: Edited by Moderator
Author: hoffbegone (Guest)
Posted on:

Rate this post
0 useful
not useful
Just noticed the two posters after my initial post. I was very 
frustrated and did not feel up to elaborating on my solution. Sorry.

But am glad I came back to correct my initial post.

I also neglected to say THANK YOU for this article. I learned a lot, 
especially from my mistakes.

Author: hoffbegone (Guest)
Posted on:

Rate this post
0 useful
not useful
Oh, Lothar wants to know what mistake I made.

OK, here it goes. As I copied the code I made changes to the variables 
to fit my design. When I came to:

result <= inff(1);

I thought, wait! inff(1) is the same as button and I typed in button 
instead.

Code seemed to work until I increased the 20ms delay to 2 seconds so I 
could actually see the delay (I was using a visible LED rather than a 
scope). What I saw was the button was detected immediately on one edge 
but then ignored, because of the delay, on the other edge. I was 
expecting to see a delay on both edges. Must be a "race" condition. I 
then modified the code and came up with my own similar solution.

It was my boss trying to understand your code when he said something 
under his breath that caused me to realize the mistake I made.

I hope this explanation was entertaining.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
hoffbegone wrote:
> I thought, wait! inff(1) is the same as button and I typed in button
> instead.
An async input into a FSM. The first of my guesses...;-)

> I thought, wait! inff(1) is the same as button and I typed in button
> instead.
Indeed (you know it now) there are 2 flipflops between them.

Try that with Google translator, that is what you get with no sync 
stages: 
http://www.lothar-miller.de/s9y/archives/64-State-...

: Edited by Moderator
Author: Farnaz Amini (Company: student) (fa77)
Posted on:

Rate this post
0 useful
not useful
Hi

I tried to use this code for debouncer but I have soe problem with this 
line:

inff <= inff(0) & button;  -- sync in the input

is it true?

could you please explain me

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Thats no "debouncer" its simply a synching stage to bring the async 
input to the FPGA clock domain.

What you have posted is just a concatenation (that's the & operator). If 
you add a clock to this, then it will become a shift register.

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.