按键在日常生活中是十分常见的器件,但是在闭合及断开的一瞬间会有一连串的抖动。在单片机的设计中可以采用延时检测的方式去判断该按键是否按下,在FPGA设计中是不行的。在平时的设计中会有硬件和软件两种方式消抖。此处在用的是软件消抖。
按键的抖动一般在5ms至10ms之间,所以设计一个20ms计时器,当计时器结束时是什么电平就是什么电平。

以黑金板卡为例,当按键按下为低电平,未按下为高。那么在抖动时,只要对应端口检测到高电平时计数器清零,低电平开始计数。思路是这样的思路,那么就可以开始编程。

当计数器达到20ms时,输出一个flag,当输出flag时表示该按键按下。代码如下:
module key_filter
#(
parameter MAX_CNT= 20'd1_000_000
)
(
input wire sys_clk,
input wire sys_rst_n,
input wire pi_key,
output reg po_flag
);
reg [19:0] cnt_20ms;
//cnt_20ms:20ms计数器,当输入电平为0同时计满时,保持999_999
always @(posedge sys_clk or negedge sys_rst_n) begin
if (~sys_rst_n) begin
cnt_20ms <= 20'd0;
end
else if(pi_key == 1'b1) begin
cnt_20ms <= 20'd0;
end
else if ((pi_key == 1'b0)&&(cnt_20ms == MAX_CNT - 1'd1)) begin
cnt_20ms <= cnt_20ms;
end
else begin
cnt_20ms <= cnt_20ms + 1'd1;
end
end
//po_flag:在计数器计至999_998时输出po_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if (~sys_rst_n) begin
po_flag <= 1'b0;
end
else if (cnt_20ms == MAX_CNT - 2'd2) begin
po_flag <= 1'b1;
end
else begin
po_flag <= 1'b0;
end
end
Testbench如下
`timescale 1ns / 1ns
module tb_key_filter();
parameter CNT_1MS = 20'd19,
CNT_11MS = 21'd69,
CNT_41MS = 22'd149,
CNT_51MS = 22'd199,
CNT_60MS = 22'd249;
//key_filter Parameters
parameter PERIOD = 10 ;
//wire define
wire key_flag;
//reg define
reg clk;
reg rst_n;
reg key_in;
reg tb_cnt;
initial
begin
forever #(PERIOD) clk=~clk;
end
initial
begin
#(PERIOD*2) rst_n = 1;
end
//tb_cnt:通过该计数器,模拟按键抖动过程
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
tb_cnt <= 22'd0;
end
else if (tb_cnt == CNT_60MS) begin
tb_cnt <= 22'd0;
end
else begin
tb_cnt <= tb_cnt + 1'd1;
end
end
//key_in:模拟输入,1ms~11ms,51ms~60ms随机抖动。11ms~51ms之间表示按键按下.
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
key_in <= 1'b1;
end
else if((tb_cnt >= CNT_1MS) && (tb_cnt <= CNT_11MS) || (tb_cnt >= CNT_51MS)&&(tb_cnt <= CNT_60MS)) begin
key_in <= {$random}%2;
end
else if((tb_cnt > CNT_11MS)&&(tb_cnt < CNT_51MS)) begin
key_in <= 1'b0;
end
else begin
key_in <= 1'b1;
end
end
key_filter
#(
.CNT_MAX (5'd24)
)
key_filter_inst(
.sys_clk ( clk ),
.sys_rst_n ( rst_n ),
.pi_key ( key_in ),
.po_flag ( key_flag )
);
modelsim仿真,由于我并没有建立该工程,但是这个模块在另外一个工程中使用,所以用另一个仿真放出。

tb文件中写当tb_cnt计数为19时,开始产生随机数,一直到计数器为69时随机数产生结束。由此可见随机抖动时测试是正常的。
有上图可知按键在23时时有一个flag拉高的。
按键断开也是同理,
这就是按键抖动软件消除的FPGA实现,最后给出总体仿真图。
如果有错欢迎指出。
896

被折叠的 条评论
为什么被折叠?



