基于VHDL4位电子密码锁的设计.docx
《基于VHDL4位电子密码锁的设计.docx》由会员分享,可在线阅读,更多相关《基于VHDL4位电子密码锁的设计.docx(19页珍藏版)》请在冰豆网上搜索。
基于VHDL4位电子密码锁的设计
理工大学本科实验报告
题目:
基于VHDL4位电子密码锁的设计
课程名称:
数字电路课程设计
学院(系):
电子信息与电气工程
专业:
电子英强
班级:
学生:
学号:
完成日期:
2013.7.8
成绩:
2013年7月08日
题目:
基于VHDL4位电子密码锁的设计
1设计要求
电子密码锁为4位8421BCD码,多于4位,密码只取前4位。
在输入密码错误,给出一个错误信号,有三次输入机会,若三次密码都输入错误,则给出一个报警信号,此后只能由密码管理员取消报警信号。
在输入密码正确的情况下,可以再次设定密码。
每次输入一个密码,将显示在7段数码管上,并依次左移。
每次输入密码的时候,按取消(cancel)键可以取消这次密码的输入,课重新输入4位密码。
2设计分析及系统方案设计
在实验室DE2开发板的条件下,考虑到key键只有4个,可以用switch开关来实现密码输入模块,用switch[9]~switch[0]来实现数字9~0的输入,并通过译码模块将其转化为8421BCD码,由8421BCD码来驱动7段数码管作为密码锁的显示模块。
每按一个键,产生一个上升沿,给4个数码管做时钟,实现没输入一个数左移一位的效果。
为了实现密码输入多于4位,可以构造一个模为4的计数器来控制只取前4位密码。
共有三次输入密码的机会,可以构造一个模为3的计数器来控制。
密码比较模块:
当按下确定键(yes)键,则将输入的密码和置密码进行比较。
密码输入模块:
当输入密码正确时,再输入密码,利用重置密码键(set_psw)直接将其赋值给置的密码psw即可实现。
LED显示模块,用来显示密码输入的正确与否。
若输入密码与置密码一致,则锁打开,输出一个高电平给LEDG,绿灯亮,密码错误则输出一个高电平给LEDR,红灯亮。
综合上述分析,本系统的硬件部分主要由密码锁输入译码模块、密码锁显示模块、密码锁控制模块、密码比较和重置模块和LED显示模块五个部分组成。
密码锁输入译码
密码锁显示模块
密码锁比较和重置
LED显示模块
密码锁控制模块
3系统以及模块硬件电路设计
说明:
1.密码锁显示模块:
段数码管是电子开发过程中常用的输出显示设备。
在本设计中使用的是4个四位一体、共阳极型七段数码管。
其单个静态数码管如右图所示。
2.密码输入和译码模块:
用switch[9]~[0]实现数字9到0的输入。
分频器
密码锁输入和译码
start
reset
Out0
Out1
q(4downto0)
clkClk_in
yes
Correct
Out_error
alarm
密码比较和重置
Out_q(15downto0)
Psw(15downto0)
Set_psw
DE2开发板上使用的元件的管脚编号如下:
端口名
FPGA管脚
说明
alarm
pin_af23
报警信号,红灯亮
cancel
pin_v1
取消密码输入
clk
pin_n2
50MHz时钟
correct
pin_ae22
密码正确,绿灯亮
num[0]
pin_n25
输入数字0到9
num[1]
pin_n26
num[2]
pin_p25
num[3]
pin_ae14
num[4]
pin_af14
num[5]
pin_ad13
num[6]
pin_ac13
num[7]
pin_c13
num[8]
pin_b13
num[9]
pin_a13
out0[0]
pin_af10
u0数码管
out0[1]
pin_ab12
out0[2]
pin_ac12
out0[3]
pin_ad11
out0[4]
pin_ae11
out0[5]
pin_v14
out0[6]
pin_v13
out1[0]
pin_v20
u1数码管
out1[1]
pin_v21
out1[2]
pin_w21
out1[3]
pin_y22
out1[4]
pin_aa24
out1[5]
pin_aa23
out1[6]
pin_ab24
out2[0]
pin_ab23
u2数码管
out2[1]
pin_v22
out2[2]
pin_ac25
out2[3]
pin_ac26
out2[4]
pin_ab26
out2[5]
pin_ab25
out2[6]
pin_y24
out3[0]
pin_y23
u3数码管
out3[1]
pin_aa25
out3[2]
pin_aa26
out3[3]
pin_y26
out3[4]
pin_y25
out3[5]
pin_u22
out3[6]
pin_w24
out_error
pin_ae23
密码错,红灯亮
reset
pin_v2
管理员权限,为0时取消报警信号
set_psw
pin_n23
设置密码
start
pin_u4
开始输入密码信号
yes
pin_g26
确定信号
4系统的VHDL设计
说明
1.分频模块,即做一个模5000的计数器,从而将50MHz的时钟转化为10000Hz的时钟。
2.密码锁输入和译码,显示模块。
switch[9]~switch[0]模拟数字9~0的输入,例如switch[9]为高电平,而其他为低电平,则通过程序译码为9,同时产生一个clock时钟上升沿,由于人操作的时间必定大于0.00001s(即10000Hz的时钟周期),所以在下次按键是,clock已经回到低电平,此后再按键clock又产生一个上升沿。
由此构造的clock时钟可以为左移寄存器当时钟。
3.密码显示模块:
switch改变一次,即每输入一个数,译码产生一个四位的BCD码,来驱动数码管。
并随着clock上升沿,依次左移显示。
4.密码比较和重置模块:
在输入了4位密码后,16位BCD码已经保存在out_q里,通过与置密码比较即可。
数码管的真值表(0代表亮,1代表不亮)
0
1
2
3
4
5
6
0000
0
0
0
0
0
0
1
0001
1
0
0
1
1
1
1
0010
0
0
1
0
0
1
0
0011
0
0
0
0
1
1
0
0100
1
0
0
1
1
0
0
0101
0
1
0
0
1
0
0
0110
0
1
0
0
0
0
0
0111
0
0
0
1
1
1
1
1000
0
0
0
0
0
0
0
1001
0
0
0
0
1
0
0
VHDL源代码
.主程序coded_lock代码:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitycoded_lockis
port(clk:
instd_logic;
start:
instd_logic;
reset:
instd_logic;
num:
instd_logic_vector(9downto0);
out3,out2,out1,out0:
outstd_logic_vector(6downto0);
correct:
bufferstd_logic;
yes:
instd_logic;
--admin:
instd_logic;
set_psw:
std_logic;
alarm:
outstd_logic;
cancel:
instd_logic;
out_error:
bufferstd_logic);
end;
architecturebehaveofcoded_lockis
--*******************************************************************
componentdecoderis--显示译码器的元件例化
port(qq:
instd_logic_vector(3downto0);
result:
outstd_logic_vector(6downto0));
endcomponent;
--*******************************************************************
signalout_q:
std_logic_vector(15downto0):
="11111";
--out_q为4位密码锁的8421BCD码
signalq:
std_logic_vector(3downto0);
--输入一个9~0的数字,q为其8421BCD码
signalclock:
std_logic:
='0';
--每按一次键,clock输出一个上升沿
signalcounter:
integerrange0to2:
=0;
--模为3的计数器
signalt4:
integerrange0to4:
=0;
--模为5的计数器
signalenable:
std_logic:
='1';
--当输错3次密码,则此使能端为0,使无法译码
signalpsw:
std_logic_vector(15downto0):
="10110";
--默认密码为9876
signalclk_in:
std_logic;
--5000分频之后的时钟
begin
--*******************************************************************process(clk_in,start,reset,enable)
begin
ifreset='0'then
clock<='0';
elsifrising_edge(clk_in)then
ifstart='1'andenable='1'then
casenumis--按个键,clock来一个上升沿
when"1000000000"=>q<="1001";clock<='1';
when"0100000000"=>q<="1000";clock<='1';
when"0010000000"=>q<="0111";clock<='1';
when"0001000000"=>q<="0110";clock<='1';
when"0000100000"=>q<="0101";clock<='1';
when"0000010000"=>q<="0100";clock<='1';
when"0000001000"=>q<="0011";clock<='1';
when"0000000100"=>q<="0010";clock<='1';
when"0000000010"=>q<="0001";clock<='1';
when"0000000001"=>q<="0000";clock<='1';
whenothers=>q<="1111";clock<='0';
endcase;
elsenull;
endif;
endif;
endprocess;
--*****************************************************************
--左移进程,按下一个按键则clock输出一个高电平,显示译码器左移
process(clock,yes,start,reset,cancel)
begin
ifreset='0'then
correct<='0';
out_error<='0';
counter<=0;
enable<='1';
alarm<='0';
out_q<="11111";
elsifcancel='1'then
correct<='0';
out_error<='0';
out_q<="00000";
cnt4<=0;--使计数器清零,重新开始译码
elsifstart='0'then
cnt4<=0;
out_q<="00000";
else
ifrising_edge(clock)then
ift4=4then
null;
else
out_q<=out_q(11downto0)&q;
cnt4<=cnt4+1;
endif;
endif;
iffalling_edge(yes)then
ifout_q=pswthen
correct<='1';
out_error<='0';
alarm<='0';
elsifcounter=2then
correct<='0';
out_error<='1';
alarm<='1';
enable<='0';
else
correct<='0';
out_error<='1';
alarm<='0';
counter<=counter+1;
endif;
endif;
endif;
endprocess;
--*******************************************************************
process(correct,set_psw)--重新设置密码的进程
begin
iffalling_edge(set_psw)then
ifcorrect='1'then--输入密码正确才可以重新设置密码
psw<=out_q;
endif;
endif;
endprocess;
--***************************************************************
--分频模块:
将50Mz的时钟分频为10000Hz
process(clk)
variabletem:
integerrange0to4999;
begin
ifrising_edge(clk)then
iftem=4999then
clk_in<='1';
tem:
=0;
else
tem:
=tem+1;
clk_in<='0';
endif;
endif;
endprocess;
--*******************************************************************u3:
componentdecoderportmap(qq=>out_q(15downto12),result=>out3);
u2:
componentdecoderportmap(qq=>out_q(11downto8),result=>out2);
u1:
componentdecoderportmap(qq=>out_q(7downto4),result=>out1);
u0:
componentdecoderportmap(qq=>out_q(3downto0),result=>out0);
endbehave;
.decoder代码:
libraryieee;
useieee.std_logic_1164.all;
entitydecoderis
port(qq:
instd_logic_vector(3downto0);
result:
outstd_logic_vector(6downto0));
end;
architectureregofdecoderis
begin
process(qq)
begin
caseqqis
when"0000"=>result<="1000000";
when"0001"=>result<="1111001";
when"0010"=>result<="0100100";
when"0011"=>result<="0110000";
when"0100"=>result<="0011001";
when"0101"=>result<="0010010";
when"0110"=>result<="0000010";
when"0111"=>result<="1111000";
when"1000"=>result<="0000000";
when"1001"=>result<="0010000";
whenothers=>result<="1111111";
endcase;
endprocess;
endreg;
5结论以及结果说明
计算机平台为window764bit旗舰版,软件调试环境为QuartusⅡ6.0.使用的硬件芯片为EP2C35F672C6.
下面试各个模块的仿真图:
图1
图1显示了密码输入和显示模块所实现的功能。
当输入9,8,7,6,5五位密码时,数码管只显示前4位,即为“1000000”,“1111001”,“0100100”,“0110000”。
由仿真图可知,输入一个密码,在4个数码管上依次左移。
图2
图2显示了密码若输错3次,则有个报警信号,即alarm为高电平。
此时只有管理员将reset置于低电平,才能解除报警信号,即为是alarm为低电平。
(默认密码为9876,上面的仿真图输入的密码依次为8765,9776,5432)
图3
图3显示了密码锁密码重置模块实现的功能。
密码锁置的密码为9876,当输入9876并yes给一个下降沿时,correct输出为高电平,此时在输入密码为5432,set_psw给一个下降沿,将5432设为新的密码。
再输入9876,out_error为到电平,只有输入5432,correct才为高电平。
图4
图4显示了cancel键的功能:
按下cancel键(即cancel为高电平),取消此次密码的输入,将4个数码管清零。
结果说明:
这次密码锁的设计过程表明,用VHDL可以快速、灵活地设计出符合要求的密码锁控制器,而且操作简单。
可以实现密码输入、密码校验、密码设置和更改等功能。
设计过程能够在设计完成后在QuartusⅡ环境下进行电路的模拟仿真,反馈结果可以验证程序设计的可行性与可靠性。
本密码锁控制器设置的是4位密码,在系统复位后,输入4位的密码串,并在4个7段数码管上依次左移。
若输入多于4位,密码只取前4位。
输入完后,按下确定键,如果密码与置密码一致,则开锁,否则继续输入,如果输入的密码3次都是错误的,则系统报警,此时只有管理员能使报警声停止。
同时,密码锁还具有密码修改功能,只有密码输入正确的情况下才能修改密码,符合实际生活中的情况。
在设计VHDL程序的过程中,怎么实现每按一次键,数码管的数据左移一次成了这次程序的重点,后来在老师的点拨之下,才明白了要自己构建一个CLOCK时钟。
在经过了一遍遍修改程序,编译,查错,一个模块一个模块的仿真,确定这一部分达到要求之后,再加入另外的功能。
总而言之,本次设计实现了预期的功能。
参考文献
[1]王兢,王洪玉主编《数字电路与系统》.电子工业,2008.
[2]KennethL.Short著,乔庐峰等译《VHDL大学实用教程》,电子工业,2011.