A debouncer circuit cleans up noisy button presses so the computer sees just one clear press.
Debouncer circuit design in Verilog
module debouncer(
input clk,
input button_in,
output reg button_out
);
// internal registers
reg [15:0] counter = 0;
reg button_sync_0 = 0;
reg button_sync_1 = 0;
always @(posedge clk) begin
// synchronize button input to clock
button_sync_0 <= button_in;
button_sync_1 <= button_sync_0;
if (button_sync_1 == button_out) begin
counter <= 0; // reset counter if stable
end else begin
counter <= counter + 1; // count how long input is stable
if (counter == 16'hFFFF) begin
button_out <= button_sync_1; // update output after stable period
end
end
end
endmoduleThis example uses a 16-bit counter to wait for the input to be stable.
Two flip-flops synchronize the button input to the clock to avoid timing issues.
module simple_debouncer(
input clk,
input button_in,
output reg button_out
);
reg [3:0] count = 0;
reg button_sync_0 = 0;
reg button_sync_1 = 0;
always @(posedge clk) begin
button_sync_0 <= button_in;
button_sync_1 <= button_sync_0;
if (button_sync_1 == button_out) begin
count <= 0;
end else begin
count <= count + 1;
if (count == 4'b1111) begin
button_out <= button_sync_1;
end
end
end
endmodulemodule debouncer_with_reset(
input clk,
input rst,
input button_in,
output reg button_out
);
reg [15:0] counter = 0;
reg button_sync_0 = 0;
reg button_sync_1 = 0;
always @(posedge clk or posedge rst) begin
if (rst) begin
counter <= 0;
button_out <= 0;
button_sync_0 <= 0;
button_sync_1 <= 0;
end else begin
button_sync_0 <= button_in;
button_sync_1 <= button_sync_0;
if (button_sync_1 == button_out) begin
counter <= 0;
end else begin
counter <= counter + 1;
if (counter == 16'hFFFF) begin
button_out <= button_sync_1;
end
end
end
end
endmoduleThis testbench simulates a noisy button press and shows how the debouncer cleans the signal.
module testbench();
reg clk = 0;
reg button = 0;
wire clean_button;
// Instantiate debouncer
debouncer uut(
.clk(clk),
.button_in(button),
.button_out(clean_button)
);
// Clock generation
always #5 clk = ~clk; // 100MHz clock
initial begin
$monitor($time, " Button: %b, Clean: %b", button, clean_button);
// Simulate noisy button press
#10 button = 1;
#2 button = 0;
#3 button = 1;
#2 button = 0;
#10 button = 1; // stable press
#100 $finish;
end
endmodule
module debouncer(
input clk,
input button_in,
output reg button_out
);
reg [15:0] counter = 0;
reg button_sync_0 = 0;
reg button_sync_1 = 0;
always @(posedge clk) begin
button_sync_0 <= button_in;
button_sync_1 <= button_sync_0;
if (button_sync_1 == button_out) begin
counter <= 0;
end else begin
counter <= counter + 1;
if (counter == 16'hFFFF) begin
button_out <= button_sync_1;
end
end
end
endmoduleDebouncing is important because mechanical buttons do not produce clean signals.
The counter length controls how long the input must be stable before changing output.
Synchronizing inputs to the clock prevents timing errors in digital circuits.
A debouncer cleans noisy button signals into one stable output.
Use counters and synchronization to detect stable button presses.
Debouncing helps avoid multiple unwanted signals from one press.
Practice
What is the main purpose of a debouncer circuit in Verilog?
Solution
Step 1: Understand the problem of noisy signals
Mechanical buttons often produce multiple quick on/off signals (noise) when pressed.Step 2: Role of debouncer
A debouncer waits for the input to be stable for some time before changing the output, thus cleaning the noise.Final Answer:
To clean noisy button signals and produce a stable output -> Option DQuick Check:
Debouncer = Clean noisy signals [OK]
- Thinking debouncer speeds up the clock
- Confusing debouncer with analog to digital converter
- Assuming debouncer generates signals
Which of the following is the correct way to declare a 16-bit counter register in Verilog?
?Solution
Step 1: Understand Verilog register declaration
Registers use 'reg' keyword and bit width is declared as [MSB:LSB].Step 2: Check each option
reg [15:0] counter; correctly declares a 16-bit register from bit 15 down to 0.Final Answer:
reg [15:0] counter; -> Option BQuick Check:
16-bit reg = reg [15:0] name; [OK]
- Using wire instead of reg for counters
- Incorrect bit range syntax
- Declaring arrays instead of bit vectors
Given this Verilog snippet for a debouncer counter:
always @(posedge clk) begin
if (button == last_button) begin
if (counter < 3) counter <= counter + 1;
end else counter <= 0;
last_button <= button;
end
What is the value of counter after 5 clock cycles if button stays stable at 1?
Solution
Step 1: Analyze counter increment condition
Counter increments only if button equals last_button and counter is less than 3.Step 2: Trace counter over 5 cycles
Initially counter=0. It increments each cycle until it reaches 3, then stops incrementing.Final Answer:
3 -> Option CQuick Check:
Counter maxes at 3 despite 5 cycles [OK]
- Assuming counter increments beyond 3
- Ignoring last_button update
- Resetting counter incorrectly
Identify the error in this debouncer code snippet:
reg [3:0] counter;
reg last_button;
always @(posedge clk) begin
if (button == last_button) begin
counter = counter + 1;
end else begin
counter = 0;
end
last_button = button;
end
Solution
Step 1: Check assignment types in sequential always block
Sequential logic should use non-blocking assignments (<=) to avoid race conditions.Step 2: Identify the error
The code uses blocking assignments (=) inside a clocked always block, which is incorrect.Final Answer:
Using blocking assignments (=) inside always block for sequential logic -> Option AQuick Check:
Use <= for sequential logic assignments [OK]
- Using = instead of <=
- Ignoring sensitivity list importance
- Assuming initial values fix assignment errors
You want to design a debouncer that waits for 10ms of stable input before changing output. The clock frequency is 1MHz. How many bits should the counter have at minimum?
Solution
Step 1: Calculate required count for 10ms at 1MHz clock
10ms = 0.01 seconds. Clock period = 1us (1/1MHz). Number of counts = 0.01 / 0.000001 = 10,000 counts.Step 2: Find minimum bits to count 10,000
2^13 = 8192 (too small), 2^14 = 16384 (enough). So minimum 14 bits needed.Final Answer:
14 bits -> Option AQuick Check:
10,000 < 2^14 = 16384 [OK]
- Using clock frequency as count directly
- Choosing too few bits to cover count
- Confusing ms and us units
Ready to prove it?
Pass the test and this pattern moves unknown
