按键消抖设计

项目名称

按键消抖设计

具体要求

独立按键消抖并控制4个led二进制增加显示

设计说明

按键分类比较多,这里主要以普通按键为例进行设计,按键未按下时IO口为高电平,按下时为低电平,当按下或者松开的时候会产生额外的物理抖动。产生抖动的次数与间隔是不确定的,一般情况下单次抖动的总时间会在20ms之内。

一般用软件实现按键消抖,在消抖之前先消除亚稳态,因为按键对FPGA来说是外部信号,先对按键信号进行同步处理,对按键信号寄存两次进行输出,同步到fpga时钟上。设计一个20ms的计数器,对按键消抖进行计数,然后对按键的上升沿与下降沿进行检测,当按下按键时,即出现下降沿,开始计数20ms,计数完成后,如果仍出现下降沿,表明按键消抖未完成继续消抖,否则消抖完成处于按下稳定期,此时如果出现上升沿,继续进行20ms计数,计数完成后,如果仍出现上升沿证明释放消抖未完成,继续消抖,否则按键处于释放稳定期。

按键消抖的状态转移图如下,根据状态转移图进行代码设计。

设计架构 

                

key_flag表示按下稳定标志信号,key_state表示按键状态

                              

代码设计

顶层模块设计

module key_top(
	input				clk,
	input				rst_n,
	input				key_in,
	output [3:0]	led_out
);
wire key_flag,key_state;
key_filter key_filter(
	.	clk(clk),
	.	rst_n(rst_n),
	.	key_in(key_in),
	.		key_flag(key_flag),
	.		key_state(key_state)
);
led  led(
	.clk(clk),
	.rst_n(rst_n),
	.key_flag(key_flag),
	.key_state(key_state),
	.led_out(led_out)
);

endmodule

按键消抖模块

module key_filter(
	input				clk,
	input				rst_n,
	input				key_in,
	output	reg		key_flag,
	output	reg		key_state
);

//异步信号处理
reg key_s0,key_s1;
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		key_s0<=0;
		key_s1<=0;
	end
	else begin
		key_s0<=key_in;
		key_s1<=key_s0;
	end

//上升沿与下降沿检测
reg key_in0;
reg key_in1;
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		key_in0<=0;
		key_in1<=0;
	end
	else begin
		key_in0<=key_s1;
		key_in1<=key_in0;
	end
wire nedge=key_in1 && (!key_in0);//下降沿检测
wire podge=(!key_in1) && key_in0;//上升沿检测

//20ms的计数
reg [24:0] cnt;
reg en_cnt;//使能计数
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		cnt<=0;
	end
	else if(en_cnt)begin
		if(cnt<25'd1_000_000-1)
			cnt<=cnt+1'b1;
		else
			cnt<=0;
	end
	else
		cnt<=0;
wire delay_20ms_done=(cnt==25'd1_000_000-1) && (en_cnt);//计满标志信号

//状态机的设计
reg [2:0] state; 
localparam IDLE   =3'd0;
localparam FILTER1=3'd1;
localparam DOWM   =3'd2;
localparam FILTER2=3'd3;
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		key_flag<=0;
		key_state<=1;
		state<=IDLE;
		en_cnt<=0;
	end
	else begin
		case(state)
			IDLE	 :	begin
							if(nedge)begin
								state<=FILTER1;
								en_cnt<=1;
							end
							else
								state<=IDLE;
						end
			FILTER1:	begin
							if(delay_20ms_done)begin
								if(podge)begin
									state<=IDLE;
									en_cnt<=0;
								end
								else begin
									state<=DOWM;
									en_cnt<=0;
									key_flag<=1;
									key_state<=0;
								end
							end
							else
								state<=FILTER1;
						end
			DOWM	 :	begin
							key_flag<=0;
							if(podge)begin
								state<=FILTER2;
								en_cnt<=1;
							end
							else begin
								state<=DOWM;
							end	
						end
			FILTER2:	begin
							if(delay_20ms_done)begin
								if(nedge)begin
									state<=DOWM;
									en_cnt<=0;
								end
								else begin
									state<=IDLE;
									en_cnt<=0;
									key_state<=1;
								end
							end
							else begin
								state<=FILTER2;
							end
								
								
						end
			default:	begin
							key_flag<=0;
							key_state<=1;
							state<=IDLE;
							en_cnt<=0;
						end
		endcase
	end
		

endmodule

led显示模块

module led(
	input			clk,
	input			rst_n,
	input			key_flag,
	input			key_state,
	output [3:0]led_out
);
reg [3:0] led_r;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		led_r<=4'b0000;
	else if(key_flag && ~key_state)
		led_r<=led_r+1'b1;
	else
		led_r<=led_r;
assign led_out=~led_r;
endmodule

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值