//说明:还是采用标志方式,通过计数1000_000即为20ms,设定按键输入为低电平时计数,高电平就置为0,当连续计数到1000_000就表明不是抖动,是正常按键的按下,
//所以我们在计数count在最后一个时钟周期时,将key_flag置定为高电平表明有按键按下
//注意:
1、如果我们将count计满又置定为0 的话,那么可能一次按键我们会识别为多次,所以将count就等于最大值不变,直到key_in 变为高电平
2、如果我们让count有最大值时,将key_flag置定为1,本来标志信号是维持一个时钟周期的高电平,这样的不符合要求,所以我们在最大值-1处就判别持续一个周期就好
module key
#(
parameter count_max = 20'd999_999 //便于调试将数值改小点方便观察时序图
)
(
input wire sys_clk,
input wire rst_n,
input wire key_in,
output reg led
);
reg [19:0] count; //20ms计数
reg key_flag;
//if else if else 执行是有顺序的,你要知道先判断什么,后判断什么就好了
always @(posedge sys_clk or negedge rst_n)
if (!rst_n)
count <= 1'b0;
else if (key_in ==1'b1) //按键是低电平表示按下
count <= 1'b0;
else if (count == count_max)
count <=count_max;
else
count <= count+1'b1;
/////////————————————————————————————
always @(posedge sys_clk or negedge rst_n)
if (!rst_n)
key_flag <= 1'b0;
else if (count == count_max-1)
key_flag <=1'b1;
else
key_flag <= 1'b0;
always @(posedge sys_clk or negedge rst_n)
if (!rst_n)
led <=1'b0;
else if (key_flag==1'b1)
led <=~led;
else
led <=led;
endmodule
module vtf_key;
// Inputs
reg sys_clk;
reg rst_n;
reg key_in;
// Outputs
wire led;
reg [8:0] moni_count;
// Instantiate the Unit Under Test (UUT)
key
#(
.count_max(7'd99) //将计数值改到99,便于观测
)
uut (
.sys_clk(sys_clk),
.rst_n(rst_n),
.key_in(key_in),
.led(led)
);
initial begin
// Initialize Inputs
sys_clk = 0;
rst_n = 0;
key_in <= 1'b1;
// Wait 100 ns for global reset to finish
#100;
rst_n <=1;
end
always #10 sys_clk = ~sys_clk;
always@(posedge sys_clk or negedge rst_n)
if (!rst_n)
moni_count<=1'b0;
else if (moni_count == 9'd500)
moni_count <=1'b0;
else
moni_count <=moni_count +1'b1;
always@(posedge sys_clk or negedge rst_n) //设置25个时钟周期为抖动样的高低变换电平接下来
//150个时钟周期为低电平接下来25个时钟周期为抖
//动样高低变换电平 这样一段模拟按下按键
if (!rst_n)
key_in <=1'b1;
else if ((moni_count >=9'd200 &&moni_count <=9'd224)|(moni_count >=9'd376 &&moni_count <=9'd399))
key_in <= {$random} % 2;
else if ((moni_count >= 9'd225) && (moni_count <=9'd375) )
key_in <= 1'b0;
else
key_in <= 1'b1;
endmodule