FPGA(Verilog)实现按键消抖

实现按键消抖功能:

1.滤除按键按下时的噪声和松开时的噪声信号。

2.获取已消抖的按键按下的标志信号。

3.实现已消抖的按键的连续功能。

Verilog实现

模块端口

复制代码
key_filter(
	input	wire 	clk		,
	input	wire 	rst_n	,
	input	wire 	key_in	,	//按下按键时为0

	output 	reg 	key_flag,	//第一次按下的标志信号(已消抖)
	output 	reg 	key_out	,	//输出按键信号(已消抖)
	output 	reg 	key_cont	//输出连续按键信号(已消抖)-计时一段时间拉高1次
);

20ms计数

复制代码
always@(posedge clk or negedge rst_n)
	if(!rst_n) cnt_20ms <= 20'd0;
	else if(key_in)	//松下按键
		cnt_20ms <= 20'd0;
	else if(cnt_20ms == CNT_20MS_MAX)	//达到消抖时间
		cnt_20ms <= CNT_20MS_MAX;
	else
		cnt_20ms <= cnt_20ms+20'd1;

按键第一次按下的标志信号

复制代码
always@(posedge clk or negedge rst_n)
	if(!rst_n) key_flag<=1'b0;
	else if(cnt_20ms == CNT_20MS_MAX-20'd1)	//已消抖,拉高key_flag一个周期
		key_flag<= 1'b1;
	else 
		key_flag<=1'b0;

已消抖的按键信号

复制代码
always@(posedge clk or negedge rst_n)
	if(!rst_n) key_out<=1'b0;
	else if(key_in)	//松下按键
		key_out<= 1'b0;
	else if(key_flag)	//已消抖
		key_out<= 1'b1;
	else ;

连续信号所需计数器

复制代码
always@(posedge clk or negedge rst_n)
	if(!rst_n) cnt_cont <= 20'd0;
	else if(key_out) begin	//已消抖
		if(cnt_cont == CNT_CONT_MAX)
			cnt_cont <= 20'd0;
		else 
			cnt_cont <= cnt_cont+20'd1;
	end
	else
		cnt_cont <= 20'd0;

连续按键信号(已消抖)-计时一段时间拉高1次

复制代码
always@(posedge clk or negedge rst_n)
	if(!rst_n) key_cont<=1'b0;
	else if(key_flag)
		key_cont <= 1'b1;
	else if(key_out) begin	//已消抖
		if(cnt_cont == CNT_CONT_MAX)	//连续按下一定时间,拉高key_cont一个周期
			key_cont <= 1'b1;
		else 
			key_cont <= 1'b0;
	end
	else
		key_cont <= 1'b0;

testbench:

复制代码
`timescale 1ns/1ns
module tb_key_filter();

reg clk ;
reg rst_n ;
reg key_in ;
reg [7:0] tb_cnt ;

wire key_flag;
wire key_out ;
wire key_cont;

defparam u_key_filter.CNT_20MS_MAX = 20'd9;
defparam u_key_filter.CNT_CONT_MAX = 24'd49;

initial begin 
	clk = 1'b1 ;
	rst_n = 1'b0;
	#20
	rst_n = 1'b1;
	#(20*199+100)
	$stop;
end
 
always #10 clk=~clk;
 
always@(posedge clk or negedge rst_n)
	if(!rst_n) tb_cnt <=8'b0;
	else if(tb_cnt ==8'd199)
		tb_cnt <=8'b0;
	else
		tb_cnt <= tb_cnt +8'b1;
 
always@(posedge clk or negedge rst_n)
	if(!rst_n) key_in <= 1'b1 ; 
	else if(((tb_cnt>=8'd9) && (tb_cnt<=8'd39))
		||((tb_cnt>=8'd159) && (tb_cnt<=8'd179)))
		key_in<={$random}%2;
	else if((tb_cnt<8'd9)||(tb_cnt>8'd179))
		key_in<=1'b1;
	else
		key_in<=1'b0;

key_filter u_key_filter(
	.clk		(clk		),
	.rst_n		(rst_n		),
	.key_in		(key_in		), 

	.key_flag	(key_flag	),	//第一次按下的标志信号(已消抖)
	.key_out	(key_out	),	//输出按键信号(已消抖)
	.key_cont	(key_cont	)	//输出连续按键信号(已消抖)-计时一段时间拉高1次
);

endmodule

仿真波形:

相关推荐
女神下凡20 小时前
芯参谋(37):EEPROM_电路设计指南
arm开发·单片机·嵌入式硬件·fpga开发·设计规范
szxinmai主板定制专家2 天前
工业视觉新思路:FPGA图像预处理+RK NPU推理,实现高速缺陷检测
人工智能·嵌入式硬件·fpga开发·rk3576+codesys
FPGA小徐2 天前
【硬件实战】立创 EDA 绘制 TF/SD 卡模块电路|SPI 模式原理图 + 阻抗匹配 + PCB 布局布线全教程
单片机·嵌入式硬件·fpga开发
狂奔蜗牛(bradley)2 天前
EtherCAT DC 分布式时钟同步的 ModelSim 仿真:从帧模板到从站行为建模
人工智能·嵌入式硬件·fpga开发·架构
ALINX技术博客3 天前
8 通道同步采样 ADC!AN706 波形显示实验 【FPGA黑金云课堂】
fpga开发
szxinmai主板定制专家3 天前
RK3568+FPGA+CODESYS异构控制方案:赋能半导体设备与工业自动化升级
人工智能·fpga开发·自动化·rk3576·半导体设备
辰丁电子3 天前
allegro入门教程-菜单栏Logic
fpga开发·pcb设计·pcb工艺·layout·pcb layout
FPGA小徐4 天前
数字IC/FPGA设计基础_ILA原理与使用
fpga开发
FPGA小徐4 天前
FPGA 部署 YOLO 完整指南:从模型量化到 Zynq PS+PL 硬件加速
yolo·fpga开发
dadaobusi4 天前
学习:chiesel,scala
学习·fpga开发·scala