哈工大数字逻辑与数字系统设计大作业(数字密码锁)

哈工大2020数字逻辑大作业

1.设计要求

1.1 主要设计要求

(1)设计一个开锁密码至少为4位数字(或更多)的密码锁。
(2)当开锁按扭开关(可设置8位或更多,其中只有4位有效,其余位为虚设)的输入代码等于所设密码时启动开锁控制电路,并且用绿灯亮、红灯灭表示开锁状态。
(3)从第一个按扭触动后的5秒内若未能将锁打开,则电路自动复位并发出报警信号,同时用绿灯灭、红灯亮表示关锁状态。

1.2附加功能

(1)可以设置密码,在解锁状态下通过设置密码按钮SP设置密码。
(2)五秒计时采用倒计时(即从5s计时到0)的方式,将秒数显示在开发板的七段数码管上。五秒后发出警报(警示灯亮)。
(3)可以清空密码输入,重新输入密码(不中止计时器)。
(4)设置密码及输入密码时,所键入的密码均会显示在开发板的七段数码管上。
(5)输入密码错误、设置密码成功、输入密码成功,均会有相应的提示灯亮。

2.工作原理及系统方框图

2.1工作原理

根据系统功能来分析,可将整个系统分为以下4个主要功能模块。
(1)编码模块:将输入的4位密码分别转换成8421-BCD码;
(2)存储模块:在设置密码后,将密码保存;
(3)比较模块:将之后输入的密码和存储的密码进行比较;
(4)计时模块:主要体现五秒倒计时的功能。
首先通过输入端输入密码,进而通过编码模块将十进制的密码转化成8421-BCD码进行保存,如果是设计密码的状态,则直接将密码保存下来,否则在输入4位密码后调用比较模块,将输入的密码与之前保存的密码进行比较。一旦输入的密码与设置的密码相等,则绿灯亮;否则,会有相应的指示灯闪烁表示输入密码错误。另外,在输入的第一位密码被读取的瞬间,计时模块启动,5s倒计时开始。如果在倒计时期间成功解锁,则立刻中止计时;如果倒计时结束后仍未解锁,则密码锁进入锁死状态,同时警示灯亮起。

2.2系统框图

系统的结构框图如下图所示。
图 1 电子密码锁流程图

3. 各部分模块具体功能及设计思路

3.1编码模块

编码模块的核心功能是将输入的十进制数(0~7)编码为3位二进制数,功能类似于一个8-3编码器,它的主要作用是为其他模块提供数据来源。编码模块的输入和输出都是高电平有效的。

3.2存储模块

通过编码模块,我们已经将输入的十进制数转换成了二进制数。显然,由于需要输入4位密码,也就是4个十进制数,我们就需要保存下4个3位二进制数。我们想通过4个3位寄存器来分别存储这4个3位二进制数。但是,四位密码是依次输入的,这也就意味着4个寄存器是依次工作的,并且一次只能有一个寄存器工作。
这里的依次存储功能可以通过一个4位计数器和一个2-4译码器的组合来实现。计数器负责选择每位数,从 1-4 位计数。为了知道已经输入几位密码而且依次准确地存储,我们将计数器的时钟端脉冲设置为密码输入端按下时产生的上升沿,用来驱动计数器,让计数器从00记到11。进而将计数器的输出端接到译码器的输入端,并且将译码器的输出端分别与4个寄存器的使能端相连接,从而完整实现分别使能四个寄存器,依次存储的功能。
另外,要想使每次密码输入端按下时都产生一个脉冲,我们可以用或门来实现,开始时密码输入端都为低电平,只要有一个高电平输入,输出的时钟信号就是高电平,计数器就向下计一个数。
另外为了便于用户设置以及输入密码,每当用户输入一位密码(无论是设置密码时还是尝试解锁时),均有一个提示灯闪烁一下表示输入成功。与此同时,用户所输入的密码会通过开发板上的七段数码管显示出来,以便于用户操作。

3.3比较模块

比较模块的核心工作是判断输入的密码与存储模块存储的密码是否相同。我们设计了4个3位的数值比较器来实现比较的功能,如果当前输入的3位二进制数与之前保存的数均相等,则输出1(高电平)。因此,当每个比较器的输出端都为1(表示数值相等)时,密码正确。我们将4个输出端用与门连接,当与门输出1时绿灯亮。每输入一位密码,就会产生一个脉冲,从而触发比较器的工作,依次输入四个密码如果都正确,那么密码锁就会打开。
一旦密码正确,绿灯就会亮起,表示解锁成功,与此同时计时器会停止计时,其他的所有指示灯均熄灭。而如果输入的4位密码有误,会有指示灯闪烁以做出提示,此时计时器模块不停止工作。

3.4计时模块

