按键消抖 verilog FPGA 基础练习5

按键消抖 verilog FPGA 基础练习5

发现问题,用技术解决问题。兴趣是自己的源动力 !

目录

    • 按键消抖 verilog FPGA 基础练习5
  • 前言
  • 一、消抖
    • 1.1 消抖问题
      • 1.1.1 功能代码
      • 1.1.2 tb仿真代码
      • 1.1.3 仿真结果
  • 总结

前言

按键消的的练习主要是对计数器使用的一个巩固,核心就是任何一个需要使用计数器的地方,先建立一个always语句去计数,然后根据条件去判断什么时候清零,什么时候保持等等功能。消抖功能的实现,消抖的本质就是通过计数器的计数来避免前抖和后抖,核心方法就是只要有高电平,计数器就清零


一、消抖

注意理解下面两句话,就可以处理任何消抖了

  • 消抖的本质就是通过计数器的计数来避免前抖和后抖:
  • 核心方法就是只要有高电平,计数器就清零

1.1 消抖问题

设定抖动参数为10个clk 后抖也是10个clk,稳定时间为50clk

1.1.1 功能代码

module key_filter
#(
parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(
input wire sys_clk , //系统时钟50MHz
input wire sys_rst_n , //全局复位
input wire key_in , //按键输入信号

output reg key_flag //key_flag为1时表示消抖后检测到按键被按下
//key_flag为0时表示没有检测到按键被按下
);

//************************************************
// 消抖的本质就是通过计数器的计数来避免前抖和后抖:
// 核心方法就是只要有高电平,计数器就清零
//************************************************

// 计数器计数,CNT_MAX 决定按键抖动的容忍时间

reg [19:0] cnt_filter;

always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0)
		cnt_filter <= 20'b0 ;		
	else if(key_in == 1'b1) // 确定计数器归零条件
		cnt_filter <= 20'b0 ;	
	else if(key_in == 1'b0 & (cnt_filter == CNT_MAX))  // 确定保持条件
		cnt_filter <= cnt_filter;			              
	else
		cnt_filter <= cnt_filter + 1; 	// 确定递增条件。这里考虑计数器在下一个按键来之前需要保持,否则会一直计数
end

// 拉高flag
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0)
		key_flag <= 1'b0 ;	
	else if(cnt_filter == CNT_MAX - 1'b1)  // 确定拉高条件,这里使用CNT_MAX - 1'b1表示只拉高一个周期
		key_flag <= 1'b1 ;
	else 
		key_flag <= 1'b0 ;
end
endmodule

1.1.2 tb仿真代码

`timescale 1ns/1ns
module tb_top;

reg sys_clk;
reg sys_rst_n;
reg [19:0] cnt_sim;
reg key_in;
wire key_flag;
initial begin
	sys_clk    = 1'b0;
	sys_rst_n  = 1'b0;
	#50;
	sys_rst_n  = 1'b1;
end

always #10 sys_clk = ~sys_clk;


// 设定抖动参数为10个clk 后抖也是10个clk,稳定时间为50clk,则可以用计数器来模拟
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0)
		cnt_sim <= 8'b0;
	else if(cnt_sim == 20'd70 -1'b1) //设置计数器清零
		cnt_sim <= 8'b0;
	else 
		cnt_sim <=  cnt_sim + 1'b1;
end

// 只要是要依据计数器来操作的,就先给单独给一个计数器来计数,然后依据这个计数器来判定动作
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0)
		key_in <= 1'b0;
// 前后10clk 来随机一个key_in
	else if(cnt_sim <= 20'd10 | cnt_sim >=20'd60) 
		key_in <= ($random) % 2;
	else 
		key_in <= 1'b0;
end


key_filter
#(
 .CNT_MAX(20'd20) //计数器计数最大值
)
u0_key_filter
(
.sys_clk 			(sys_clk 	), //系统时钟50MHz
.sys_rst_n 			(sys_rst_n 	), //全局复位
.key_in 			(key_in 	), //按键输入信号
.key_flag			(key_flag	) //key_flag为1时表示消抖后检测到按键被按下
									//key_flag为0时表示没有检测到按键被按下
);


endmodule

1.1.3 仿真结果

在这里插入图片描述图1 前抖

在这里插入图片描述图2 后抖

总结

  • 核心思想:很多功能的实现,都是需要一个计数器(计数器需要考虑递增条件、归零条件或者保持条件),然后通过对计数器值的判别,实现其特有的功能或者操作
  • 知识点总结:
    1. 消抖的核心要点是什么?
    2. 计数器使用的核心是什么?
    3. 当一个功能需要使用计数器时?如何进行核计数器进行交互或者判决?
  • 欢迎一起交流学习,如有错误之处,还请各位指正。

参考资料

[1] FPGA系列教学

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值