小梅哥三段式状态机按键消抖改写

小梅哥三段式状态机按键消抖改写

小梅哥资料中按键消抖部分是用一段式、二段式状态机写的。我用三段式状态机改写了一下,仿真和板载测试通过。
代码记录如下:

module key_filter1(
		input clk,
		input rst_n,
		input key_in,
		output reg key_flag,
		output reg key_state
);
reg key_ina;
reg key_inb;
always@(posedge clk or negedge rst_n)
		if(!rst_n)begin
			key_ina<=1'b0;
			key_inb<=1'b0;
		end
		else begin
			key_ina<=key_in;
			key_inb<=key_ina;
		end
reg key_tempa;
reg key_tempb;
wire nege,pose;
assign nege=key_tempa&(!key_tempb);
assign pose=(!key_tempa)&key_tempb;
always@(posedge clk or negedge rst_n)
		if(!rst_n)begin
			key_tempa<=1'b0;
			key_tempb<=1'b0;
		end
		else begin
			key_tempa<=key_inb;
			key_tempb<=key_tempa;
		end
reg [19:0]cnt;
reg en_cnt;
reg cnt_full;
always@(posedge clk or negedge rst_n)
		if(!rst_n)
		cnt<=20'd0;
		else if(en_cnt)
			cnt<=cnt+1'b1;
		else
			cnt<=20'd0;
always@(posedge clk or negedge rst_n)
		if(!rst_n)
			cnt_full<=1'b0;
		else if(cnt==20'd999999)
			cnt_full<=1'b1;
		else
			cnt_full<=1'b0;
localparam IDLE    =2'd0;
localparam FILTER0 =2'd1;
localparam DOWN    =2'd2;
localparam FILTER1 =2'd3;
reg [1:0] st_next;
reg [1:0] st_cur;
//第一段
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		st_cur<=0;
	else begin
		st_cur<=st_next;
	end
	//第二段:状态转移
always@(*)begin
	case(st_cur)
			IDLE:begin
			     //key_flag<=1'b0;
				  if(nege)begin
						//en_cnt<=1'b1;
						st_next=FILTER0;
				  end
				  else begin
						//en_cnt<=1'b0;
						st_next=IDLE;
				  end
				  end
			FILTER0:begin
					  if(cnt_full)begin
							//en_cnt<=1'b0;
							st_next=DOWN;
							//key_flag<=1'b1;
					  end
					  else if(pose)begin
							st_next=IDLE;
							//en_cnt<=1'b0;
					  end
					  else begin
							st_next=FILTER0;
							//en_cnt<=1'b1;
					  end
					  end
			DOWN:begin
					//key_flag<=1'b0;
					if(pose)begin
						//en_cnt<=1'b1;
						st_next=FILTER1;
					end
					else begin
						//en_cnt<=1'b0;
						st_next=DOWN;
					end
				  end
		   FILTER1:if(cnt_full)begin
							//key_flag<=1'b1;
							//en_cnt<=1'b0;
							st_next=IDLE;
					  end
					  else if(nege)begin
							st_next=DOWN;
							//en_cnt<=1'b0;
					  end
					  else begin
							//en_cnt<=1'b1;
							st_next=FILTER1;
					  end
			default: ;	
	endcase
end
//第三段:输出决策
always@(posedge clk or negedge rst_n)
			if(!rst_n)begin
				//key_flag<=1'b0;
				key_state<=1'b1;
				end
				else begin
						case(st_cur)
						IDLE:begin
									key_flag<=1'b0;
									key_state<=1'b1;
									if(nege)
									en_cnt<=1'b1;
									else
									en_cnt<=1'b0;
							  end
						FILTER0:begin
						         if(cnt_full)begin
									en_cnt<=1'b0;
									key_flag<=1'b1;
									end
									else if(pose)begin
									en_cnt<=1'b0;
									end
									else
									en_cnt<=1'b1;
										
									//key_flag<=1'b0;
									key_state<=1'b1;									
								  end
						DOWN:begin
									key_flag<=1'b0;
									//key_flag<=1'b1;
									key_state<=1'b0;
							      if(pose)begin
									en_cnt<=1'b1;						
									end
									else begin
									en_cnt<=1'b0;						
									end
							  end
					   FILTER1:begin
									//key_flag<=1'b1;
									key_state<=1'b0;
									if(cnt_full)begin
										key_flag<=1'b1;
										en_cnt<=1'b0;							
										end
									else if(nege)begin						
										en_cnt<=1'b0;
									end
									else begin
										en_cnt<=1'b1;							
									end									
								  end
						default:begin
								   //key_flag<=1'b0;
				               key_state<=1'b1;
								  end
						endcase
				end
endmodule

仿真波形:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值