在上节课学习了按键消抖的原理及解决办法,具体如下:
这节课以按键消抖过程学习了如何绘制状态转移图;
首先明确:上图的按键消抖过程中共有4个状态:
1.空闲态 2.按下消抖状态 3.等待释放状态 4.释放消抖状态
分别用四个圆圈表示这四个状态
下面目标:搞清楚这四个状态之间分别是如何转移的,即转移条件
为了表示方便,做以下意义说明:
20ms计数器 cnt;
下降沿 nedege_key;
上升沿 pedge_key;
1.空闲态:①当检测到下降沿,则跳转到按下消抖状态,并开始20ms计数
②当未检测到下降沿,保持空闲态
2.按下消抖状态:①当在20ms计数期间检测到上升沿,则回到空闲态
②当在20ms计数期间未检测到上升沿,则按键消抖成功,进入等待释放状态
③当在20ms计数期间上升沿和下降沿均未检测到,则保持原状态,继续计数
3.等待释放状态:①当检测到上升沿,则跳转到释放消抖状态,并开始20ms计数
②当未检测到上升沿,则保持原状态
4.释放消抖状态:①当在20ms计数期间检测到下降沿,则回到等待释放状态
②当在20ms计数期间未检测到下降沿,则释放消抖成功,此时输出按键消抖成功信号,进入空闲状态
9月23日更新
上周疯狂摸鱼,今天早上把上周写完的代码进行了初步测试,结果应该是没问题的;
附代码:
module key_filter(clk,restn,key,p_flag,r_flag );
input clk;
input restn;
input key;
output reg p_flag;
output reg r_flag;
reg dff0_key;
reg dff1_key;
parameter IDLE = 0;
parameter p_filter = 1;
parameter wait_rest = 2;
parameter r_filter = 3;
parameter MCNT = 1000000-1; // 20ms
//key是异步输入信号,对其打两拍消除亚稳态
always@(posedge clk)
dff0_key<=key;
always@(posedge clk)
dff1_key<=dff0_key;
reg reg_key;
always@(posedge clk)
reg_key<=dff1_key;
//定义上升沿和下降沿
wire nedge_key;
assign nedge_key = (dff1_key==0)&&(reg_key==1);
wire pedge_key;
assign pedge_key = (dff1_key==1)&&(reg_key==0);
//20ms计数
reg[19:0]cnt;
always@(posedge clk or negedge restn)
if (!restn)
cnt<=0;
else if(cnt==MCNT)
cnt<=0;
else if((state==p_filter)||(state==r_filter))
cnt<=cnt+1;
else cnt<=0;
reg reached_20ms;
always@(posedge clk or negedge restn)
if(!restn)
reached_20ms<=0;
else if(cnt==MCNT)
reached_20ms<=1;
reg [1:0]state;
reg complete;
always@(posedge clk or negedge restn)
if(!restn)
state<=0;
else
case(state)
IDLE:
begin
if(nedge_key)
state<=p_filter;
else
state<=IDLE;
end
p_filter:
begin
if(pedge_key)
state<=IDLE;
else if(reached_20ms)
begin
state<=wait_rest;
p_flag<=1;
end
end
wait_rest:
begin
if(pedge_key)
state<=r_filter;
else
state<=wait_rest;
end
r_filter:
begin
if(nedge_key)
state<=wait_rest;
else if(reached_20ms)
begin state<=IDLE;
r_flag<=1;
complete<=1;
end
end
default
state<=state;
endcase
endmodule
测试代码比较简单,只需要对key输入信号进行多次赋值,控制赋值间隔以达到产生抖动的效果,再通过对比仿真进行验证即可。
今天的分享就到这里啦,继续摸鱼~~