vhdl/verilog 按键消抖

来源:百度知道 编辑:UC知道 时间:2024/06/05 17:53:50
本人刚学verilog和vhdl,请看如下程序 附注释
`timescale 1ns/1ns

module sw_debounce(
clk,
rst_n,
sw1,
sw2,
sw3,
//output
led_d3,
led_d4,
led_d5
);

input clk;
input rst_n;
input sw1,sw2,sw3; //Active low
output led_d3;
output led_d4;
output led_d5;

// ---------------------------------------------------------------------------
// 通过降采样对sw1~sw3的输入做低通滤波,将其高频分量滤除,得到low_sw值
// ---------------------------------------------------------------------------
reg [19:0] cnt;
always @ (posedge clk or negedge rst_n)
if (!rst_n)
cnt <= 20'd0;
else
cnt <= cnt + 1'b1;

reg [2:0] low_sw;
always @(posedge clk or negedge rst_n)
if (!rst_n)
low_sw <= 3'b111;
else if (cnt == 20'hfffff) //每隔20MS检测一次按

reg [2:0] low_sw_r; //将low_sw信号锁存一个时钟周期,延时不是真的“锁存”
always @ ( posedge clk or negedge rst_n )
if (!rst_n)
low_sw_r <= 3'b111;
else
low_sw_r <= low_sw;

wire [2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);
就是这一段消抖的,考虑键没有按下的情况,low_sw_r应该是高电平,low_sw一样,这样led_ctrl是0,如果有键按下,low_sw先变成0,而low_sw_r要等到20ms后才置0,因此在这个时间段里led_ctrl就变成1, 因此就检测到了按键的下降沿变化.
同样的,下面这段
always @ (posedge clk or negedge rst_n)
if (!rst_n)
begin
d1 <= 1'b0;
d2 <= 1'b0;
d3 <= 1'b0;
end
else
begin
if ( led_ctrl[0] ) d1 <= ~d1;
if ( led_ctrl[1] ) d2 <= ~d2;
if ( led_ctrl[2] ) d3 <= ~d3;
end

也是20ms采样一次led_ctrl的结果,如果毛刺小于20ms,那么led_ctrl置0的时间同样也会小于20ms,那么这段程序就检测不到led_ctrl的变化了.

20ms采样一次按键,然后在判断是否与原来一样,从而确定按键是否按下,也就是消抖的意思