I'm trying to design a de-bouncer circuit , which is widely used in digital design . The module that I'm trying to implement is as shown below :-

I've written the following Verilog Module :-

timescale 1ns / 1ps

module debounce_ckt(
input button,
input clk,
output reg result
);

/************************************* Internal Variables **********************************/
reg Q1;
reg Q2;
wire EN1 = 1'b1;
wire EN2 = 1'b1;
wire xor_out;
/****************************** Debounce ckt Implementation code ****************************************/

DFF FF1 (button,clk,EN1,Q1);
DFF FF2 (Q1,clk,EN2,Q2);

xor g1 (xor_out,Q1,Q2);

counter C1 (clk,xor_out,~Cout,Cout);
DFF FF3 (Q2,clk,Cout,result);

endmodule

/***************************************** N-bit counter *************************************/
module counter (clk, SCLR,EN,Cout);
input clk;
input SCLR;   // Clear of counter //
input EN ; // Active 'HIGH' Enable //
output reg [N-1:0] Cout; // Counter Output //

// Time period of debounce ckt = T = (2^N + 2)/ f //
// 'f' is the input clock frequency //
// 'N' is the mod value of counter //

parameter N = 16;

always@(posedge clk)
if(SCLR)    Cout <= 0;
else if (EN)
begin
if (Cout == N-1)
Cout <= 0;
else
Cout <= Cout + 1;
end

endmodule

/************************************* D Flip Flop Module (with Enable)**************************/

module DFF(input D,input clk,input EN ,output reg Q);

always @(posedge clk or EN)
begin
if(EN)
begin
Q <= D;
end
end
endmodule



Testbench is as follows :-

timescale 1ns / 1ps

module tb;

// Inputs
reg button;
reg clk;

// Outputs
wire result;

// Instantiate the Unit Under Test (UUT)
debounce_ckt uut (
.button(button),
.clk(clk),
.result(result)
);

initial begin
clk = 1'b0;
end

always #5 clk = ~ clk;

initial begin

#12 button = 0;#10 button = 0 ; #10 button = 1 ; #10 button = 0 ;
#12 button = 1;#10 button = 1 ; #10 button = 0 ; #10 button = 1 ;
#12 button = 1;#10 button = 0 ; #10 button = 0 ; #10 button = 1 ;
#12 button = 0;#10 button = 1 ; #10 button = 1 ; #10 button = 0 ;
#10 $finish; end endmodule  The output 'result' is going to 'X' don't care state, when I'm trying to simulate the files. Can anyone point out where the issue lies and what corrections are to be made. I'm not expecting a whole working code in the answer. I'd just want to know the error in my code which is causing this. • That design is asking for trouble. Are your two flip flops meant to synchronize the asynchronous input to your FPGA clock domain? Because if so, it's bad practice to try and use the signal before it has run through both flip flops because it somewhat defeats the synchronization. You may not see problems in the simulation, but you will see problems in the real world. Instead, compare your debouncer output to your debouncer input. Commented Jun 16, 2020 at 18:31 • Look at how the maximintegrated.com/en/products/interface/… does it. Don't forget to keep synchronizers on your design. The ASIC doesn't need them but yours is on an FPGA so it does. Commented Jun 16, 2020 at 18:33 • The circuit mentioned in the question is the one used by digikey . A VHDL code for similar circuit has been provided by them. But I was trying to develop a Verilog equilvalent . You may refer this link. digikey.com/eewiki/display/LOGIC/… . The circuit above is not particularly intended for FPGA's in specific. I've made the changes in question. Commented Jun 16, 2020 at 18:35 • I can't really help you on the verilog since I don't know verilog. But I still stand by what I said about the synchronizers. You should really had a chain of two flip flops before this entire circuit. But just glancing at everything, are your simulated button presses actually long enough to exceed the debounce time? Because from the looks of it, each button presses is only a few clock cycles long but your N =16 Commented Jun 16, 2020 at 18:41 • There are no compile errors when I run it in Xilinx ISE 14.7. But the issue pointed by @toolic came up, when run in edaplayground . Should I reduce the N value and try ? Or how to resolve this ? Commented Jun 16, 2020 at 18:56 ## 5 Answers # Debouncer This debouncer assumes that its input is synchronised to the clock. The output will only change state when the input has been in the opposite state for N clock cycles, i.e. a form of hysteresis to produce a kind of low pass filter. The counter only counts when the input and output differ, thus reducing switching losses when the input equals the output. module Debounce #( parameter MAX_COUNT = 16 ) ( input wire clock, input wire in, // Synchronous and noisy input. output reg out, // Debounced and filtered output. output reg edj, // Goes high for 1 clock cycle on either edge of output. Note: used "edj" because "edge" is a keyword. output reg rise, // Goes high for 1 clock cycle on the rising edge of output. output reg fall // Goes high for 1 clock cycle on the falling edge of output. ); localparam COUNTER_BITS =$clog2(MAX_COUNT);

