||
//自己写的一个通过按键,控制数码管显示数据0-99的程序
主要练习:按键状态判断,按键消抖,哪一个按键按下判断,数码管扫描,数码管显示
module test_key3(CLK,RSTn,key_in,SEG_DATA,SEG_SEL);
input CLK;
input RSTn;
input [1:0]key_in;
output [7:0]SEG_DATA;
output [1:0]SEG_SEL;
reg [1:0]key_in_r;
wire [1:0]key_in_or;
//按键消抖
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
key_in_r<=2'b11;
else
key_in_r<=key_in;
end
assign key_in_or=key_in_r^key_in; //用于判断是否有按键变化
parameter T20MS=20'd1000_000; //20MS用于按键消抖
reg [19:0]counter2;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
counter2<=20'd0;
else if(counter2==T20MS || key_in_or) //计时满20ms或者有按键变化时counter2清零
counter2<=20'd0;
else
counter2<=counter2+20'b1;
end
reg [1:0]key_s;
reg [1:0]key_s_n;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
key_s<=2'b11;
else
key_s<=key_s_n;
end
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
key_s_n<=2'b11;
else if(counter2==T20MS)
key_s_n<=key_in;
else
key_s_n<=key_s_n; //开始时此处写成了key_s_n<=key_s造成错误
end
parameter T10MS=20'd500_000; //10MS用于数码管扫描
reg [19:0]counter;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
counter<=20'd0;
else if(counter==T10MS)
counter<=20'd0;
else
counter<=counter+20'b1;
end
reg t;
always @(posedge CLK or negedge RSTn) //t用于数码管扫描
begin
if(!RSTn)
t<=1'b0;
else if(counter==T10MS)
t<=~t;
end
reg [6:0]counter1;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
counter1<=7'd0;
else if(counter1==7'd100)
counter1<=7'd0;
else if(counter1==7'd127)
counter1<=7'd99;
else case({key_s,key_s_n}) //{key_s,key_s_n}用于判断是哪一个按键发生了按下或者放开的操作
4'b1110:counter1<=counter1+7'd1;
4'b1101:counter1<=counter1-7'd1;
default:counter1<=counter1;
endcase
end
reg [3:0]ge;
reg [3:0]shi;
always @(posedge CLK or negedge RSTn) //用于计算数据位
begin
if(!RSTn)
begin
ge<=4'b0;
shi<=4'b0;
end
else
begin
ge<=counter1%10;
shi<=counter1/10;
end
end
reg [7:0]ge_SEG_DATA;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
ge_SEG_DATA<=8'hc0;
else case(ge)
4'd0:ge_SEG_DATA<=8'hc0;
4'd1:ge_SEG_DATA<=8'hf9;
4'd2:ge_SEG_DATA<=8'ha4;
4'd3:ge_SEG_DATA<=8'hb0;
4'd4:ge_SEG_DATA<=8'h99;
4'd5:ge_SEG_DATA<=8'h92;
4'd6:ge_SEG_DATA<=8'h82;
4'd7:ge_SEG_DATA<=8'hf8;
4'd8:ge_SEG_DATA<=8'h80;
4'd9:ge_SEG_DATA<=8'h90;
default:ge_SEG_DATA<=8'hff;
endcase
end
reg [7:0]shi_SEG_DATA;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
shi_SEG_DATA<=8'hc0;
else case(shi)
4'd0:shi_SEG_DATA<=8'hc0;
4'd1:shi_SEG_DATA<=8'hf9;
4'd2:shi_SEG_DATA<=8'ha4;
4'd3:shi_SEG_DATA<=8'hb0;
4'd4:shi_SEG_DATA<=8'h99;
4'd5:shi_SEG_DATA<=8'h92;
4'd6:shi_SEG_DATA<=8'h82;
4'd7:shi_SEG_DATA<=8'hf8;
4'd8:shi_SEG_DATA<=8'h80;
4'd9:shi_SEG_DATA<=8'h90;
default:shi_SEG_DATA<=8'hff;
endcase
end
reg [1:0]rSEG_SEL;
reg [7:0]rSEG_DATA;
always @(posedge CLK or negedge RSTn)
begin
if(!RSTn)
begin
rSEG_SEL<=2'b01;
rSEG_DATA<=8'hc0;
end
else case(t)
1'b0:begin
rSEG_SEL<=2'b01;
rSEG_DATA<=ge_SEG_DATA;
end
1'b1:begin
rSEG_SEL<=2'b10;
rSEG_DATA<=shi_SEG_DATA;
end
default:begin
rSEG_SEL<=2'b11;
rSEG_DATA<=8'hff;
end
endcase
end
assign SEG_DATA=rSEG_DATA;
assign SEG_SEL=rSEG_SEL;
endmodule