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!
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
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
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:vhdlexamples_debounce http://eewiki.net/pages/viewpage.action?pageId=4980758
132 wrote: > Take google.com, type vhdl debounce and find about 9000 hits. Lets take the first one:
1 | process (CLK, x) |
2 | variable SDC : integer; |
3 | constant Delay : integer := 50000; |
4 | begin
|
5 | if CLK'Event and CLK = '1' then |
6 | ...
|
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:
1 | :
|
2 | SDC := Delay; |
3 | |
4 | State <= S1; |
5 | when S1 => |
6 | SDC := SDC - 1; |
7 | |
8 | if SDC = 0 then |
9 | State <= S0; |
10 | :
|
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:
1 | LIBRARY ieee; |
2 | USE ieee.std_logic_1164.all; |
3 | USE ieee.numeric_std.all; |
4 | |
5 | ENTITY debounce IS |
6 | PORT( clk : IN STD_LOGIC; --input clock |
7 | button : IN STD_LOGIC; --input signal to be debounced |
8 | result : OUT STD_LOGIC); --debounced signal |
9 | END debounce; |
10 | |
11 | ARCHITECTURE behave OF debounce IS |
12 | SIGNAL inff : STD_LOGIC_VECTOR(1 DOWNTO 0); -- input flip flops |
13 | CONSTANT cnt_max : INTEGER := (33000000/50)-1 : -- 33MHz and 1/20ms=50Hz |
14 | SIGNAL count : INTEGER range 0 to cnt_max := 0; |
15 | BEGIN
|
16 | PROCESS(clk) |
17 | BEGIN
|
18 | IF(clk'EVENT and clk = '1') THEN |
19 | inff <= inff(0) & button; -- sync in the input |
20 | IF(inff(0)/=inff(1)) THEN -- reset counter because input is changing |
21 | count <= 0; |
22 | ELSIF(count<cnt_max) THEN -- stable input time is not yet met |
23 | count <= count + 1; |
24 | ELSE -- stable input time is met |
25 | result <= inff(1); |
26 | END IF; |
27 | END IF; |
28 | END PROCESS; |
29 | END behave; |
> Thanks!
Youre welcome!
:
Edited by Moderator
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
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...
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!
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
Would have been nice if this solution actually worked. Spent all day on it till I finally figured out the race condition. Whew!
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
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.
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
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.
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.
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-Machine-mit-asynchronem-Eingang.html
:
Edited by Moderator
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
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.
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.