2.按键消抖的学习
module key_detect(
clk,
Rst_n,
key_in,
key_flag,
key_state
);
input clk,Rst_n;
input key_in;
// output [3:0] led;
output reg key_flag;//按键状态切换标志
output reg key_state;//按键状态标志
reg [3:0]state;
reg [2:0] key_tem;//定义一个寄存器,去存储按键的前一个状态
wire posedge_key;
wire negedge_key;
always@(posedge clk)
key_tem <= {key_tem [1:0],key_in};
assign posedge_key = (key_tem [1] && (!key_tem [2]));
assign negedge_key = ((!key_tem [1]) && key_tem [2]);
此处是完成按键作为一个异步信号的,对其做同步处理,去除亚稳态,并做了判断是上升沿还是下降沿。
亚稳态:当信号发生变化时,处于0与1之间的状态,也就是说,自己的理解,在晶体管中电容的充放电是一个过程,所以0与1之间有一个不定态,当异步信号有效,但还不够稳定时,也就是不满足采稳定信号的建立时间时,时钟有效沿正好到来,则会采到不确定的信号,之后稳定为不定值0或1,为了解决这个问题,这里定义了一个位宽为3的信号key_tem,来存储按键的信号状态。然后经过两个时钟后,做到信号同步,去除亚稳态,再判断先进来的是高电平还是低电平作为是上升沿还是下降沿的基准。
reg cnt_en;
reg [19:0] cnt;//定义一个计数器去测量key的沿是抖动还是真的按下,就是去算时间宽度是否到20ms
//计数使能模块
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
cnt <= 0;
else if(cnt_en)
cnt <= cnt + 1;
else
cnt <= 0;
//计数满标志模块
reg cnt_full;
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
cnt_full <= 1'b0;
else if(cnt == 1_000_000)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
//逻辑消抖模块
localparam
IDLE = 4'b0001,//用了独热编码,降低组合逻辑上的毛刺产生
FILTER0 = 4'b0010,
DOWN = 4'b0100,
FILTER1 = 4'b1000;
always@(posedge clk or negedge Rst_n)
if(!Rst_n) begin
state <= IDLE;
cnt_en <= 1'b0;
key_flag <= 1'b0;
key_state <= 1'b1;
end
else begin
case(state)
IDLE:
begin
key_flag <= 1'b0;
if(negedge_key)begin
cnt_en <= 1;
state <= FILTER0;
end
else
state <= IDLE;
end
FILTER0:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b0;
cnt_en <= 1'b0;
state <= DOWN;
end
else if(posedge_key)begin
state <= IDLE;
cnt_en <= 1'b0;
end
else
state <= FILTER0;
DOWN:
begin
key_flag <= 1'b0;
if(posedge_key)begin
cnt_en <= 1'b1;
state <= FILTER1;
end
else
state <= DOWN;
end
FILTER1:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b1;
cnt_en <= 1'b0;
state <= IDLE;
end
else if(negedge_key)begin
state <= DOWN;
cnt_en <= 1'b0;
end
else
state <= FILTER1;
default:
begin
state <= IDLE;
cnt_en <= 1'b0;
key_flag <= 1'b0;
key_state <= 1'b1;
end
endcase
end
这里用一个状态机去按键消抖,思路就是初始我们的按键是高电平的,当我们检测到下降沿时,让计数器开始计数,如果计数到5ms以上说明这是“真”下降沿,则给按键状态信号和按键改变信号相应的值,若计数器没计数到5ms就检测到了上升沿,认为是抖动,返回继续等下降沿。检测到“真”上升沿同理,就是一个只有四个状态的简单的状态机。