四位按键检测模块, 25Mhz对应时钟周期40ns
按下>20ms才有效, key_in低有效
设计数器,计500_000.
1位按键按下>=20ms标志位flag,由end_cnt拉高,无按键按下则拉低。
`timescale 1ns / 1ns
//4个按键消抖
//25Mhz 对应40ns
module OV7670_KEY(clk,rst_n,key_in,key_vld);
input clk;
input rst_n;
input [3:0] key_in;//低电平有效
output [3:0] key_vld;
reg [3:0] key_vld;
reg [3:0] key_in_1;
reg [3:0] key_in_2;//打2拍
reg [18:0] cnt;//20ms/40ns=0.5e6<2的19次方
wire add_cnt;
wire end_cnt;
reg flag;//按下20ms标志位 1位 无论是哪个按键按下
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_in_1<=4'b1111;
key_in_2<=4'b1111;
end
else begin
key_in_1<=key_in;
key_in_2<=key_in_1;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt<=0;
end
else if (add_cnt) begin
if (end_cnt)
cnt<=0;
else
cnt<=cnt+1;
end
end
assign add_cnt=(key_in_2!==4'b1111)&&(!flag);//有按键按下且未到20ms
assign end_cnt=add_cnt && (cnt==50_0000-1);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
flag<=0;
end
else if (end_cnt) begin
flag<=1;
end
else if (key_in_2==4'b1111) begin//放开了
flag<=0;
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_vld<=4'b0;
end
else if (flag) begin
key_vld<=~key_in_2;
end
else begin
key_vld<=4'b0;
end
end
endmodule
testbench
**`timescale 1ns / 1ns
//
module test_key();
reg clk;
reg rst_n;
reg [3:0] key_in;//低电平有效
wire [3:0] key_vld;
OV7670_KEY test(
.clk(clk),
.rst_n(rst_n),
.key_in(key_in),
.key_vld(key_vld)
);
initial begin
clk=1'b0;
forever #20 clk=~clk;
end
initial begin
rst_n=1'b0;
#50 rst_n=1'b1;
end
initial begin
key_in=4'b1111;
#30_000_000 key_in=4'b0111;
#30_000_000 key_in=4'b1111;
#30_000_000 key_in=4'b1011;
#30_000_000 key_in=4'b1111;
#30_000_000 key_in=4'b1110;
end
endmodule
**