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