4x4键盘扫描消抖4位数码管显示4位流水灯蜂鸣器驱动v代码
刚学FPGA,用Verilog HDL写了一个4x4键盘扫描带消抖,4位数码管动态扫描显示,4位流水灯和蜂鸣器驱动的实验代码,分享给初学FPGA的电工。自认为代码风格较好,代码思路清析,用REDLOGIC II EP1C6开发板调试通过。希望各位路过的FPGA大牛不吝赐教。
module ledbeepkeypad (
input wire clk, //时钟50MHz
input wire rst, //复位信号
input wire keypadi, //键盘行输入(外接上拉电阻)
output reg keypado, //键盘列输出扫描(低电平)
output reg ledd, //数码管数据接口
output reg ledc, //数码管位控制接口
output reg beep, //蜂鸣器
output reg led //4个指示灯
);
reg keypad = 8'h00; //保存键盘扫描码
reg keycode = 5'h10; //当前按键编码,5'h0d表示编号为h0d的按键按下,5'h1x表示没有按键按下或非法按键组合
reg keystate1 = 4'hf; //每列上一次检测到的按键状态,用于消抖
reg keystate2 = 4'hf; //每列上上一次检测到的按键状态,用于消抖
reg keypressdone = 1'b1; //按键已处理标志,用于消抖,0表示按键未处理,1到示按键已处理
reg ledmsk = 5'h0; //数码管驱动位图索引
reg lednum = 16'h1234; //4位数码管显示数据BCD码
reg dotpint = 2'd0; //小数点后有几位数据
reg cnt = 28'd0; //28位记数器,用于时序控制
always @ (posedge clk)//记数器向上记数
cnt = cnt + 1'b1;
always @ (*)//4个指示灯按记数规律亮灭
led = cnt;
always @ (posedge cnt) begin //4x4键盘扫描,(2^19)*4/50000=42ms扫描一遍
case (keypado) //列扫描输出低电平
4'b0111: keypado <= 4'b1011; //非阻塞赋值
4'b1011: keypado <= 4'b1101;
4'b1101: keypado <= 4'b1110;
default: keypado <= 4'b0111;
endcase
keypad = keypadi; //行检测
keypad = keypado; //完整键盘扫描码
case (keypad) //按键译码
8'b11101110: keycode = 5'hD; //阻塞赋值
8'b11101101: keycode = 5'hE;
8'b11101011: keycode = 5'hF;
8'b11100111: keycode = 5'h0;
8'b11011110: keycode = 5'hC;
8'b11011101: keycode = 5'h3;
8'b11011011: keycode = 5'h2;
8'b11010111: keycode = 5'h1;
8'b10111110: keycode = 5'hB;
8'b10111101: keycode = 5'h6;
8'b10111011: keycode = 5'h5;
8'b10110111: keycode = 5'h4;
8'b01111110: keycode = 5'hA;
8'b01111101: keycode = 5'h9;
8'b01111011: keycode = 5'h8;
8'b01110111: keycode = 5'h7;
default: keycode = 5'h10; //没有按键或非法按键组合
endcase
if(rst) begin //按键处理
case (keypado) //保存每列按键状态
default: keystate1 = keycode;
4'b1011: keystate1 = keycode;
4'b1101: keystate1 = keycode;
4'b1110: keystate1 = keycode;
endcase
keystate2 = keystate1; //保存上一次每列按键状态
if(keystate1 == keystate2) begin //2次检测按键状态相同
if(keystate1 == 4'b1111) begin //按键释放
keypressdone = 1'b0; //确认按键释放
beep = 1'b0; //蜂鸣器停
end
else begin //按键按下
if(keypressdone) ; //按键已处理
else begin //按键未处理则处理当前按键
lednum = lednum << 4; //数码管前3位显示前3次按键值
lednum = keycode; //数码管第4位显示当前按键值
keypressdone = 1'b1; //按键处理完毕
beep = 1'b1; //蜂鸣器响
end
end
end
else ; //两次检测按键状态不同
end
else ; //复位时不处理按键
end
always @ (negedge cnt) begin //动态扫描4位数码管显示,刷新频率50000000/((2^17)*4)=95Hz
case (ledc) //数码管位扫描
default: begin
ledc = 4'b1000;
ledmsk = lednum;
ledd = dotpint == 2'd3 ? 1'b1 : 1'b0; //小数点驱动
end
4'b1000: begin
ledc = 4'b0100;
ledmsk = lednum;
ledd = dotpint == 2'd2 ? 1'b1 : 1'b0; //小数点驱动
end
4'b0100: begin
ledc = 4'b0010;
ledmsk = lednum;
ledd = dotpint == 2'd1 ? 1'b1 : 1'b0; //小数点驱动
end
4'b0010: begin
ledc = 4'b0001;
ledmsk = lednum;
ledd = 1'b0; //末位小数点不显示
end
endcase
case (ledmsk) //数码管掩码数据输出
5'h0: ledd = 7'b0111111;
5'h1: ledd = 7'b0000110;
5'h2: ledd = 7'b1011011;
5'h3: ledd = 7'b1001111;
5'h4: ledd = 7'b1100110;
5'h5: ledd = 7'b1101101;
5'h6: ledd = 7'b1111101;
5'h7: ledd = 7'b0000111;
5'h8: ledd = 7'b1111111;
5'h9: ledd = 7'b1101111;
5'hA: ledd = 7'b1110111;
5'hB: ledd = 7'b1111100;
5'hC: ledd = 7'b0111001;
5'hD: ledd = 7'b1011110;
5'hE: ledd = 7'b1111001;
5'hF: ledd = 7'b1110001;
default: ledd = 7'b0000000;
endcase
end
endmodule
上传附件 请教两个问题:
1、怎么设置FPGA端口内部上拉?
2、怎么设置FPGA端口开漏输出?
希望路过的大牛不吝赐教。 Altera FPGA管脚弱上拉电阻的软件设置方法
1.打开Assignments Editer;
2.选择I/O features;
3.查找需要上拉的端口;
4.选择需要上拉的端口;
5.选择上拉方式;
6.在value中选择ON,Enable选择YES;
7.保存然后再重新编译,设置完成。在.qsf中可以看到对应的端口已经上拉。
PIN_NAME引脚设置弱上拉:set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to PIN_NAME
PIN_NAME引脚关闭弱上拉:set_instance_assignment -name WEAK_PULL_UP_RESISTOR OFF -to PIN_NAME 开漏输出设置与上拉设置方法基本相同,选项为Auto Open-Drain Pins
页:
[1]