FPGA系统性学习笔记连载_Day17【状态机:实现按键消抖】 【verilog仿真】篇
本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。
连载《叁芯智能fpga设计与研发-第17天》 【状态机:实现按键消抖】 【verilog仿真】
原创作者:紫枫术河 转载请联系群主授权,否则追究责任
本篇文章,采用状态机,来实现按键检测及消抖,本程序做成一个标准模块,模块输入clk,rst_n,key,flag_down,flag_up。
可以供工程使用,模块同时输出按键按下、抬起的标准信号,具体怎么用看工程需要。
一、代码实现
代码语言:javascript复制module FSM_key_fiter(
input clk,
input rst_n,
input key,
output reg flag_up,
output reg flag_down
);
parameter WAIT_DOWN = 3'b000;
parameter DOWN = 3'b001;
parameter DOWN_Fiter = 3'b010;
parameter WAIT_UP = 3'b011;
parameter UP = 3'b100;
parameter UP_Fiter = 3'b101;
parameter OK = 3'b110;
parameter T_10ms = 500_000;
reg [19:0] cnt;
reg [2:0] status;
wire flag_up_r;
wire flag_down_r;
edge_check edge_check_inst(
.signal (key),
.clk (clk),
.rst_n (rst_n),
.flag_up (flag_up_r),
.flag_down (flag_down_r)
);
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
status <= WAIT_DOWN;
cnt <= 20'd0;
flag_down <= 1'b0;
flag_up <= 1'b0;
end
else
begin
case(status)
WAIT_DOWN:
begin
if(flag_down_r)
status <= DOWN;
else
status <= WAIT_DOWN;
end
DOWN:
begin
cnt <= 20'd0;
status <= DOWN_Fiter;
end
DOWN_Fiter:
begin
if(flag_down_r || flag_up_r)
status <= DOWN;
else
begin
if(cnt == T_10ms-1)
begin
//flag拉高,产生脉冲
flag_down <= 1'b1;
cnt <= 20'd0;
status <= WAIT_UP;
end
else
cnt <= cnt 1'b1;
end
end
WAIT_UP:
begin
//flag拉低,只产生一个clk的脉冲
flag_down <= 1'b0;
if(flag_up_r)
status <= UP;
else
status <= WAIT_UP;
end
UP:
begin
cnt <= 20'd0;
status <= UP_Fiter;
end
UP_Fiter:
begin
if(flag_down_r || flag_up_r)
status <= UP;
else
begin
if(cnt == T_10ms-1)
begin
//flag拉高,产生脉冲
flag_up <= 1'b1;
cnt <= 20'd0;
status <= OK;
end
else
cnt <= cnt 1'b1;
end
end
OK:
begin
//flag拉低,产生脉冲
flag_up <= 1'b0;
status <= WAIT_DOWN;
end
default:
begin
status <= WAIT_DOWN;
flag_down <= 1'b0;
flag_up <= 1'b0;
cnt <= 20'd0;
end
endcase
end
end
endmodule
二、仿真代码
代码语言:javascript复制`timescale 1ns/1ps
module FSM_key_fiter_tb;
reg signal;
reg clk;
reg rst_n;
wire flag_down;
wire flag_up;
FSM_key_fiter FSM_key_fiter_inst(
.clk (clk),
.rst_n (rst_n),
.key (signal),
.flag_down (flag_down),
.flag_up (flag_up)
);
always #10 clk = ~clk;
initial begin
clk = 0;
signal = 1;
rst_n = 0;
#20;
rst_n = 1;
//模拟按下
signal = 1;
//延时15ms
#15000000;
repeat(50)
begin
//抖动
signal = 0;
#10;
signal = 1;
#15;
//抖动
signal = 0;
#17;
signal = 1;
#26;
end
signal = 0;
//延时15ms
#15000000;
//模拟抬起
signal = 1;
repeat(50)
begin
//抖动
signal = 0;
#10;
signal = 1;
#15;
//抖动
signal = 0;
#17;
signal = 1;
#26;
end
signal = 1;
#500;
//延时15ms
#15000000;
$stop;
end
endmodule
三、仿真波形
从图中看,我们检测按键有效,且产生的脉冲的判断条件是完整的按下和抬起全过程。