计时模块主要包括分频器、计数器和显示器,能准确通过7段数码管显示秒数,并且能在计时5s后,发出警告(alarm 警示灯亮),且使红灯亮。此时,进入复位状态(清空输入,设置的密码保存),即使输入正确密码也不能再使绿灯亮。
这里的计时5s可以通过计数器和分频器的组合来实现,由于开发板的时钟频率是100Mhz,可以先将它分频100M,然后计数器每计数1次就代表1s,并且通过一个多多译码器在7段数码管上显示对应的秒数。当输入0~7数字中的任何一个(即开始输入密码)时,5秒倒计时开始,此时复位信号is_locked=0(低电平),其他模块均可以正常工作。一旦5s倒计时结束,就把is_locked设置为1(高电平),即进入锁死状态,并且警示灯亮起。

4. 调试过程

4.1 计时器的调试

计时器的主要功能是5s倒计时,并且将秒数显示在七段数码管上。倒计时的功能其实相对容易,只要调整分频参数即可实现。最需要调试的其实是计时器的启动和终止,因为尽管计时器是一个相对独立的模块,它的开始和停止很大程度上受到输入密码的控制。
我们规定,在设置密码的状态下,计时器不会启动;在尝试解锁时,输入第一位密码后,计时器启动;输入密码正确时,计时器中止;倒计时结束后,计时器中止,如不手动复位,则计时器不再启动。
上述功能我们是通过向计时器(timer)模块传递一个start参数进行实现的。首先初始化start<=0。在任何时候,一旦sp== 1(即进入设置密码状态),start保持为0;而一旦密码锁已经上锁,尝试输入密码时,更改start<=1;如果倒计时未停止且解锁成功,便立刻将start赋值为0,停止计时。这三种情况都比较好实现,相对复杂的是最后一种情况,即倒计时结束后,计时器需要立刻中止。因为start是传入timer模块的参数,所以在模块内部是不能给start赋值的,正是这一点造成了这种情况的复杂性。不过由于计时器倒计时结束alarm便会变成高电平,我们可以在主模块内部对alarm的值进行判断,一旦alarm==1,则start<=1。

4.2 设置及输入密码的调试

我最初的设想是只要pw(输入的密码)值改变,并且是有效值,就把输入转为二进制后保存下来。但是这样做存在一个致命的问题——对于一个reg类型的变量,verilog是不允许它在不同的两个always语句块中被赋值的,比如说我设置了一个clr按钮,一旦按下就清空当前输入的密码,那么清空操作触发的信号其实是posedge clr,这个操作改变了暂存密码的几个寄存器的值;而在always @(pw)语句块中,肯定也需要修改这几个寄存器的值,这就产生了矛盾。而如果将这两个always语句块合并,又与预期的功能不符,所以这个设想被否定了。
我在最后的代码里采用的想法是将这几个模块的处理统一放在一个always @(div_clk)语句块中,在语句块里检测sp,clr是否按下,pw是否有效等等。相对于之前的设想,这里对密码输入、clr操作等的检测的灵敏度一定程度上都下降了,但却能保证所有功能的正常实现。这里div_clk是对系统时钟的一个分频,这里分频的目的是便于用户输入密码——如果时钟频率过高,系统可能会一次读入多个密码;而如果频率过低,输入密码、clr、sp操作的效率就会下降。而只要分频合适,就能够兼顾上述功能的实现。以下是分频以及clr操作的部分代码。
图 2 时钟分频部分代码
图 3 clr操作部分代码

4.3 七段数码管显示的调试

七段数码管在开发板的左上方,一共有8组数码管。下图是七段数码管的实物图。
图 4 七段数码管实物图
但是在这8组数码管下方只标出了两组接口(图中较大的矩形框),这表明一次最多使用两个数码管。另外,在调试中我发现如果只对这两组接口进行赋值,七段数码管是不会有任何显示的,这就类似于数码管没有使能。经过更仔细的观察,我发现在每个七段数码管上方都有一个对应的接口(图中较小的蓝色矩形框),可以把这个看做数码管的使能端,只有在对应接口输入高电平数码管才能正常工作。

4.4 各类指示灯的调试

整个系统里有6个指示灯——alarm(警示灯)、red(红灯)、green(绿灯)、work(输入有效)、sp_success(设置密码成功)、fail(输入密码错误)。这些指示灯的设置一方面是便于用户使用,另一方面也是便于调试。
指示灯的调试其实是对不同状态的调试,指示灯不同代表密码锁进入了不同的状态。以下是密码锁的几个主要状态以及对应指示灯的情况:
(1)复位状态:密码锁启动后的状态——只有红灯亮;
(2)设置或输入密码状态:每输入一个有效密码——work灯闪烁一次;
(3)设置密码成功状态:设置密码状态下连续读入4位有效密码——sp_success灯闪烁一次;
(4)输入密码错误状态:尝试解锁时输入的4位密码错误——fail灯闪烁一次;
(5)解锁成功状态——只有绿灯亮;
(6)锁死状态:倒计时结束——alarm灯亮。
在调试过程中,经常出现的问题是在控制相应灯亮起的同时会忽略关闭其他指示灯,这会造成很多指示灯同时亮起,导致对状态辨别的困难。例如,一旦输入密码正确,便会进入解锁状态,绿灯亮起,但如果忘记对其他指示灯操作,很有可能红灯也是亮起状态,这就产生了一个没有规定过的状态。如果这时又按下了sp按钮,绿灯就必须立马熄灭,因为进入了设置密码状态。下面这段代码展示的是在解锁后对指示灯的配置。
图 5 判断解锁部分代码

