有限状态机实现的软件消抖电路
Figure 5.8 Original and debounced waveforms.
debouncing scheme 2
// Debouncing circuit
module debouncing
(
input wire clk,
input wire reset,
input wire sw, // 抖动的按钮或拨码开关输入信号
output reg db_level, // 去抖动后的开关信号输出
output reg db_tick // 每次输出宽度等于一个clk周期的脉冲信号
);
// 状态寄存器相关常量和变量定义
localparam [1:0]
zero = 2'b00,
wait0 = 2'b01,
one = 2'b10,
wait1 = 2'b11;
reg [1:0] state_reg;
reg [1:0] state_next;
// 状态寄存器时序逻辑
always @(posedge clk, posedge reset)
begin
if (reset)
state_reg <= zero;
else
state_reg <= state_next;
end
// 计数器相关常量和变量定义
localparam N=21; // 2^N * 20ns 约等于 40ms, 此处假定clk时钟频率=50MHz, 即周期=20ns
localparam COUNTER_MAX={N{1'b1}};
localparam COUNTER_ZERO={N{1'b0}};
reg [N-1:0] cnt_reg;
wire [N-1:0] cnt_next;
reg cnt_load;
reg cnt_is_decreasing;
wire cnt_is_finished;
// 计数器时序逻辑
always @(posedge clk, posedge reset)
begin
if (reset)
cnt_reg <= COUNTER_ZERO;
else
cnt_reg <= cnt_next;
end
// 计数器的 next-state 组合逻辑
assign cnt_next =
(cnt_load)? (COUNTER_MAX) : // load cnt_next=COUNTER_MAX
(cnt_is_decreasing)? (cnt_reg - 1) : // cnt_next=(cnt_reg - 1)
cnt_reg; // cnt_next=cnt_reg
// 计数器是否到达计数终点
assign cnt_is_finished = (COUNTER_ZERO == cnt_next);
// 有限状态机控制通道的 next-state 组合逻辑
always @*
begin
state_next = state_reg; // default state: the same
cnt_load = 1'b0; // default
cnt_is_decreasing = 1'b0; // default
db_tick = 1'b0; // default
case (state_reg)
zero:
begin
db_level = 1'b0;
if (sw)
begin
state_next = wait1;
cnt_load = 1'b1;
end
end
wait1:
begin
db_level = 1'b0;
if (sw)
begin
cnt_is_decreasing = 1'b1;
if (cnt_is_finished)
begin
state_next = one;
db_tick = 1'b1;
end
end
else
state_next = zero;
end
one:
begin
db_level = 1'b1;
if (~sw)
begin
state_next = wait0;
cnt_load = 1'b1;
end
end
wait0:
begin
db_level = 1'b1;
if (~sw)
begin
cnt_is_decreasing = 1'b1;
if (cnt_is_finished)
begin
state_next = zero;
end
end
else
state_next = one;
end
default:
begin
end
endcase
end
endmodule