今天做了一天的键盘消抖,也就是用到了上一篇写的脉冲边沿检测技术,但是在键盘延时方面,时间老是设置的不好,太长或者太短都会使键盘消抖不理想!纠结了一天,参考了特权同学的键盘消抖程序,现在总算做的让自己满意了,接下来看程序吧!

 

//程序功能:键盘控制流水灯,key1控制流水灯的停起;key2控制流水灯左移;key3控制流水灯右移;

module johnson_cout
         (
          sysclk,                        //系统时钟 50MZH;
          rst_b,                         //复位信号,低电平有效;
          key1,                          //三个独立键盘,低电平表示按下;
          key2,
          key3,
          led_out                        //LED灯,低电平点亮;
          );
//------------------------------------//          
input        sysclk;
input        rst_b;
input        key1;                    //key1对应硬件电路图上的SW4 ,控制流水灯的停起;
input        key2;                    //key2对应硬件电路图上的SW5 ,流水灯左移;
input        key3;                    //key3对应硬件电路图上的SW6 ,流水灯右移;


output[3:0]  led_out;
//------------------------------------//
wire         sysclk;
wire         rst_b;
wire         key1;
wire         key2;
wire         key3;
wire[3:0]    led_out;
//-------------------------------------------------------//
reg [2:0]    key_rst;
reg [2:0]    key_rst_r;
always @ (posedge sysclk or negedge rst_b)
  begin
       if(!rst_b)
         key_rst<=3'b111;
       else
         key_rst<={key1,key2,key3};
              
  end
always @ (posedge sysclk or negedge rst_b)
  begin
       if(!rst_b)
         key_rst_r<=3'b111;
       else
         key_rst_r<=key_rst;
              
  end  
wire[2:0] key_change;
assign   key_change=key_rst_r&(~key_rst);  
//-------------------------------------------------------//
reg[23:0]    time_cnt;                                   //

always @ (posedge sysclk or negedge rst_b)
 begin
       if(!rst_b)
         time_cnt<=24'h0;
       else if (key_change)                            //当检测到键盘按下后,time_cnt马上清零,重新开始计数;
          time_cnt<=24'h0;
       else   
         time_cnt<=time_cnt+24'h1;  
 end

//-------------------------------------------------------// 
reg[2:0]    key;                                         
reg[2:0]    key_n;


always @(posedge sysclk or negedge rst_b)
 begin
      if(!rst_b)
         key<=3'b111;
      else if(time_cnt==24'hfffff)                       // 这里的time_cnt不能设的太大20ms(2 *20ns=20ms)就行了;
         key<={key1,key2,key3};                          //如果使time_cnt= 24'hffffff则键盘消抖不理想,手必须在键盘上多停留会 ;
 end

always @(posedge sysclk or negedge rst_b)
 begin
      if(!rst_b)
        key_n<=3'b111;
      else
        key_n<=key;  
 end
 



wire[2:0] key_edge;
assign    key_edge=(~key)&key_n;                       //脉冲下降沿检测;    key      111  111  111  110  111
//---------------------------------------------------------//                key_n         111  111  111  110 110 
reg  stop_start;                                           //控制流水灯停起; ~key     000  000  000  001  000  
always @ (posedge sysclk or negedge rst_b)                 //                key_edge      000  000  001  000
  begin                                                    // 当有键盘按下时,key就会有高电平变成低电平 key_edge就会维持一个时钟周期的高脉冲;                   
       if(!rst_b)                                          
          stop_start<=1'h1;
       else if(key_edge[2])
             stop_start<=~stop_start; 
   
  end 
  
reg  left_right;                                          //控制流水灯:左移/右移;
always @(posedge sysclk or negedge rst_b)
  begin 
         if(!rst_b)
           left_right<=1'h1;
         else
           begin 
             if(key_edge[1])
               left_right<=1'h1;
             if(key_edge[0])
               left_right<=1'h0; 
           end   
  end

 //---------------------------------------------------------// 
 reg[3:0]  led_r;
 
 always @(posedge sysclk or negedge rst_b) 
   begin
       if(!rst_b) 
          led_r<=4'b1110;
       else if((time_cnt==24'hffffff)&&(stop_start))        //这里time_cnt=24’hffffff正好,太小了流水灯扫描的太快了,太大了灯变成静态了;
        begin
          if(left_right)
              led_r<={led_r[2:0],led_r[3]};             //left move
          else 
              led_r<={led_r[0],led_r[3:1]};             //right move
            
        end  
      
       
   end 

assign   led_out=led_r;  
endmodule