原创 针对独立式按键消抖的verilog硬件描述

2012-7-27 22:32 1188 1 1 分类: FPGA/CPLD

本人是个初学者,在网络上看了一些高手针对独立式按键消抖的verilog建模,为了练手在他们的基础上改编了按键的采样方式,请大家指点!如下:

 

/*
 按键消抖实验
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;
 else low_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

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
1
关闭 站长推荐上一条 /3 下一条