FPGA 独立按键消抖

思路:

状态机的思想,分4个状态:

1.空闲状态,等待按键按下

2.消除抖动状态1,用计数器延时5ms至10ms

3.按键按下

4.消除抖动状态2,用计数器延时5ms至10ms


程序:

module Key_Filter(Clk,Rst_n,Key_in,Key_flag,Key_state);

	input Clk;
	input Rst_n;
	input Key_in;
	
	output reg Key_flag;
	output reg Key_state;
		
	reg [3:0] state;
	reg [19:0] cnt;
	reg en_cnt;
	reg cnt_full;
	
	reg temp0,temp1;
	wire pos_edge,neg_edge;
	
	localparam 
		IDLE 		= 4'b0001,
		FILTER0 	= 4'b0010,
		DOWN		= 4'b0100,
		FILTER1	= 4'b1000;
																
	always@( posedge Clk or negedge Rst_n )
		begin
			if( Rst_n==0 )
				begin
					state <= IDLE;
					Key_flag <= 0;
					Key_state <= 1;
					en_cnt <= 0;
				end
				
			case ( state )
				IDLE:
					begin
						Key_flag <= 0;
						if( neg_edge==1 )
							begin
								state <= FILTER0;
								en_cnt <= 1;
							end
					end
				FILTER0:
					begin
						if( cnt_full==1 )
							begin
								state <= DOWN;
								Key_flag <= 1;
								Key_state <= 0;
								en_cnt <= 0;
							end
						else if( pos_edge==1 )
							begin
								state <= IDLE;
								en_cnt <= 0;
							end	
					end
				DOWN:
					begin
						Key_flag <= 0;
						if( pos_edge==1 )
							begin
								state <= FILTER1;
								en_cnt <= 1;
							end
					end
				FILTER1:
					begin
						if( cnt_full==1 )
							begin
								state <= IDLE;
								Key_flag <= 1;
								Key_state <= 1;
							end
						else if( neg_edge==1 )
							begin
								state <= DOWN;
								en_cnt <= 0;
							end
					end
				default:
					begin
						state <= IDLE;
						Key_flag <= 0;
						Key_state <= 1;
						en_cnt <= 0;
					end
			endcase
		end

	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		temp0 <= 1'b0;
		temp1 <= 1'b0;
	end
	else begin
		temp0 <= Key_in;
		temp1 <= temp0;	
	end

	assign neg_edge = !temp0 & temp1;
	assign pos_edge = temp0 & (!temp1);
		
	always@( posedge Clk or negedge Rst_n )
		begin
			if( Rst_n==0 )
				cnt <= 0;	
			else if( en_cnt==1 )
				cnt <= cnt+1;
			else
				cnt <= 0;
		end
		
	always@( posedge Clk or negedge Rst_n )
		begin
			if( Rst_n==0 )
				cnt_full <= 0;	
			else if( cnt==99_999 )
				cnt_full <= 1;
			else
				cnt_full <= 0;
		end
endmodule 


testbench程序:

`timescale 1ns/1ns
`define clk_period 20

module Key_Filter_tb;

	reg Clk;
	reg Rst_n;
	reg Key_in;
	
	reg [15:0] rand;
	
	wire key_flag;
	wire key_state;
								
	Key_Filter Key_Filter0
	(
	.Clk(Clk),
	.Rst_n(Rst_n),
	.Key_in(Key_in),
	.Key_flag(key_flag),
	.Key_state(key_state)
	);
	
	initial Clk= 1;
	always#(`clk_period/2) Clk = ~Clk;
	
	initial 
		begin
			Rst_n = 0;
			#(`clk_period*10);
			Rst_n = 1;
			#(`clk_period*10 + 1);	
			press_key;
			#10000;
			press_key;
			#10000;
			press_key;
			#10000;
			$stop;
		end

		task press_key;
			begin
				repeat(20)
					begin
						rand = {$random} % 65536 ;
						#rand;
						Key_in = ~Key_in;
					end		
				Key_in = 0;
				#50_000_000;
				
				repeat(20)
					begin
						rand = {$random} % 65536 ;
						#rand;
						Key_in = ~Key_in;
					end
				Key_in = 1;
				#50_000_000;	
			end
		endtask
endmodule 

RTL仿真结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值