//功能:按键代表0~9 10个数字,按下按键led显示按下数字的二进制码,同时数码管加上该数字
/*
****************************************************************************/ /*--思路:让行分别为0111 1011 1101 1110 然后检测列的状态 如果列的状态为0111 1011 1101 1110 通过矩阵按键 来让led显示二进数字*/ //错误1 行输入不稳定 错的话经常显示第一行的数据,但是第一行数据稳定 解决:消抖 //错误2:按键按下的是上一个状态 解决:松手检测 //错误三:延时20ms计算错误 //通过20ms检测一次电平的方法消抖效果更好 //当第一个按键按下的时候 temp没有加数字 但是value已经发生变换了 数码管比按键落后一个状态 // if(FLAG&&!STATE)//有键按下且完成消抖原来是这个鬼,如果是按键检测的话rcol,rROW的值还没有刷新 //错误四:第三四行,刷新数据满不如12行稳定 可能是时间比较长 将20ms消抖改成10ms消抖 module juzhenbutton ( CLK,RSTn,ROW,COL,LED,SMG1,SMG2 ); input CLK; input RSTn; input [3:0]COL; output[3:0]ROW; output [9:0]LED; output[6:0]SMG1; output[6:0]SMG2; /*************************/ reg[2:0]State;//多个状态 reg[3:0]ROW;//寄存器放行 四个寄存器 reg[9:0]Value;//储存按键码 reg FLAG;//如果FLAG为1的话表示按键按下 reg [3:0]rCOL;//储存列 reg [3:0]rROW;//储存行键值 reg CLK_10MS; parameter _0=8\'hc0,_1=8\'hf9,_2=8\'ha4,_3=8\'hb0,_4=8\'h99, _5=8\'h92,_6=8\'h82,_7=8\'hf8,_8=8\'h80,_9=8\'h90; /******************************************/ reg[19:0]Count; parameter TIME_10MS=20\'d499_999; always@(posedge CLK or negedge RSTn) if(!RSTn) begin CLK_10MS<=1\'b0; Count<=20\'d0; end else if(Count==TIME_10MS) begin CLK_10MS<=~CLK_10MS; Count<=20\'d0; end else Count<=Count+1\'b1; /**********************************/ //定时器20ms /* reg[19:0]Count1; reg isCount;//是否开始计数 //parameter TIME_20MS=20\'d999_999; always@(posedge CLK or negedge RSTn) if(!RSTn) Count1<=20\'d0; else if(Count1==TIME_20MS) Count1<=20\'d0; else if(isCount) Count1<=Count1+1\'b1; else if(!isCount) Count1<=20\'b0; /*********************************/ /*-----检测各行-----*/ always@(posedge CLK_10MS or negedge RSTn) if(!RSTn) begin State<=3\'d0; ROW<=4\'b0000; //isCount<=1\'b0; rROW<=4\'b1111; rCOL<=4\'b1111; end else case(State) 3\'d0: begin FLAG<=1\'b0; ROW<=4\'b0000; if(COL!=4\'b1111)//说明有键按下 begin //if(Count==TIME_20MS) //begin FLAG<=1\'b1;//有键按下 State<=3\'d1;//检测第一行 ROW<=4\'b1110; //isCount<=1\'b0; // end // else isCount<=1\'b1; end else State<=3\'d0; end 3\'d1: begin if(COL!=4\'b1111&&ROW==4\'b1110)//第一行有键按下 begin State<=3\'d5; //FLAG<=1\'b1; // rCOL<=COL;//锁存键值 // rROW<=ROW; end else begin State<=3\'d2;//检测第二行 ROW<=4\'b1101; end end 3\'d2: begin if(COL!=4\'b1111&&ROW==4\'b1101)//第二行有键按下 begin State<=3\'d5; // FLAG<=1\'b1; //rCOL<=COL; //rROW<=ROW; end else begin State<=3\'d3; ROW<=4\'b1011; end end 3\'d3: begin if(COL!=4\'b1111&&ROW==4\'b1011)//第三行有键按下 begin State<=3\'d5; // FLAG<=1\'b1; //rCOL<=COL; //rROW<=ROW; end else begin State<=3\'d4; ROW<=4\'b0111; end end 3\'d4: begin if(COL!=4\'b1111&&ROW==4\'b0111)//第四行有键按下 begin State<=3\'d5; //FLAG<=1\'b1; //rCOL<=COL; // rROW<=ROW; end else State<=3\'d0; end 3\'d5: if(COL!=4\'b1111) begin rCOL<=COL;//锁存键值 rROW<=ROW; FLAG<=1\'b1;//有键按下 State<=3\'d5;//FLAG保持一个时钟/ end else begin State<=3\'d0; FLAG<=1\'b0; end default: begin FLAG<=1\'b0; State<=1\'b0; end endcase reg[7:0] TEMP;//要计算到99 //reg[7:0]TEMP1;//储存TEMP reg STATE;//flag的前一状态 always@(posedge CLK or negedge RSTn) if(!RSTn) begin Value<=10\'d0; TEMP<=7\'d0; // TEMP1<=7\'d0; STATE<=1\'b0; end else if(TEMP>=7\'d100)//如果大于等于100清0 TEMP<=7\'d0; else begin STATE<=FLAG; //把flag的状态赋值给STATE if(!FLAG&&STATE)//有键按下且完成消抖 begin begin //STATE_Value<=1\'b1; case({rCOL,rROW}) 8\'b11101110:begin Value<=4\'d0; TEMP<=TEMP+1\'b0; end 8\'b11011110:begin Value<=4\'d1; TEMP<=TEMP+1\'b1; end 8\'b10111110:begin Value<=4\'d2; TEMP<=TEMP+2\'d2; end 8\'b01111110:begin Value<=4\'d3; TEMP<=TEMP+2\'d3; end 8\'b11101101:begin Value<=4\'d4; TEMP<=TEMP+3\'d4; end 8\'b11011101:begin Value<=4\'d5; TEMP<=TEMP+3\'d5; end 8\'b10111101:begin Value<=4\'d6; TEMP<=TEMP+3\'d6; end 8\'b01111101:begin Value<=4\'d7; TEMP<=TEMP+3\'d7; end 8\'b11101011:begin Value<=4\'d8; TEMP<=TEMP+4\'d8; end 8\'b11011011:begin Value<=4\'d9; TEMP<=TEMP+4\'d9; end 8\'b10111011:begin Value<=4\'d10;TEMP<=TEMP+4\'d10;end 8\'b01111011:begin Value<=4\'d11;TEMP<=TEMP+4\'d11;end 8\'b11100111:begin Value<=4\'d12;TEMP<=TEMP+4\'d12;end 8\'b11010111:begin Value<=4\'d13;TEMP<=TEMP+4\'d13;end 8\'b10110111:begin Value<=4\'d14;TEMP<=TEMP+4\'d14;end 8\'b01110111:begin Value<=4\'d15;TEMP<=TEMP+4\'d15;end default: begin Value<=4\'d0;TEMP<=TEMP ; end endcase //TEMP1<=TEMP; end //else isCount<=1\'b1;//开始计数 end end reg[7:0] rSMG1; always@(posedge CLK or negedge RSTn) if(!RSTn) rSMG1[7:0]<=8\'hff; else case(TEMP%10) 4\'d0:rSMG1<=_0; 4\'d1:rSMG1<=_1; 4\'d2:rSMG1<=_2; 4\'d3:rSMG1<=_3; 4\'d4:rSMG1<=_4; 4\'d5:rSMG1<=_5; 4\'d6:rSMG1<=_6; 4\'d7:rSMG1<=_7; 4\'d8:rSMG1<=_8; 4\'d9:rSMG1<=_9; default:rSMG1<=_0; endcase reg[7:0] rSMG2; always@(posedge CLK or negedge RSTn) if(!RSTn) rSMG2[7:0]<=8\'hff; else case(TEMP/10) 4\'d0:rSMG2<=_0; 4\'d1:rSMG2<=_1; 4\'d2:rSMG2<=_2; 4\'d3:rSMG2<=_3; 4\'d4:rSMG2<=_4; 4\'d5:rSMG2<=_5; 4\'d6:rSMG2<=_6; 4\'d7:rSMG2<=_7; 4\'d8:rSMG2<=_8; 4\'d9:rSMG2<=_9; default:rSMG2<=_0; endcase /********************************/ assign LED=Value; assign SMG1=rSMG1; assign SMG2=rSMG2; endmodule

 

版权声明:本文为bixiaopengblog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/bixiaopengblog/p/5949751.html