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