- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic to the Top
- Bookmark
- Subscribe
- Printer Friendly Page
My debouncer design not working
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-22-2012 07:34 PM
Since I got my bounce counter circuit working with the help or Gabor and Bob (Thanks), I was able to test it and bot did it bounce.. each button press made the count jump to 94, 91, 88..
So I made a debouncing module.. my understanding is that push button stabalizes after 20 ms, so I made a counter that will check the input for 30ms and after this time if input is stable it will activate the output.
Now the problem is it is still bouncing.. not as much though.. in this design each press makes the count go to 41, 32, 49, 54...
here is the debouncing module I made (following a guide, which was also in FSM):
module debouncing(
input clock,
input reset,
input button,
output reg out
);
localparam N = 19; //for a 10ms tick
reg [N-1:0]count;
wire tick;
// the counter that will generate the tick.
always @ (posedge clock or posedge reset)
begin
if(reset)
count <= 0;
else
count <= count + 1;
end
assign tick = &count;
// now for the debouncing FSM
localparam[2:0]
zero = 3'b000,
high1 = 3'b001,
high2 = 3'b010,
high3 = 3'b011,
one = 3'b100,
low1 = 3'b101,
low2 = 3'b110,
low3 = 3'b111;
reg [2:0]state_reg;
reg [2:0]state_next;
always @ (posedge clock or posedge reset) // I think this block is useless if I dont have a reset
begin
if (reset)
state_reg <= zero;
else
state_reg <= state_next;
end
always @ (*)
begin
state_next <= state_reg; // to make the current state the default state
out <= 1'b0; // default output low
case(state_reg)
zero:
if (button)
state_next <= high1;
high1:
if (~button)
state_next <= zero;
else if (tick)
state_next <= high2;
high2:
if (~button)
state_next <= button;
else if (tick)
state_next <= high3;
high3:
if (~button)
state_next <= zero;
else if (tick)
state_next <= one;
one:
begin
out <= 1'b1;
if (~button)
state_next <= low1;
end
low1:
if (button)
state_next <= one;
else if (tick)
state_next <= low2;
low2:
if (button)
state_next <= one;
else if (tick)
state_next <= low3;
low3:
if (button)
state_next <= one;
else if (tick)
state_next <= zero;
default state_next <= zero;
endcase
end
endmodule
and here is the old counter that I posted in my other thread.. The only change is that it looks at the output from the debouncing circuit.
module button_bounce_counter(
input clock,
input reset,
input btn,
output a,
output b,
output c,
output d,
output e,
output f,
output g,
output dp,
output [3:0] an,
output led
);
wire db_btn;
debouncing debouncer(.clock(clock), .reset(reset), .button(btn), .out(db_btn));
reg ledtemp;
reg [3:0] count1;
reg [3:0] count2;
always @ (posedge clock or posedge reset)
begin
if(reset)
begin
ledtemp <= 0;
count1 <= 0;
count2 <= 0;
end
else if(db_btn)
begin
ledtemp <= 1'b1;
if (count1==4'd9) begin
count1 <= 0;
if (count2 == 4'd9)
count2 <= 0;
else
count2 <= count2 + 1;
end
else
count1 <= count1 + 1;
end
else if(~db_btn)
ledtemp <= 1'b0;
end
assign led = ledtemp;
Note:
I edited out the 7 segment multiplexing and 7 seg display code as it was not relevant here and I did not to overwhelm you guys with uncommented code :)
Should I increase the timer on my debouncing circuit?
Thanks
Async inputs must be sync'ed.
[ Edited ]- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-22-2012 08:12 PM - edited 06-22-2012 11:08 PM
You neglected to follow Gabor's advice from your previous thread. Async inputs always -- that is ALWAYS -- need to be synchronised (aligned) to the clock domain before use in any state machine. If you do not do this, the result will be a completely unreliable state machine.
Have you yet read the New Users Forum README thread ? In the mini-FAQ (post #2 in the thread) you will find this:
Design Fundamentals:
handling asynchronous inputs link#1 link#2 link#3
The first link has all that needs to be said, I believe. The two other links pretty much say the same things in different ways in the hopes that the ideas make sense to as many readers as possible.
You may well have other problems, but the async input problem will render your design unreliable until you fix it.
Let us know if you have questions on this topic. Then we can move forward to the next problem(s).
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Design this puppy first, THEN implement. ..
[ Edited ]
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-22-2012 10:56 PM - edited 06-23-2012 10:55 AM
After you absorb the async input problem, the next problem is your debouncer logic.
Forgive me if I am wrong, but it has the look of something which was written first, then tweaked here and there, without having first been designed. Please indulge my lecturing tone for a moment...
I like to distinguish design -- where the design function is first conceived and described as a block diagram or flowchart -- from implementation -- where the design is reduced to lines of source code, using the design as a guide. Ignoring your debouncing module source code for a moment or two, would you please describe in blocks, steps, or flowchart how the function of switch debouncing works?
I think this exercise, as simplistic as it might seem, will be helpful.
If you aren't in the mood for the design-before-implementing exercise, I have attached a cheat file for you. It includes a short and concise function design, and the source code implementing the functional design. I urge you to come up with your own design first, and then compare. Will you be tempted to peek?
UPDATE: While I'm indulging in shameless lecturing mode, here's another excerpt from the README thread:
7. You are not charged extra fees for comments in your code.
Another common problem is extensive sections of HDL code posted for review, without a description of how the code works or its intended function. And without comments. When trying to review source code which we are seeing for the very first time, well-written comments are a huge help. If the code is not well described or commented, the volunteers may be less likely to spend the time and effort required to figure out what you are trying to implement.
Not only are well-written comments helpful to strangers reading your code, they are also helpful to you, the designer. They help remind you of details you may forget over time, and they help you to quickly and easily assemble sections of your code into a larger design.
Regards,
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Re: Design this puppy first, THEN implement. ..
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 09:06 AM
I like your lecturing mode.. I get to learn lots when you are in that mode :)
My code was based on some flow chart work, here it is in its very raw and rough form. Im sorry if its not clear but it was for meant for me so I didnt make it that neat.
Also I apologize for pasting the code as it was and did not comment.. I have commented it now and hope it is much clearer.
module debouncing(
input clock,
input reset,
input button,
output reg out
);
localparam N = 19; //for a 10ms tick
reg [N-1:0]count;
wire tick;
// the counter that will generate the tick.
always @ (posedge clock or posedge reset)
begin
if(reset)
count <= 0;
else
count <= count + 1;
end
assign tick = &count; //tick will only go high when all 19 bits of count are 1, i.e. after 10ms
// now for the debouncing FSM
localparam[2:0] //defining the various states to be used
zero = 3'b000,
high1 = 3'b001,
high2 = 3'b010,
high3 = 3'b011,
one = 3'b100,
low1 = 3'b101,
low2 = 3'b110,
low3 = 3'b111;
reg [2:0]state_reg;
reg [2:0]state_next;
always @ (posedge clock or posedge reset)
begin
if (reset)
state_reg <= zero;
else
state_reg <= state_next;
end
always @ (*)
begin
state_next <= state_reg; // to make the current state the default state
out <= 1'b0; // default output low
case(state_reg)
zero:
if (button) //if button is detected go to next state high1
state_next <= high1;
high1:
if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero
state_next <= zero;
else if (tick) //but if button remains high even after 10 ms, go to next state high2.
state_next <= high2;
high2:
if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero
state_next <= zero;
else if (tick) //else if after 20ms (10ms + 10ms) button is still high go to high3
state_next <= high3;
high3:
if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero
state_next <= zero;
else if (tick) //and finally even after 30 ms input stays high then it is stable enough to be considered a valid input, go to state one
state_next <= one;
one: //debouncing eliminated make output high, now here I'll check for bouncing when button is released
begin
out <= 1'b1;
if (~button) //if button appears to be released go to next state low1
state_next <= low1;
end
low1:
if (button) //while here if button goes back to high then input is not yet stable and go back to state one
state_next <= one;
else if (tick) //else if after 10ms it is still high go to next state low2
state_next <= low2;
low2:
if (button) //while here if button goes back to high then input is not yet stable and go back to state one
state_next <= one;
else if (tick) //else if after 20ms it is still high go to next state low3
state_next <= low3;
low3:
if (button) //while here if button goes back to high then input is not yet stable and go back to state one
state_next <= one;
else if (tick) //after 30 ms if button is low it has actually been released and bouncing eliminated, go back to zero state to wait for next input.
state_next <= zero;
default state_next <= zero;
endcase
end
endmodule
I acted upon your suggestion and applied the single register delay.. more info on this below the code:
module button_bounce_counter(
input clock,
input reset,
input btn,
output a,
output b,
output c,
output d,
output e,
output f,
output g,
output dp,
output [3:0] an,
output led
);
reg db_reg;
wire db_btn, db_tick;
debouncing debouncer(.clock(clock), .reset(reset), .button(btn), .out(db_btn)); //instantiate the debouncer circuit
always @ (posedge clock)
begin
db_reg <= db_btn; //create a single clock cycle delay while sampling input
end
assign db_tick = ~db_reg & db_btn;
reg ledtemp;
reg [3:0] count1;
reg [3:0] count2;
always @ (posedge clock or posedge reset)
begin
if(reset)
begin
ledtemp <= 0;
count1 <= 0;
count2 <= 0;
end
else if(db_tick) //block for 2 digit counter (00 to 99)
begin
ledtemp <= 1'b1;
if (count1==4'd9) begin
count1 <= 0;
if (count2 == 4'd9)
count2 <= 0;
else
count2 <= count2 + 1;
end
else
count1 <= count1 + 1;
//if(count1 == 4'd9) count1 <= 0;
//else count1 <= count1 + 1;
end
else if(~db_btn)
ledtemp <= 1'b0;
end
assign led = ledtemp
Now here is the weird part.. I tried using the method taight by Bob, i.e. not to sampe the input directly and use a 2 register delay..
I first tried implementing this in the debouncing module and got many errors, and when I got rid of the errors each press on the button would make the counter jump to 88 and then it would get stick there only a reset would change the count to 0.
I tried the single register method as in exapmle 4 in link #1 by Bob, but it failed as well..
But when I applied this method to the other module i.e. the counter modulte, it works like a charm.. It is counting perfectly without any bounces.
I know that it works but I dont get it why wont it work when I put it in the debouncing module.. So even though its working the state machine is stick sampleing the button directly.. and yet it works..
Re: Design this puppy first, THEN implement. ..
[ Edited ]
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 10:18 AM - edited 06-23-2012 11:07 AM
Imagine that you are hereby appointed the Alfred E Neumann Visiting Professor of Debouncer Design. You are standing in front of a lecture hall filled with eager first-year debouncer design students.
Please explain to the lecture hall audience how your state diagram works.
I first tried implementing this in the debouncing module and got many errors,
Professor, please describe the nature of the errors -- and why these errors occurred.
and when I got rid of the errors each press on the button would make the counter jump to 88
Professor, there are 3 counters in your example code. Please, sir, which of these counters is jumping to 88, and how does the logic make this possible?
- Of the three counters, only one is wide enough (enough bits) to reach a value of 88.
- The counter which is wide enough to reach value=88 (count) depends only on clock and reset, and is not affected or controllled by the button input.
and then it would get stick there only a reset would change the count to 0.
Professor, please explain what signals are required to keep the counter 'running' so it is not 'stuck'.
I tried the single register method as in example 4 in link #1 by Bob, but it failed as well.
Sir, what logic failed, and in what manner did it fail? Is the example 4 method to which you refer a two-register edge-detection filter (as well as synchroniser)?
But when I applied this method to the other module i.e. the counter module, it works like a charm.. It is counting perfectly without any bounces.
Please, your example shows modules named debouncing and button_bounce_counter. Are you referring to the button_bounce_counter module?
I know that it works but I dont get it why wont it work when I put it in the debouncing module.. So even though its working the state machine is stick sampling the button directly.. and yet it works.
In science, one learns as much from failure as from success (if not more). Please explain what can be learned from this failure. Perhaps you can describe the events which lead to the failure, and how the failure is observed.
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Re: Design this puppy first, THEN implement. ..
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 11:28 AM
wow, I did not expect a reply like that as the level of sarcasm there is over 9000!
I dont know if I offended you or anything as I cant think of anyway you can get offended by anything I have written.
I'm afraid I would have to politely decline the honory title of professor given by you.
Also I mentioned before hand Im new to verilog and FPGA and started from scratch, I follow multiple books and this concept is also my understanding of what I read
But here are my replies.
Please explain to the lecture hall audience how your state diagram works
I have esplained its working in detail in the comments I made to the code. I will paste that section again here:
case(state_reg) zero: if (button) //if button is detected go to next state high1 state_next <= high1; high1: if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero state_next <= zero; else if (tick) //but if button remains high even after 10 ms, go to next state high2. state_next <= high2; high2: if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero state_next <= zero; else if (tick) //else if after 20ms (10ms + 10ms) button is still high go to high3 state_next <= high3; high3: if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero state_next <= zero; else if (tick) //and finally even after 30 ms input stays high then it is stable enough to be considered a valid input, go to state one state_next <= one; one: //debouncing eliminated make output high, now here I'll check for bouncing when button is released begin out <= 1'b1; if (~button) //if button appears to be released go to next state low1 state_next <= low1; end low1: if (button) //while here if button goes back to high then input is not yet stable and go back to state one state_next <= one; else if (tick) //else if after 10ms it is still high go to next state low2 state_next <= low2; low2: if (button) //while here if button goes back to high then input is not yet stable and go back to state one state_next <= one; else if (tick) //else if after 20ms it is still high go to next state low3 state_next <= low3; low3: if (button) //while here if button goes back to high then input is not yet stable and go back to state one state_next <= one; else if (tick) //after 30 ms if button is low it has actually been released and bouncing eliminated, go back to zero state to wait for next input. state_next <= zero; default state_next <= zero; endcase
Professor, please describe the nature of the errors -- and why these errors occurred.
EXAMPLE 4
input clock, async_in;
reg [3..0] state = idle;
reg in_dly1, in_dly2, in_dly3, edge_flag;
reg edge_flag;
wire edge_detected;
always @(posedge clock) in_dly1 <= async_in; // delay input one clock cycle
always @(posedge clock) in_dly2 <= in_dly1; // delay input a second clock cycle
assign edge_detected = in_dly1 && !in_dly2; // async_in was '0', now '1', rising edge detected
always @(posedge clock)
case (state)
idle: begin // wait for a low level on asynchronous input async_in
edge_flag <= 0;
if (edge_detected == 1) state <= found_edge; // edge found!
end
found_edge: begin // rising edge found, set a flag, loop back to idle state
edge_flag <= 1;
state <= idle;
end
endcase
This was your code that I followed as you clearly stated that we should not sample an input directly, Also I realized that this code was initself a debouncing mechanism.. so I connected my out signal to the edge_flag signal in your code. It compiled correctly but gave an error in synthesis. Ive forgotten the exact error but it was something about Xilinx cannot handle this operation and it was pointing to "case(state)
Professor, there are 3 counters in your example code. Please, sir, which of these counters is jumping to 88, and how does the logic make this possible?
by counter I meant the final result on the FPGA board on the 7 segment.. Im sorry I should have been more clear regarding that..
Please, your example shows modules named debouncing and button_bounce_counter. Are you referring to the button_bounce_counter module?
the debouncer is the module that compensates the bounces.. the one having 6 states high1, high2, high3, low1, low2, low3.. and the button_bounce_counter is who takes the output from the debouncer and uses it to enable the counter.. or in other words it consiste the if blocks that count to 99.
always @ (posedge clock) begin db_reg <= db_btn; //db_btn connected to out signal from the debouncing module end assign db_tick = ~db_reg & db_btn;
This is the part that I added in the debouncing module first.. thats what made it jump to 88 and stay there.. why?? I dont know.
But when I added this part to the counter module and made the counter only activate when db_tick was high it worked.
else if(db_tick) //block for 2 digit counter (00 to 99) begin ledtemp <= 1'b1; if (count1==4'd9) begin count1 <= 0; if (count2 == 4'd9) count2 <= 0; else count2 <= count2 + 1; end else count1 <= count1 + 1; //if(count1 == 4'd9) count1 <= 0; //else count1 <= count1 + 1; end else if(~db_btn) ledtemp <= 1'b0;
by worked I mean I programed my FPGA board and on every time I press the button, the 7 segment increments by 1.
In science, one learns as much from failure as from success (if not more).
Completely agree with this, and this is the reason why I posted here even though I got my desired result.
<deleted post>
[ Edited ]- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 11:45 AM - edited 06-23-2012 11:42 PM
<deleted>
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
No sarcasm intended
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 11:55 AM
wow, I did not expect a reply like that as the level of sarcasm there is over 9000!
I dont know if I offended you or anything as I cant think of anyway you can get offended by anything I have written.
No sarcasm was intended, and no offense toward you was intended or (from you) perceived.
I have often found it helpful -- as a student -- to take on the role of instructor. The demands of teaching and explaining are a thorough understanding of the subject matter, which leads to -- a better understanding of the subject matter.
In other words, the burden of teaching what you 'know' is an excellent teaching tool for the instructor because it requires 'knowing' what you teach.
Does this help? I apologise for giving you the wrong impression.
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Re: An interestin g Verilog coding question
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 11:56 AM
http://www.asic-world.com/verilog/vbehave2.html
check out the Example- nested-if-else-if .
Re: No sarcasm intended
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-23-2012 12:00 PM
I have often found it helpful -- as a student -- to take on the role of instructor. The demands of teaching and explaining are a thorough understanding of the subject matter, which leads to -- a better understanding of the subject matter.
In other words, the burden of teaching what you 'know' is an excellent teaching tool for the instructor because it requires 'knowing' what you teach.
its alright :)
like I said I come here to learn and value each response I get..
I completely agree with what you said, explaining as a teacher is way more difficult but it doesnt help if the teacher is as clueless as the students regarding how did we achieve the output.
Im really tired now and will look into this and code it in the way suggested by you from scratch tomorrow again. maybe that will help clarify things for me











