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