reg [COUNTER_BITS - 1 : 0] counter;
wire w_edj;
wire w_rise;
wire w_fall;

initial
begin
counter = 0;
out = 0;
end

always @(posedge clock)
begin
counter <= 0;  // Freeze counter by default to reduce switching losses when input and output are equal.
edj <= 0;
rise <= 0;
fall <= 0;
if (counter == MAX_COUNT - 1)  // If successfully debounced, notify what happened.
begin
out <= in;
edj <= w_edj;    // Goes high for 1 clock cycle on either edge.
rise <= w_rise;  // Goes high for 1 clock cycle on the rising edge.
fall <= w_fall;  // Goes high for 1 clock cycle on the falling edge.
end
else if (in != out)  // Hysteresis.
begin
counter <= counter + 1;  // Only increment when input and output differ.
end
end

// Edge detect.
assign w_edj = in ^ out;
assign w_rise = in & ~out;
assign w_fall = ~in & out;

endmodule


# Synchroniser

All asynchronous inputs, such as buttons, need to be synchronised to the clock something like this:

module Sync
#(
parameter SYNC_BITS = 3  // Number of bits in the synchronisation buffer (2 minimum).
)
(
input wire clock,
input wire in,     // Asynchronous input.
output wire out    // Synchronous output.
);

localparam SYNC_MSB = SYNC_BITS - 1;

reg [SYNC_MSB : 0] sync_buffer;

assign out = sync_buffer[SYNC_MSB];

always @(posedge clock)
begin
sync_buffer[SYNC_MSB : 0] <= {sync_buffer[SYNC_MSB - 1 : 0], in};
end

endmodule


The output of the synchroniser should be connected to the input of the debouncer.

# Test Bench

I increased the button timings and reduced MAX_COUNT to see the debouncing effect.

timescale 1ns/1ps

module SyncDebounce_TB;

reg clock;
reg button;
wire button_sync;
wire button_sync_db;
wire edj;
wire rise;
wire fall;

Sync Sync_Inst
(
.clock(clock),
.in(button),
.out(button_sync)
);

Debounce
#(
.MAX_COUNT(4)
)
Debounce_Inst
(
.clock(clock),
.in(button_sync),
.out(button_sync_db),
.edj(edj),
.rise(rise),
.fall(fall)
);

initial
begin
clock = 0;
end

always #5 clock = ~clock;

always
begin
#2 button = 0; #20 button = 1; #20 button = 0;
#22 button = 1; #20 button = 1; #20 button = 0; #20 button = 1;
#22 button = 1; #20 button = 0; #20 button = 0; #20 button = 1;
#22 button = 0; #20 button = 1; #20 button = 1; #20 button = 0;
#80 \$stop;
end

endmodule


# Simulation

This shows the debounced button signal with edge detect (both, rise and fall).

It takes 3 clock cycles to synchronise the input and 4 clock cycles to debounce it.

There's a wiring error in the instantiation of counter — you have the fourth port declared as an N-bit register, but you've connected it to the undeclared (implied 1-bit) signal Cout. Doesn't the simulator give you a warning about that?

But in any case, you'll need to let the simulation run for at least N = 16 clock cycles before anything significant happens.

Note that using the same constant N for both the width of the counter and its terminal value is at best confusing ... not to mention wasteful.

EDIT: Suggested implementation of counter:

module counter (
input         clk,
input         SCLR,   // Synchronous clear of counter
input         EN,     // Active-HIGH Enable
output        Cout    // terminal count reached
);

// Time period of debounce ckt = T = (2^N + 2)/ f
// 'f' is the input clock frequency
// 'N' is the mod value of counter

parameter N = 16;

reg   [N:0] count;  // internal counter

assign Cout = count[N];

