Sign In

Don't have a Xilinx account yet?

  • Choose to receive important news and product information
  • Gain access to special content
  • Personalize your web experience on Xilinx.com

Create Account

Username

Password

Forgot your password?
XClose Panel
Xilinx Home
Reply
Visitor
farazk86
Posts: 40
Registered: ‎05-30-2012
0

My debouncer design not working

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

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009

Async inputs must be sync'ed.

[ Edited ]

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

SIGNATURE:
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.
Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

Design this puppy first, THEN implement...

[ Edited ]

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

SIGNATURE:
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.
Visitor
farazk86
Posts: 40
Registered: ‎05-30-2012
0

Re: Design this puppy first, THEN implement...

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.

 

http://i.imgur.com/JNrlR.jpg

 

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..

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

Re: Design this puppy first, THEN implement...

[ Edited ]

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

SIGNATURE:
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.
Visitor
farazk86
Posts: 40
Registered: ‎05-30-2012
0

Re: Design this puppy first, THEN implement...

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.

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

<deleted post>

[ Edited ]

<deleted>

 

-- Bob Elkind

SIGNATURE:
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.
Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009

No sarcasm intended

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

SIGNATURE:
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.
Visitor
farazk86
Posts: 40
Registered: ‎05-30-2012
0

Re: An interesting Verilog coding question

This is how I always coded, and as I have learned from websites and books.. my books code this way as well and here is the website which appears as the top result in Google when searched for "if else verilog"

http://www.asic-world.com/verilog/vbehave2.html

check out the Example- nested-if-else-if .

Visitor
farazk86
Posts: 40
Registered: ‎05-30-2012
0

Re: No sarcasm intended

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