一、按键状态
按键未按下时:空闲态,FPGA的引脚通过上拉电阻置为高电平。
按键按下时:FPGA的引脚接地,变为低电平。
**在按键按下和释放的过程中:**会出现一段时间的抖动,可以通过示波器观察抖动时间,不超过20ms(如果是50M的晶振,就会经过多个时钟周期,前一个时钟是高电平,下一个可能就是低电平,也就是会出现抖动的现象,这是我们不想要的)
IDEL:空闲态
DOWN:按下状态
***消抖原理:***当按键按下时,检测到下降沿进入FILTER,设置FILTER时间(信号抖动的最大时间)为20ms,也就是说20ms内检测到的上升沿下降沿的抖动不计入引脚状态,直到抖动的最后一次一定是下降沿(因为按下是低电平),然后等待20ms时间到来,就认为信号稳定了,后面同理。
下图为时序逻辑图:
**边沿检测:**前一个时刻低电平,后一个时刻高电平,那么就一定有上升沿。
reg1记录前一个时刻的状态,reg0记录后一个时刻的状态。reg0为‘0’时,经取反之后为‘1’,reg1为‘1’时,与门(两者为1,输出才为1)输出为才为‘1’,检测到上升沿。
//2级寄存器,边沿检测
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
key_tmp0 <= 1'b0;
key_tmp1 <= 1'b0;
end
else begin
key_tmp0 <= key_in_a1;
key_tmp1 <= key_tmp0;
end
assign nedge = !key_tmp0 & key_tmp1;
assign pedge = key_tmp0 & (!key_tmp1);
!是逻辑取反,将不是0的数变为0,0110->0
~是按位取反,每一个bit都取反,0110->1001
二、代码
在这里,可以查看状态图。
module key_filter(Rst_n,Clk,key_in,key_flag,key_state);
input Rst_n,Clk,key_in;
output reg key_flag,key_state;//在always@中进行赋值就要加上reg
localparam
IDEL =4'b0001,
FILTER0 =4'b0010,
DOWN =4'b0100,
FILTER1 =4'b1000;
reg [3:0]state; //表示上述的四种状态
//寄存器类型必须放在最前面
reg key_tmp0,key_tmp1; //边沿检测(前一个时刻高电平,下一个时刻低电平,就是出现了下降沿)
reg [19:0]cnt;
reg en_cnt; //使能计数器,检测到下降沿,开始计数
reg cnt_full; //计数满的标志位
wire pedge,nedge