always @(posedge clk) begin
if (SCLR) begin
count <= 0;
end else if (EN) begin
if (count[N] == 1'b1) begin
count <= 0;
end else begin
count <= count + 1;
end
end
end

endmodule

• Yes, the simulator does give me a warning regarding this, and not an error. Can you please suggest me on how to rectify this warning ? Commented Jun 16, 2020 at 19:07
• See edit above. Commented Jun 16, 2020 at 19:19
• This rectified the counter warning. But the signals Q1,Q2,xor_out are being in "X" state. Do I need to put them in any always block ? Commented Jun 16, 2020 at 19:28

Verilog Module :-

timescale 1ns / 1ps

module debounce_ckt(
input button,
input clk,
input reset,
output result
);

/*********** Internal Variables **********/

wire Q1,Q2,SCLR,Q3,Cout;
wire HIGH = 1;
wire LOW = 0;

/************** Main Code ******************/

D_FF D1(clk,reset,button,HIGH,LOW,Q1);
D_FF D2(clk,reset,Q1,HIGH,LOW,Q2);

xor g1(SCLR,Q1,Q2);

N_bit_counter C1(clk,reset,~Cout,SCLR,Cout);

D_FF D3(clk,reset,Q2,Cout,LOW,Q3);

assign result = Q3;

endmodule

/************** D Flip Flop Module ***************/

module D_FF(
input clk,
input reset,
input D,
input enable,
input clear,
output reg Q
);

// Active "HIGH " clear, reset, enable signals //

always @(posedge clk)
begin
if (reset) Q<=0;
else
begin
case({clear,enable})
2'b00 : Q<=Q;
2'b01 : Q<=D;
default : Q<=0;
endcase
end
end
endmodule

/******************** Counter Module **********************/

module N_bit_counter(
input clk,
input reset,
input enable,
input clear,
output Cout
);

// Active "HIGH " clear, reset, enable signals //

parameter N = 8; // Counts from 0 to 2^[N-1]
reg [N-1:0] count;

assign Cout = count[N-1];

always @(posedge clk)
begin
if (reset) count <= 8'b0;
else
begin
case({clear,enable})
2'b00 : count <= count;
2'b01 : count <= count+1;
default : count <= 8'b0;
endcase
end
end
endmodule



Testbench :-

timescale 1ns / 1ps

module testbench;

// Inputs
reg button;
reg clk;
reg reset;
// resultputs
wire result;

// Instantiate the Unit Under Test (UUT)
debounce_ckt uut (
.button(button),
.clk(clk),
.reset(reset),
.result(result)
);

initial begin
// Initialize Inputs
clk = 0;
forever #15 clk=~clk;      // Clock Time peroid T = 30 ns

end

initial begin

#6000;
button=0; reset=1;
#50 reset=0;
#50 button=1;            // Fluctuations - glitch
#200 button=0;
#50 button=1;           // Fluctuations - glitch
#150 button=0;
#100 button=1;          // Pushbotton pressed
#8000 button=0;
#50 button=1;           // Fluctuations - glitch
#200 button=0;
#50 button=1;           // Fluctuations - glitch
#200 button=0;

end
endmodule

`

In simulation wave window, make sure that the simulation is run for atleast 20 microseconds or higher .

Simulation Output :-

Well, your implementation of the DFF with enable is not quite correct, but I'll give you a chance to look at that yourself. There may be other problems with your code as well.

Since you have a working simulation you should be able to look at signals inside your modules to see why the logic behaves at it does.

Note that the output of FF3 will not be loaded with a known value until your counter reaches its final value and its COUT signal goes high. Does your simulation allow that to happen.

• Can you suggest me what's the issue with the D-FF ? And yes, all the signals Cout,Q1,Q2 etc are in "X" state . How do I rectify this ? Commented Jun 16, 2020 at 18:46
• Use the simulation to observe the signals inside FF1. Tell us how you think it should work and how it actually does behave. Commented Jun 16, 2020 at 18:53
• I've tried simulating the. D_FF module which I've written. It seems to work fine . Commented Jun 16, 2020 at 19:01
• Try changing the D input while EN is high but the clock is low. Commented Jun 16, 2020 at 20:05

Are your two flip flops meant to synchronize the asynchronous input to your FPGA clock domain? Because if so, it's bad practice to try and use the signal before it has run through both flip flops because it somewhat defeats the synchronization. You may not see problems in the simulation, but you will see problems in the real world.

Just glancing at everything, are your simulated button presses actually long enough to exceed the debounce time? Because from the looks of it, each button press is only a one or two clock cycles long but your debounce period is N = 16 clock cycles.

If that's the case, of course your output wouldn't respond because all your button presses are short enough to be interpreted bounces. Set your button presses to be 20 clock cycles long and then check that it is passed to the output on the 16th clock cycle.

• I've tried the simulation with each button press being 20 clock cycles long. Still the error persists. Commented Jun 16, 2020 at 18:50