|
module key_shake(Rst_n,key_in,clk,key_flag,key_state);
input Rst_n;
input clk;
input key_in;
output reg key_flag; //按键状态切换标志
output reg key_state; //按键状态标志
localparam
IDEL = 4'b0000,
FILTER0 = 4'b0010,
DOWN = 4'b0100,
FILTER1 = 4'b1000;
reg [19:0]cnt;
reg en_cnt;//使能计数器
reg cnt_full;//计数满标志
reg [3:0]state;
reg key_temp0,key_temp1;
wire pedge,nedge;
always@(posedge clk or negedge Rst_n)
if(!Rst_n)begin
key_temp0<=1'b0;
key_temp1<=1'b0;
end
else begin
key_temp0<=key_in;
key_temp1<=key_temp0;
end
/*检测边沿信号*/
assign nedge =!key_temp0 & key_temp1; //下降沿
assign pedge = key_temp0 & (!key_temp1);//上升沿
//*计数器模块设计*//
/*计数使能模块*/
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'd999_999)
cnt_full<=1'b1;
else
cnt_full<=1'b0;
always@(posedge clk or negedge Rst_n) //所有状态的复位
if(!Rst_n)begin
state <= IDEL;
en_cnt<=1'b0;
key_flag<=1'b0;
key_state<=1'b1;
end
else begin
case(state)
IDEL:
begin
key_flag<=1'b0; //按键按下标志位清零
if(nedge)begin //检测到下降沿,进入FILTER0 状态,计数器开始计数
state<= FILTER0;
en_cnt<=1'b1;
end
else
state <= IDEL; //没有检测到下降沿,返回初始态IDEL
end
FILTER0:
if(cnt_full)begin //如果说计数值达到20ms 并且没有上升沿,认为按键按下
key_flag<=1'b1;
key_state<=1'b0;
en_cnt<=1'b0; //进入DOWN状态,计数器清零
state<= DOWN;
end
else if(pedge)begin
state <= IDEL; //检测到上升沿,返回IDEL
en_cnt<=1'b0;
end
else
state <= FILTER0;
DOWN:
begin
key_flag<=1'b0; //进入down状态后将状态标志位清零
if(pedge)begin //检测到上升沿,进入FILTER1,并开始计数
state<=FILTER1;
en_cnt<=1'b1;
end
else
state <= DOWN; //保持原位
end
FILTER1:
if(cnt_full)begin //计数满20ms后不存在下降沿。将flag。state置1,回到IDEL态,等待下一次按键按下
state<=IDEL;
key_flag<=1'b1;
key_state<=1'b1;
end
else if(nedge)begin// 检测到下降沿,返回到上一状态DOWN,计数器清零
en_cnt<=1'b0;
state<=DOWN;
end
else
state<=FILTER1;
default:begin state <= IDEL;
en_cnt<=1'b0;
key_state <=1'b1;
key_flag <=1'b0;
end
endcase
end
endmodule
//*仿真文件1*/
`timescale 1ns/1ns
`define clock_period 20
module key_shake_tb;
reg clk;
reg Rst_n;
wire key_in;
wire key_flag;
wire key_state;
key_shake shake0 (
.Rst_n(Rst_n),
.key_in(key_in),
.clk(clk),
.key_flag(key_flag),
.key_state(key_state)
);
key_model key_model(.key(key_in));
initial clk=1;
always #(`clock_period/2)clk =~clk;
initial begin
Rst_n=1'b0;
#(`clock_period*10) Rst_n =1'b1;
#(`clock_period*10+1);
end
endmodule
/**仿真文件2*/
`timescale 1ns/1ns
module key_model(key);
output reg key;
reg [15:0]myrand;
initial begin
key= 1'b1;
press_key;
#10000;
press_key;
#10000;
$stop;
end
task press_key; //产生随机函数
begin
repeat(50)begin
myrand ={$random}%65536; //0~65536
#myrand key =~key;
end
key = 0;
#50000000;
repeat(50)begin
myrand ={$random}%65536; //0~65536
#myrand key =~key;
end
key = 1;
#50000000;
end
endtask
endmodule
|
|