按键消抖的学习

2.按键消抖的学习

module key_detect(
	clk,
	Rst_n,
	key_in,
	key_flag,
	key_state
);
	input clk,Rst_n;
	input key_in;
	
//	output [3:0] led;
	output reg key_flag;//按键状态切换标志
	output reg key_state;//按键状态标志
	
	reg [3:0]state;
	reg [2:0] key_tem;//定义一个寄存器,去存储按键的前一个状态
	wire posedge_key;
	wire negedge_key;
	
	always@(posedge clk)
			key_tem <= {key_tem [1:0],key_in};
	assign posedge_key = (key_tem [1] && (!key_tem [2]));
	assign negedge_key = ((!key_tem [1]) && key_tem [2]);

此处是完成按键作为一个异步信号的,对其做同步处理,去除亚稳态,并做了判断是上升沿还是下降沿。
亚稳态:当信号发生变化时,处于0与1之间的状态,也就是说,自己的理解,在晶体管中电容的充放电是一个过程,所以0与1之间有一个不定态,当异步信号有效,但还不够稳定时,也就是不满足采稳定信号的建立时间时,时钟有效沿正好到来,则会采到不确定的信号,之后稳定为不定值0或1,为了解决这个问题,这里定义了一个位宽为3的信号key_tem,来存储按键的信号状态。然后经过两个时钟后,做到信号同步,去除亚稳态,再判断先进来的是高电平还是低电平作为是上升沿还是下降沿的基准。

reg cnt_en;	
	reg [19:0] cnt;//定义一个计数器去测量key的沿是抖动还是真的按下,就是去算时间宽度是否到20ms
	//计数使能模块
	always@(posedge clk or negedge Rst_n)
		if(!Rst_n)
			cnt <= 0;
		else if(cnt_en)
			cnt <= cnt + 1;
		else
			cnt <= 0;
	//计数满标志模块
	reg cnt_full;
	
	always@(posedge clk or negedge Rst_n)
		if(!Rst_n)
			cnt_full <= 1'b0;
		else if(cnt == 1_000_000)	
			cnt_full <= 1'b1;
		else
			cnt_full <= 1'b0;
	//逻辑消抖模块
	localparam  
		IDLE = 4'b0001,//用了独热编码,降低组合逻辑上的毛刺产生
		FILTER0 = 4'b0010,
		DOWN = 4'b0100,
		FILTER1 = 4'b1000;
	
	always@(posedge clk or negedge Rst_n)
		if(!Rst_n) begin
			state <= IDLE;
			cnt_en <= 1'b0;
			key_flag <= 1'b0;
			key_state <= 1'b1;
		end
		else begin
			case(state)	
				IDLE: 
					begin
						key_flag <= 1'b0;
						if(negedge_key)begin
								cnt_en <= 1;
								state <= FILTER0;
							end
						else 
							state <= IDLE;
					end
				FILTER0: 
					if(cnt_full)begin
						key_flag <= 1'b1;
						key_state <= 1'b0;
						cnt_en <= 1'b0;
						state <= DOWN;
						end
					else if(posedge_key)begin
						state <= IDLE;
						cnt_en <= 1'b0;
					end
					else
						state <= FILTER0;
				DOWN:
					begin
						key_flag <= 1'b0;
						if(posedge_key)begin
								cnt_en <= 1'b1;
								state <= FILTER1;
							end
						else 
							state <= DOWN;
					end
				FILTER1:
					if(cnt_full)begin
							key_flag <= 1'b1;
							key_state <= 1'b1; 
							cnt_en <= 1'b0;
							state <= IDLE;							
						end
					else if(negedge_key)begin
						state <= DOWN;
						cnt_en <= 1'b0;
					end
					else
						state <= FILTER1;
				default: 
					begin
						state <= IDLE;
						cnt_en <= 1'b0;
						key_flag <= 1'b0;
						key_state <= 1'b1;
					end
			endcase
		end

这里用一个状态机去按键消抖,思路就是初始我们的按键是高电平的,当我们检测到下降沿时,让计数器开始计数,如果计数到5ms以上说明这是“真”下降沿,则给按键状态信号和按键改变信号相应的值,若计数器没计数到5ms就检测到了上升沿,认为是抖动,返回继续等下降沿。检测到“真”上升沿同理,就是一个只有四个状态的简单的状态机。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值