1摘要:随着数字技术飞速发展,具有防盗报警功能的数字密码锁代替安全性差的机械锁已成为必然的趋势。数字密码锁不但可以用来保管物品,还可以防止越权操作,例如银行自动柜员机、自动售货机、门卡系统等。基于EDA技术设计的电子密码锁,以其价格便宜、安全可靠、使用方便,受到了人们的普遍关注。而以现场可编程逻辑器件(FPGA)为设计载体,以硬件描述语言(VHDE)为主要表达方式,以QuartusⅡ开发软件和KHF-3型CPLD/FPGA实验开发系统为设计工具设计的电子密码锁,由于其能够实现数码输入、数码清除、密码解除、密码更改、密码上锁和密码解除等功能,因此,能够满足社会对安全防盗的要求。◆关键词:FPGA;VHDL;数字密码锁;原理图;VHDL源程序1.设计题目:数字密码锁2.设计要求:设计一个数字密码锁,用户可输入4位的二进制数,连续3次不正确则报警。开锁密码可手动预置,并可进行修改密码,取消报警。3.设计系统的功能要求与分析3.1系统的功能要求本次的设计主要是采用先进的EDA技术,利用QuartusII工作平台和VHDL设计语言的设计。为了更好地满足实际的需要,将4位二进制改为3位十进制。根据系统设计的要求,可以用自顶向下的设计思路设计一个简易的数字密码锁,该锁应在收到3位与规定码相符的十进制数码时打开,使相应的指示灯点亮;若收到的代码与规定的不符或者开锁程序有误,表示错误的指示灯点亮。由于设计的这个密码锁密码位数较少,所以必须给操作的人严格的次数限制。若连续三次没有输对,则表示操作的人不是该锁的使用者。此时报警铃长响,这时只有锁的使用者才能关取消报警。由于开锁密码可手动预置,故可在输入端加多一个按键,在开锁状态下按下此按键后可以进行密码设置和修改密码。3.2系统的功能分析2(1)系统接通电源后处于开锁状态,此时可以通过手动预置三位十进制数密码,再按上锁键将密码锁上锁,通过指示灯显示出上锁状态。(2)开锁密码是3位十进制数,可以通过系统预先设定。开锁时输入密码不足三位或超过三位,又或者密码错误均不能开锁。(3)开锁程序由设计者确定,用户必须严格执行所规定的程序,方可开锁。(4)开锁密码和程序正确,表示密码锁上锁的指示灯熄灭,此时处于开锁状态。(5)系统允许用户在开锁过程中有3次错误,连续输入密码错误或三次以后,报警灯亮而上锁灯也依然在亮,此时必须通过取消报警键解除报警才能进行其他操作。4.设计思路分析与方案选择4.1方案选择:要设计一个数字密码锁,可以有多种实现方法,下面列出其中的两种:方案一:采用键盘扫描的方法扫描键盘输入信号,扫描信号变化的顺序依次为1110—1101—1011—0111—1110……,周而复始。键盘一个数字输入键,每次扫描产生新的按键数据,即采取串行左移输入数据。设计系统由密码锁输入模块、密码锁控制模块和错误报警模块三个部分组成。方案二:直接采用并行输入数据,每一个按键代表一个十进制数。此系统则由密码锁控制模块、计数器I模块、计数器II模块、寄存器模块、比较器模块以及编码器模块六个部分组成。其中,控制模块是核心。经过比较,虽然方案一结构模块少,但程序过于复杂,难于理解和编译,而方案二虽然结构模块多了点,但易于读懂,而且操作过程简单,不易出现错误,故采用方案二设计本系统。4.2设计方案分析根据系统设计要求,系统设计采用自顶向下的设计方法。顶层设计采用原理图设计方式,系统整体组装设计结构图如图(1)所示,它由密码锁控制模块、计数器I模块、计数器II模块、寄存器模块、比较器模块以及编码器模块六个部分组成。3图(1)系统整体组装设计结构图4.2.1编码器部分其共有三个输入和两个输出端口,如图(2)图(2)编码器部分在时钟脉冲信号的作用下,当“en=1”时,表示此时可以输入三个十进制数码,分别对应关系如下:0000000001=0000;0000000010=0001;0000000100=0010;0000001000=0011;0000010000=0100;0000100000=0101;0001000000=0110;0010000000=0111;0100000000=1000;1000000000=c1001。即当“key_in=左边数”时,“code_out=右边数”。而当输入的数码等于系统设置密码时,“ps_i=1”,否则“ps_i=0”。4.2.2计数器I部分其部分有两个输入端和两个输出端,如图(3)输入编码计数器I寄存器比较器控制模块计数器II4图(3)计数器I部分其脉冲信号为编码器的“code_out”的输出数值,|“clr”是清零端,当“clr=1”时“cout=0”;当“clr=0”时,“cnt=cnt+'1'”,若“cnt=10”时,再遇到下一个脉冲信号后则变成“11”,并使“cout=1”,最后将“cnt”的值赋给“addr”输出。4.2.3寄存器部分此部分有5个输入端和一个输出端,如图(4)图(4)寄存器部分寄存器主要用来储存输入的三位十进制数码,即密码。在时钟脉冲下降沿时若“en=1”,则可以输入数据。此时,如果“addr”为when01=ifreg_wr='1'thenm0=data_in;elsedata_out=m0;when10=ifreg_wr='1'thenm1=data_in;elsedata_out=m1;when11=ifreg_wr='1'thenm2=data_in;elsedata_out=m2;whenOTHERS=NULL。4.2.4比较器部分此部分较为简单,其只有两个输入端和一个输出端,如图(5)图(5)比较器部分当从编码器“code_out”端输出的数a与储存在寄存器中的数b相等时,c端输出“1”,否则为“0”。4.2.5计数器II部分此部分也只有两个输入端和一个输出端,如图(6)5图(6)计数器II部分其主要是用来计算连续输入错误的次数。当清零端“clr=1”时计数器II清零,“wro_count”自然也为零;当“clr=0”时,控制器的“cnt_clk2”端的输出信号作为此部分的脉冲信号,遇到上升沿时计数器加1,计到3次时“wro_count”端输出“1”,否则为“0”。4.2.6中心控制部分此部分是整个系统的核心部分,其管脚也甚多,共有10个输入端和7个输出端。如图(7)图(7)中心控制部分在“OUTLOCK”即开锁状态下,“key=0”,上锁指示灯熄灭;在“INLOCK”即安锁状态下,“key=1”,上锁指示灯亮,并且有“code_en=0;cnt_clr=1;reg_wr=0;warn=0”。按下“start”键后,系统可以输入三位十进制密码,再按“enter”键确认,如果密码正确,则开锁,否则“wro_count=1”,连续输错三次,则“warn=1”,系统报警,按下“off_al=1”键则取消报警,而此过程中“key”始终为“1”。5.VHDL源程序5.1底层文件VHDL源程序65.1.1编码器部分libraryieee;useieee.std_logic_1164.all;useieee.std_logic_unsigned.all;useieee.std_logic_arith.all;entitydl_coderisport(clk:instd_logic;en:instd_logic;key_in:instd_logic_vector(9downto0);ps_i:outstd_logic;code_out:outstd_logic_vector(3downto0));enddl_coder;architecturebehaveofdl_coderissignalkey_in_1:std_logic_vector(9downto0);signalkey_in_2:std_logic_vector(9downto0);beginU1:process(clk)beginifrising_edge(clk)thenifen='1'thenifkey_in=0000000000thenkey_in_1=key_in;key_in_2=key_in;elsekey_in_2=key_in_1;key_in_1=key_in;endif;endif;endif;endprocess;ps_i='1'whenkey_in_2/=key_in_1else'0';U2:process(clk)beginifrising_edge(clk)thenifen='1'andkey_in/=000000000thencasekey_iniswhen0000000001=code_out=0000;when0000000010=code_out=0001;when0000000100=code_out=0010;when0000001000=code_out=0011;when0000010000=code_out=0100;7when0000100000=code_out=0101;when0001000000=code_out=0110;when0010000000=code_out=0111;when0100000000=code_out=1000;when1000000000=code_out=1001;whenOTHERS=code_out=0000;endcase;endif;endif;endprocess;endbehave;5.1.3寄存器部分libraryieee;useieee.std_logic_1164.all;useieee.std_logic_unsigned.all;useieee.std_logic_arith.all;entitydl_regisport(clk:instd_logic;reg_wr:instd_logic;en:instd_logic;addr:instd_logic_vector(1downto0);data_in:instd_logic_vector(3downto0);data_out:outstd_logic_vector(3downto0));endentity;architecturebehaveofdl_regissignalm0:std_logic_vector(3downto0);signalm1:std_logic_vector(3downto0);signalm2:std_logic_vector(3downto0);beginprocess(clk)beginiffalling_edge(clk)thenifen='1'thencaseaddriswhen01=ifreg_wr='1'thenm0=data_in;elsedata_out=m0;8endif;when10=ifreg_wr='1'thenm1=data_in;elsedata_out=m1;endif;when11=ifreg_wr='1'thenm2=data_in;elsedata_out=m2;endif;whenOTHERS=NULL;endcase;endif;endif;endprocess;endbehave;5.1.4比较器部分libraryieee;useieee.std_logic_1164.all;useieee.std_logic_unsigned.all;useieee.std_logic_arith.all;entitydl_cmpisport(a:instd_logic_vector(3downto0);b:instd_logic_vector(3downto0);c:outstd_logic);enddl_cmp;architecturebehaveofdl_cmpisbeginc='1'whena=belse'0';endbehave;5.1.5计数器II