基于状态机的设计代码
module key_filter(clk,rst,key,key_p_flag,key_r_flag,key_state);input clk,rst;input key;output reg key_p_flag;output reg key_r_flag;output reg key_state;reg [1:0]r_key; //后面用来判断什么时候pedge,什么时候nedgealways@(posedge clk)r_key<={r_key[0],key}; //位拼接wire pedge_key;assign pedge_key=r_key==2'b01; //识别到key的上升沿wire nedge_key;assign nedge_key=r_key==2'b10; //识别到key的下降沿reg [19:0]cnt;localparam IDLE=0;reg [1:0]state;always@(posedge clk or negedge rst)if(!rst)beginstate<=0;key_r_flag<=0;key_p_flag<=0;cnt<=0;key_state<=1;endelse begin case (state)0:beginkey_r_flag<=0;if(nedge_key)state<=1;elsestate<=0;end1:if((pedge_key)&&(cnt<1000000-1))begincnt<=0;state<=0;end else if(cnt>=1000000-1)begin state<=2;cnt<=0; //给计数器清零,为下一次计数做准备key_p_flag<=1;key_state<=0;endelse beginstate<=1;cnt<=cnt+1;end 2:beginkey_p_flag<=0;if(pedge_key)state<=3;elsestate<=2;end 3:if((nedge_key)&&(cnt<1000000-1))beginstate<=2;state<=0;endelse if(cnt>=1000000-1) beginstate<=0;cnt<=0; //给计数器清零,为下一次计数做准备key_r_flag<=1;key_state<=1;endelse beginstate<=3;cnt<=cnt+1;endendcaseendendmodule
testbench代码
`timescale 1ns / 1psmodule key_filter_tb();reg clk,rst;reg key;wire key_p_flag;wire key_r_flag;wire key_state; key_filter key_filter(clk,rst,key,key_p_flag,key_r_flag,key_state);initial clk=1;always #10 clk=~clk;initial beginrst=0;key=1;#201;rst=1;#3000;key=0;#20000; //20ns,模拟按键抖动key=1;#30000; //30ns,模拟按键抖动key=0;#20000; //20ns,模拟按键抖动key=1;#30000; //30ns,模拟按键抖动key=0;#50000000; //50mskey=1;#20000; //20ns,模拟按键抖动key=0;#30000; //30ns,模拟按键抖动key=1;#20000; //20ns,模拟按键抖动key=0;#30000; //30ns,模拟按键抖动key=1;#50000000; //50ms $stop;end
endmodule
仿真验证波形
在按下抖动的过程中,key在抖动但是p_flag并没有出现高脉冲 ,直到稳定了20ms后p_flag出现了高脉冲。
并只稳定了一个时钟周期后就变为0
R_flag也是同样
在输出端再加入一个key_state,模拟什么时候确定按键按下,什么时候按键释放