5. 设计结论

我设计的电子密码锁有8个数字输入端,能存储4位密码,可以设置、修改密码,能够用绿灯亮表示密码输入正确,警示灯亮表示锁死。除了基本的功能外,我设计的电子密码锁还加入了一些对用户进行提示的功能。例如,倒计时和输入的密码均可以通过七段数码管显示出来,用户可以时刻了解到剩余的开锁时间、输入的密码;为了防止用户误输了密码,我还增加了清空密码输入的clr按钮,一旦按下就会清空密码输入;当设置密码成功、尝试输入密码错误时均会有相应指示灯亮起,以提示用户。
在现有基础上,密码锁还可以实现更多的功能。比如增加密码的位数,又比如在设置密码时也可以清空输入,这些都是密码锁可以优化、改进的地方。

6. 设计心得与总结

(1)模块化
将整个系统划分成若干子模块是非常重要的。模块化的过程是对整个问题分析、理解的过程,也有助于理清整个问题的实现思路。尽管我最后的代码并没有完全依照模块的划分去实现,但是总的思路偏差不大。除此之外,模块化还有一个好处在于如果想添加新的功能,只需要在相应模块里修改即可,而无需考虑整个代码。
(2)加注释
在编写一个较为复杂的工程时,及时地添加必要的注释是很重要的。写注释不仅仅是为了让别人看懂你的代码,更重要的是为自己理清思路,也便于后续的修改。对我而言,我不是很擅长变量命名,所以我在每个变量后面都加上了注释,如图所示。
图 6 变量含义注释
这样一来,即使我一时忘记了某个变量的含义,也可以通过查看注释很快回想起来。
而在主程序中,也可以在if语句、case语句后加上注释,标明某段代码的功能。
(3)仿真文件
仿真文件可以帮助我验证某段代码的正确性,但一旦代码过多、输入输出变量个数过多,编写仿真文件反而成了一件麻烦的事情。我采取的方法是只针对子模块编写仿真程序,而不对整个工程编写仿真程序,因为那样做不仅费时费力,而且一旦某个变量出错还难以发现。
仿真文件测试通过也不能完全保证代码的正确性。有的问题只有把程序烧到板子上的时候才能发现。比如七段数码管的问题,如果只看仿真波形图的话,不会有一点问题,但是在板子上一测试就会发现数码管是不亮的,这时候才会发现问题所在。在板子上进行测试的另一个好处就是直观,也更容易发现一些隐藏的问题。比如我的密码锁共有6个指示灯,如果只看仿真波形图,很不直观,也很难发现问题,而在板子上一测试就会发现有些指示灯没控制好。

总结

这次的大作业很好的锻炼了我独立完成整个工程的能力。我收获到的不仅是代码的编写、调试能力的提升,还有自信心的提升。
在代码的编写方面,我体会到了模块化、添加注释的重要性,其实这些都不会花费很多时间,但如果不去做的话就会给后续的调试带去很大的麻烦。而代码的调试也是很有讲究的,在我看来,编写仿真文件、看仿真波形是粗调,可以大致验证代码的正确性;验证通过后再将代码烧录到板子上细调,如果直接烧到板子上调理论上也可以,不过若代码错误较多,是不方便定位错误的。
在自信心方面,这次的大作业对我的自信心是一次很大的提升。刚看到这道题目的时候,我是没有什么思路的。但经过细细分析,将问题逐渐分解,编写子模块的代码,组合代码等一系列过程后,我不但基本上完成了整个电子密码锁程序的编写,而且很有成就感,对于解决类似工程问题的信心增加了。

参考文献

[1] 李建军,胡苗苗.基于FPGA的电子密码锁系统的设计[J].智能计算机与应用,2019(02): 187-188+192.
[2] 熊军洲. 基于FPGA的电子密码锁控制电路设计[J].石家庄职业技术学院学报,2018(06): 11-15.
[3] 王俊博.关于FPGA的电子密码锁系统的设计[J].科学技术创新,2019(26):89-90.
[4] 康浩,叶翔,王建国,鄢梦林,杨斐.基于FPGA的智能电子密码锁的设计[J].湖北理工学院学报,2014(03):45-49.
[5] 肖萌萌.电子密码锁控制电路设计[J].黑龙江科技信息,2017(15):38.

附录

附录一:总体设计图

图 7 总体设计图

附录二:各模块仿真截图

以下为各个模块的仿真结果截图。
图 8 8-3编码器仿真截图
图 9 存储模块仿真截图
图 10 数值比较器仿真截图
图 11 计时模块仿真截图

附录三:组员所做工作说明

所有工作均由本人独立完成。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值