//功能:按键代表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