设计算是完成了。
我们再来进行一些扩展的思考。
有些时候,我们需要输出的是一个按键脉冲,表示按下了一次键。
而我们之前的程序仅仅是做了一个单纯的10ms滤波,也就是要求按键按下、释放均需经过10ms持续保持时间再确认。
我们对之前的程序稍微修改一下,就可以达到这个目的。
也就是在滤波结果的下降沿输出一个对应的脉冲即可,类似于flag标志信号,我们这里称之为key_flag,即按键标志信号。
我们新建一个key_flag.v文件。
module key_flag (clk, rst_n, key_n, key_out);
input clk, rst_n;
input key_n;
output key_out;
reg click_n;
parameter MASK_TIME = 500_000; // 10ms/20ns = 500_000, for checking key hold time
reg cnt;
reg state;
localparam s0 = 1'b0,
s1 = 1'b1;
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
cnt <= 0;
click_n <= 1;
state <= s0;
end
else
begin
case (state)
s0 : begin
if (key_n)
begin
cnt <= 0;
click_n <= 1;
state <= s0;
end
else
begin
if (cnt < MASK_TIME - 1)
begin
cnt <= cnt + 19'b1;
state <= s0;
end
else
begin
cnt <= 0;
click_n <= 0;
state <= s1;
end
end
end
s1 : begin
if (!key_n)
begin
cnt <= 0;
click_n <= 0;
state <= s1;
end
else
begin
if (cnt < MASK_TIME - 1)
begin
cnt <= cnt + 19'b1;
state <= s1;
end
else
begin
cnt <= 0;
click_n <= 1;
state <= s0;
end
end
end
default : state <= s0;
endcase
end
end
reg click_r_n;
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
click_r_n <= 1;
else
click_r_n <= click_n;
end
assign key_out = click_r_n & ~click_n;
endmodule
本帖最后由 lcytms 于 2016-11-4 17:53 编辑
将key_flag.v模块设置为顶层模块,进行分析综合检查。
新建Testbench文件key_flag_tb.v。
`timescale 1ns/1ps
module key_flag_tb;
reg clk, rst_n;
reg key_n;
wire key_out;
key_flag #(.MASK_TIME(5))
dut (.clk(clk), .rst_n(rst_n), .key_n(key_n), .key_out(key_out));
initial
begin
clk = 1;
rst_n = 0;
key_n = 1;
#200.1
rst_n = 1;
#200
key_n = 0;
#10
key_n = 1;
#20
key_n = 0;
#80
key_n = 1;
#200
key_n = 0;
#400 //key hold time is long enough
key_n = 1;
#10
key_n = 0;
#20
key_n = 1;
#80
key_n = 0;
#200
key_n = 1;
#200 //key hold time is long enough
#200 $stop;
end
always #10 clk = ~clk;
endmodule
设置好仿真。
仿真结果如下。
看到了key_out是一个脉冲,代表有一次按键按下。
好了,今天的课程就讲到这里。
通过今天的课程,我们学习了单独按键消抖的基本原理,并对单独按键消抖电路进行了建模和仿真检查。
希望大家建立对单独按键消抖的理解,并熟练运用Verilog语言编写驱动逻辑。
更复杂的知识和技巧我们将逐步通过后面的课程展现给大家。
课程到此结束,谢谢大家的关注!
FPGA初级课程第六讲 单独按键消抖 感谢群主分享:funk: 6
页:
1
[2]