||
//在学习Verilog 按键消抖的时候,花费了很多时间来理解这个过程。下面是根据自己的理解,写的一个按键消抖的程序。一开始写的时候,没有定义key_s_r寄存器,想着利用key_s和key_s_n取亦或来判断是否有按键变化,但是key_s_n只有在计时满20ms时才等于key_in,而不是按键变化后开始计时,所以出现错误。而判断哪一路按键发生变化,用的是将key_s和key_s_n取合集,观察每一位的变化来判断是哪一个按键发生变化,以及是发生H2L还是L2H的变化。
module test_key1(rst,clk,led_out,key_in);
input rst;
input clk;
input [3:0]key_in;
output reg [3:0]led_out;
parameter T20MS=21'd1_000_000; //20ms,用于延时消抖
reg [3:0]key_s;
reg [3:0]key_s_n;
reg [3:0]key_s_r;
reg [20:0]timer;
wire [3:0]key_s_or;
//按键消抖
always @ (posedge clk or negedge rst) //将key_in寄存于key_s_r用于判断按键是否发生变化
begin
if(!rst)
key_s_r<=4'b1111;
else
key_s_r<=key_in;
end
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
key_s<=4'b1111;
end
else
key_s<=key_s_n;
end
always @ (*)
begin
if(!rst)
begin
key_s_n<=4'b1111;
end
else
if(timer==T20MS)
key_s_n<=key_s_r;
else
key_s_n<=key_s;
end
wire [7:0]judge;
assign judge={key_s,key_s_n}; //用于判断是哪一个按键发生变化
assign key_s_or=key_s_r^key_in; //检测是否有按键发生变化
always @ (posedge clk or negedge rst)
begin
if(!rst)
timer<=21'd0;
else if(timer==T20MS||key_s_or) //判断时间有没有到、是否有按键变化
begin
timer<=21'd0;
end
else
timer<=timer+1'b1;
end
//led 控制
always @ (posedge clk or negedge rst)
begin
if(!rst)
led_out<=4'b0000;
else case(judge) //根据判断出的按键变化,实现功能
8'b11111110:led_out[0]<=~led_out[0];
8'b11111101:led_out[1]<=~led_out[1];
8'b11111011:led_out[2]<=~led_out[2];
8'b11110111:led_out[3]<=~led_out[3];
default:led_out<=led_out;
endcase
end
endmodule