本次做的是基于FPGA的电子密码锁设计,先描述一下所实现的功能:该密码锁使用6位十进制密码,密码由开发板上的独立按键输入,有四个按键,一个按键控制系统开始启动,一个控制密码的自增,一个控制密码的自减,另一个用于确认密码输入。由于6位密码是一位一位输入的,所以这个“确认”按键要按六次,每按一次,所输入的数字都会在数码管上显示,并且是左移显示(新输入的数字会占据最低位,旧数字总体左移一位),当密码输入完成后,会判断密码是否正确,如果正确,则绿灯亮。否则,绿灯不亮。(系统开始运行时,红灯亮,用于指示系统的工作)。系统默认的密码可以在代码中修改。
本次设计使用原理图输入方式,采用自顶层向下的设计思想。整体的原理图如下所示:
大致分为按键消抖模块、密码处理模块(核心控制逻辑)、数码管动态显示模块。接下来一一为大家介绍。
按键模块:
本次使用的独立按键实物图如下:
这种按键使用简单,但是有个缺点,就是抖动太大,再使用前要进行消抖处理。关于FPGA对按键进行消抖处理的原理,可以看我的这篇博客:
FPGA项目(3)--按键消抖_嵌入式小李的博客-CSDN博客FPGA按键消抖的原理https://blog.csdn.net/guangali/article/details/130674206?spm=1001.2014.3001.5501
数码管显示模块:
本次使用6位数码管,进行动态显示,将输入的密码时刻显示出来。数码管实物图如下:
本次使用的是共阳极数码管,关于FPGA驱动数码管的具体原理,也可以看我的这篇博客:
FPGA项目(5)--FPGA控制数码管动态显示的原理_fpga数码管显示实验原理_嵌入式小李的博客-CSDN博客FPGA驱动数码管的动态显示https://blog.csdn.net/guangali/article/details/130754726?spm=1001.2014.3001.5501
重点要讲的是输入密码和密码判断的逻辑控制。
首先要定义四个按键,用于控制系统的开始,密码的输入和确认等等。然后要定义两个LED输出,还要定义一个24位宽的输出量,用于将6位十进制密码输出到数码管显示模块进行显示。复位的时候让所有变量都清0,只有当按下开始按键时,系统才开始工作。接下来,结合代码来讲解设计的思路:
Password用于保存初始密码,如果要修改密码,就修改这里。
Key_input用于保存实时输出的密码,例如第一次输入1,这个量就应该是等于24’d000_001,再输入一次2,它就等于24’d000_012,
再把这个变量传入到数码管模块进行显示,就能达到实时显示输入密码的效果。
Num是保存每一次输入的密码,默认值为5.例如第一次输入密码时,num=5,当按下密码自增键(k2时),num=6,再按一次k2,num=7,如果此时按下确认键(k1),那么num的值就会保存到key_input中,表示这是一次有效的密码输入,同时num返回到复位值5。
Confi_times用于保存按下确认按键的次数,如果按下确认按键6次,那么说明密码已经全部输入完成了,此时要进行密码核对,如果密码正确,就亮绿灯。
Flag按键用于标志系统开始运行,当开始键按下(k3),flag就置1,当flag被置1时,系统才开始运行,否则不运行。
Flag相关代码如下:
这部分代码全部给出:
module mima(
input clk,
input rst, //复位 低电平有效
input k0, // -
input k1, // confirm
input k2, // +
input k3, // start
output reg led_red,
output reg led_green,
output [23:0] data //将输入的密码输出到显示模块用于显示
);
parameter password=24'h600417; //设定密码 如要修改密码 则修改这里
reg [23:0] key_input; //用于保存输入的密码
reg [3:0] num; //用于寄存正在从键盘输入的数 默认为5
reg [3:0] confirm_times; //用于记录按下k1的次数
reg flag; //用于标记k3已经按下 即系统已经开始工作
//记录k3已经被按下
always @(posedge clk or negedge rst) begin
if(!rst)
flag<=1'b0;
else if(k3==1'b0)
flag<=1'b1;
else
flag<=flag;
end
//控制密码的输入 判断密码是否正确
always @(posedge clk or negedge rst) begin
if(!rst)
begin
led_green<=1'b0;
led_red<=1'b0;
key_input<=24'd0;
confirm_times<=4'd0;
num<=4'd5; //默认为5
end
else if(flag==1'b1) //如果系统已经开始工作
begin
key_input[3:0]<=num;
led_red<=1'b1; //系统开启时 红灯亮
if(k2==1'b0)
num<=num+4'd1;
else if(k0==1'b0)
num<=num-4'd1;
else if(k1==1'b0)
begin
if(confirm_times>=4'd5) //如果按了6次k1 说明密码全部输入完毕 此时判断密码是否正确
begin
confirm_times<=4'd0; //清0 以便下一次输入密码
if(key_input==password) //密码正确
led_green<=1'b1; //绿灯亮
else
led_green<=1'b0;
end
else //按下k1次数不满6次 说明密码没有输入完 则继续输入
begin
confirm_times<=confirm_times+4'd1;
key_input<=key_input<<4; //一个十进制数占了四位 所以左移四位看起来就是十进制数左移了一位
num<=4'd5; //num恢复为默认值
end
end
end
else
begin
led_green<=led_green;
led_red<=led_red;
key_input<=key_input;
confirm_times<=confirm_times;
num<=num;
end
end
//数据输出
assign data=key_input;
endmodule
相信大家通过我上面的讲解以及代码里面的注释,能够弄懂这个设计!