如下:
/*
按键消抖实验
4个按键分别控制1个led灯点亮和熄灭,时钟频率50MHz,按键按下时为低电平;
*/
module key1(rst_n,clk,key_in,led0,led1,led2,led3);
input rst_n,clk;
input [3:0] key_in;
output led0;
output led1;
output led2;
output led3;
//////////////////////////////////////////////////
/*通过降采样对key的输入做低通滤波
将其高频分量滤除*/
reg[19:0] cnt2;//计数寄存器
reg clke;
always @(posedge clk or negedge rst_n)
begin
if (!rst_n) cnt2<=20'd0;
else if(cnt2==20'h7A120)
begin
cnt2<=20'd0;
clke<=~clke; //通过对CLK 分频输出CLKe作为按键的采样时钟;
end
else
cnt2<= cnt2+1'b1;
end
///////////////////////////////////////////////////////////
//按键检测程序,每次在CLKe下降沿时检测是否有按按键按下;
reg key_e;
always @(posedge clke or negedge rst_n)
begin
if(!rst_n) key_e<=1'b0;
else if(key_in!=4'b1111) key_e<=1'b1; //当有按键按下时key_in不等于4'b1111,使能key_e开始延时;
else key_e<=1'b0;
end
wire key_an=key_e&key_r;
////////////////////////////////////////////////////////////
//按键按下后用计数器实现延时约40ms
reg[20:0] cnt;//计数寄存器
reg key_r;
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
cnt<=21'd0;
key_r<=1'b1;
end
else if((cnt==21'h1fffff)&&key_e) //延时约40ms停止计数;
key_r<=1'b0; //控制停止计数
else if(key_an) //延时约40ms停止计数;
cnt <= cnt+1'b1;
else
begin //按键释放后清零cnt计数寄存器和置位计数器控制位key_r,方便下次按键按下时计数;
cnt<=21'd0;
key_r<=1'b1;
end
end
////////////////////////////////////////////////////////////
//当按键按下后延时约40ms读取按键值,当按键未释放时控制只允许读取键值一次
reg[3:0] low_sw;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) low_sw<=4'b1111;
else if((cnt==21'h1fffff)&&key_an)//延时约40ms把按键值锁存到寄存器low_sw中,且每次按下只锁存一次(key_an位控制)
low_sw<=key_in;
elselow_sw<=4'b1111;
end
wire[3:0] key_ctrl=(~low_sw); //键值输出,并且只保持一个CLK时钟周期
//---------------------------------------
//按键按下后对应的LED输出口取反
reg [3:0] key_value;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_value<=4'd0;
else
begin
case(key_ctrl)
4'b0001: key_value[0]<=~key_value[0];
4'b0010: key_value[1]<=~key_value[1];
4'b0100: key_value[2]<=~key_value[2];
4'b1000: key_value[3]<=~key_value[3];
default: ;//瞬时值,保持原状
endcase
end
end
assign led0=key_value[0]?1'b1:1'b0;
assign led1=key_value[1]?1'b1:1'b0;
assign led2=key_value[2]?1'b1:1'b0;
assign led3=key_value[3]?1'b1:1'b0;
endmodule