本实验加了简单的防抖功能,模块功能注释写得很详尽
关于防抖,因为我在设计的时候是一直在扫描,如果没有键被按下,就一直输出无效信号。 每次按下键盘按钮后,由于存在抖动,会连续输出多个有效信号,之后又会一直输出无效信号。 寄存器num[4..0]为5’b1_0000时信号无效,为了达到防抖效果,这里对无效信号出现的次数进行计数,注意之所以防抖是因为按下一次会出现多次有效信号,但是这些信号的间隔很短,我们只要第一次出现的有效信号,那么当有效信号间隔很短的时候我们就把他丢掉。即两次有效信号之间的无效信号次数过少时丢掉它。
补充:之所以count_num从1开始计数是为了防止间隔时间过长count_num位数不够又变成0
//Key_module(clk,KEY_R,KEY_C,out,rst);
/*
该模块的功能为:从4*4矩阵键盘输入数值
输出一个32位的数
代替用key拨动开关置数,引脚数不够时很好用
*/
module Key_module(
input clk,
input rst,
//这里加了复位信号,如果不需要复位信号删掉即可
input [3:0] KEY_R,
output reg[3:0] KEY_C = 4'b0111,
output reg[31:0] out= 32'h0000_0000
//注:这里的输出是三十二位的,对应led模块最多可以显示三十二位的二进制数。共八个示数,每个示数四位
//如需要非三十二位的输出,即需要其他位宽的输出,只需要在这里将out的位宽改掉即可,其他部分均不需要改动
//例如需要八位的输出,则需要改为output reg[7:0] out= 8'h00
);
reg[4:0]num = 5'b1_0000;
reg [31:0]count_num = 32'b1;
reg [1:0] cnt = 2'b0;
//根据按钮的列扫描信号和行输入信号判断按钮是否被按下
always @(posedge clk)
begin
if(rst)
out = 32'h0000_0000;
else
begin
cnt = cnt + 1'b1;
case (cnt)
2'b00: KEY_C <= 4'b1110;
2'b01: KEY_C <= 4'b1101;
2'b10: KEY_C <= 4'b1011;
2'b11: KEY_C <= 4'b0111;
endcase
//如果无按钮按下,定义num=16为无效状态
if (KEY_R == 4'b1111)begin
num = 5'd16; end //无按键输入,输出16
else begin
case ({KEY_R, KEY_C})
8'b1011_1110: num = 5'd0;
8'b0111_0111: num = 5'd1;
8'b1011_0111: num = 5'd2;
8'b1101_0111: num = 5'd3;
8'b0111_1011: num = 5'd4;
8'b1011_1011: num = 5'd5;
8'b1101_1011: num = 5'd6;
8'b0111_1101: num = 5'd7;
8'b1011_1101: num = 5'd8;
8'b1101_1101: num = 5'd9;
8'b1110_0111: num = 5'd10;
8'b1110_1011: num = 5'd11;
8'b1110_1101: num = 5'd12;
8'b1110_1110: num = 5'd13;
8'b0111_1110: num = 5'd14;
8'b1101_1110: num = 5'd15;
endcase
end
begin
if(num == 5'b1_0000)
begin
if(count_num == 32'b0)begin
count_num = 32'd100001;end
count_num = count_num + 1'b1;
end
else if(count_num > 32'd100000)
begin
count_num = 32'b1;
//移位
begin
out = out << 4;
out[3:0] = num[3:0];
end
end
end
end
end
endmodule
补充:仿真时将防抖的部分注释掉
这里给出仿真波形图: