俄语在线网站制作/上海专业做网站
文章目录
- 按键抖动分析
- 按键消抖逻辑
- Verilog设计与仿真
- Modelsim工程下载
按键抖动分析
常用的轻触按键内部结构为金属弹片,在手按下、松开的过程中往往会发生细微抖动。
输出的逻辑电平也会发生快速翻转,按键按下和释放的过程中,都会产生抖动,虽然时间非常短暂,但是对于单片机、FPGA这种实时性非常高的系统来说是不可接受的,为了保证系统能正确识别按键的开关,必须对按下和释放的过程进行滤波处理。
按键消抖逻辑
和单片机消抖逻辑类似,FPGA可以通过两个计数器来对持续的高低电平进行计时,当达到一定的时间时,可以认为触点稳定,可以认为是一次有效的按下或释放,从而输出对应的信号。
Verilog设计与仿真
下面是基于Verilog状态机思路,使用两个计数器分别对按下和释放进行滤波处理,理论上按下和释放不会同时出现,所以使用一个计数器也可以实现的,为了便于理解,我们使用两个计数器分别对高低电平进行计时。
按键消抖驱动模块drv_key.v
:
/********************************************************************** Copyright(C), 2010-2023, CSDN @ whik1194* ModuleName : drv_key.v * Date : 2023年2月20日* Time : 21:26:01* Author : https://blog.csdn.net/whik1194* Function : drv_key* Version : v1.0* Version | Modify* ----------------------------------* v1.0 .....*********************************************************************/module drv_key(//Inputsinput clk,input rst_n,input key,//Outputsoutput flag_press,output flag_release
);//parameter
parameter KEY_PRESS = 1'b0; //按键按下有效
parameter FILTER_TIME = 27_000_0; //按键消抖时间//localparam
localparam KEY_RELEASE = !KEY_PRESS;
localparam S0_IDLE = 0;
localparam S1_KEY_PRESS = 1;
localparam S2_KEY_RELEASE = 2;//reg
reg [31:0] cnt_press;
reg [31:0] cnt_release;
reg [4:0] key_sreg; //shift reg
reg [3:0] fsm;
reg en;wire key_is_press = (key_sreg[4:1] == {4{KEY_PRESS}});
wire key_is_release = (key_sreg[4:1] == {4{KEY_RELEASE}});
wire key_is_shake = !(key_is_press || key_is_release);//assign
assign flag_press = (fsm == S1_KEY_PRESS);
assign flag_release = (fsm == S2_KEY_RELEASE);//always
//按键边沿捕获移位寄存器
always @ (posedge clk) beginif(!rst_n) beginkey_sreg <= {5{KEY_RELEASE}};endelse beginkey_sreg <= key_sreg << 1 | key;end
endalways @ (posedge clk) beginif(!rst_n) beginfsm <= S0_IDLE;cnt_press <= 0;cnt_release <= 0;en <= 0;endelse begincase (fsm)S0_IDLE: beginif(key_is_shake) begincnt_press <= 'd0;cnt_release <= 'd0;en <= 1;end else if(key_is_press && en) beginif(cnt_press < FILTER_TIME)cnt_press <= cnt_press + 1;else begincnt_press <= 0; //max = FILTER_TIMEfsm <= S1_KEY_PRESS;endendelse if(key_is_release && en) beginif(cnt_release < FILTER_TIME)cnt_release <= cnt_release + 1;else begincnt_release <= 0; //max = FILTER_TIMEfsm <= S2_KEY_RELEASE;endendelse beginfsm <= fsm;cnt_press <= 0;cnt_release <= 0;en <= 0;endendS1_KEY_PRESS: beginfsm <= S0_IDLE;en <= 0; endS2_KEY_RELEASE: beginfsm <= S0_IDLE;en <= 0; enddefault: beginfsm <= fsm;endendcaseend
endendmodule //get_key end
Modelsim仿真激励模块drv_key_tb.v
/********************************************************************** Copyright(C), 2010-2023, CSDN @ whik1194* ModuleName : drv_key.v * Date : 2023年2月20日* Time : 21:26:01* Author : https://blog.csdn.net/whik1194* Function : drv_key* Version : v1.0* Version | Modify* ----------------------------------* v1.0 .....*********************************************************************/`timescale 1ns/1psmodule drv_key_tb;localparam PERIOD = 10; //ns
localparam KEY_PRESS = 1'b0;
localparam KEY_RELEASE = !KEY_PRESS;
localparam FILTER_TIME = 500; reg clk;
reg rst_n;
reg key;always #(PERIOD/2) clk <= !clk;initial begin$display("testbench: %s", drv_key_tb);rst_n = 0;clk = 0;key = KEY_RELEASE;#(PERIOD*100)rst_n = 1;#(PERIOD*1000)task_press;task_release;task_press;task_release;enddrv_key #(.FILTER_TIME(FILTER_TIME)
)drv_key(//Inputs.clk(clk),.rst_n(rst_n),.key(key),//Outputs.flag_press(),.flag_release()
);integer i;
task task_press;
begin@(posedge clk);for(i = 0; i <= 10; i = i + 1) beginkey = KEY_PRESS;#(100*PERIOD);@(posedge clk);key = !key;#(100*PERIOD);@(posedge clk);endkey = KEY_PRESS;#(FILTER_TIME*PERIOD)#(FILTER_TIME*PERIOD)@(posedge clk);end
endtasktask task_release;
begin@(posedge clk);for(i = 0; i <= 10; i = i + 1) beginkey = KEY_RELEASE;#(100*PERIOD);@(posedge clk);key = !key;#(100*PERIOD);@(posedge clk);endkey = KEY_RELEASE;#(FILTER_TIME*PERIOD)#(FILTER_TIME*PERIOD)@(posedge clk);end
endtaskendmodule //drv_key_tb end
Modelsim仿真波形:
实际调用也非常方便,只需要指定按键按下的电平状态和滤波的周期即可:
drv_key #(.KEY_PRESS(1'b0),.FILTER_TIME(100_000_000/20) //100ms
)drv_key_ut0(//Inputs.clk(gclk), //50MHz=20ns.rst_n(gresetn),.key(key1),//Outputs.flag_press(flag_press),.flag_release(flag_release)
);
Modelsim工程下载
- fsm_key_filter.rar