@数字系统课程设计
VHDL密码锁控制器
VHDL语言设计的密码锁控制器,模拟仿真平台为vivado 2018。(学生:慌慌和张张)
使用器材:Nexys4 DDR Artix-7 FPGA
设计软件:Vivado2018
设计要求
(1)设计一个4位密码锁,用户拨动相应的开关进入输入密码状态,输入4位密码,按下确定键后,若密码正确,锁打开,若密码错误,将提示密码错误,要求重新输入,三次输入都错误,将发出报警信号。
(2)用户输入密码时,在按下确定键之前,可以通过按退格键修正,每按一次退格键消除一位密码。
(3)报警后,只有管理员作相应的处理(专用按键)才能停止报警。
(4)管理员可以通过设置(专用按键)更改密码。
(5)如果没有预置密码,密码缺省为“0000”。
(6)正确开锁后,用户处理完毕后,按下确定键,系统回到等待状态。
(7)系统操作过程中,只要密码锁没有打开,如果10秒没有对系统操作,系统回到等待状态。
(8)系统操作过程中,如果密码锁已经打开,如果20秒没有对系统操作,系统自动上锁,回到等待状态。
功能描述
(1)用户密码初始值为“1234”;
(2)管理员密码初始值为“0000”;
(3)非报警状态下,只要密码锁没有打开,如果10秒没有对系统操作,系统回到等待状态。
(4)非报警状态下,密码锁已经打开,如果20秒没有对系统操作,系统回到等待状态
(5)操作分为用户状态和管理员状态
(6)等待状态默认为用户状态
用户状态:
(1)设计一个4位密码锁,用户拨动相应开关进入输入密码状态,输入4位密码,通过数码管显示出来,按下确定键后,若密码正确,锁打开,数码管显示“HELLO”,若密码错误,数码管显示“ERROR”要求重新输入,三次输入都错误,将发出报警信号(10个LED灯闪烁)等待管理员操作。
(2)开锁后,用户可按相应键关锁,回到等待状态,也按下相应键进入修改密码状态,输入四位新密码,按下确认键则修改密码成功。
管理员状态:
(1)报警状态下,管理员按下相应键进入输密码状态,输入四位管理员密码,按下确定键进行验证(错误则提示“ERROR”重新输入,没有次数限制)。
(2)验证通过后,管理员可以按下管理员键停止报警,也可以按相应键修改用户密码,输入4位密码后按确认键则修改密码成功。
设计思路
根据自顶向下的设计方法,先确定系统顶层实体的功能设计,按功能划分成若干模块,系统主要由6个模块构成,分别是控制模块,分频模块,显示模块,计数器模块,输入模块,编码模块,然后由6个模块实现具体功能。其中控制模块主要由状态机构成。然后先编写test_bench文件,在仿真平台上运行代码,然后再下载到FPGA板子中,进行硬件的调试。
状态图:
接口设置:
状态机输入:共有16个按键输入,10个按键输入0~9,6个按键分别为重置,管理员键,用户键,改密码建,确定键,返回键;
状态机输出:16个LED灯,四位数码管输出。
时钟信号100MHz
状态描述
等待状态 S
等待输入第一位密码状态
等待输入第二位密码状态:S2
等待输入第三位密码状态:S3
等待输入第四位密码状态:S4
密码比较状态:S5
开锁状态:Sopen
管理员状态:Sadmin
报警状态:Salarm
错误状态:Serror
程序设计
密码锁显示模块:给七段数码管显示信号赋值
process(clk)
begin
case data is
when "0000"=>seg7<="10000001"; --数码管显示内容为0
when "0001"=>seg7<="11001111"; --数码管显示内容为1
when "0010"=>seg7<="10010010"; --数码管显示内容为2
when "0011"=>seg7<="10000110"; --数码管显示内容为3
when "0100"=>seg7<="11001100"; --数码管显示内容为4
when "0101"=>seg7<="10100100"; --数码管显示内容为5
when "0110"=>seg7<="10100000"; --数码管显示内容为6
when "0111"=>seg7<="10001111"; --数码管显示内容为7
when "1000"=>seg7<="10000000"; --数码管显示内容为8
when "1001"=>seg7<="10000101"; --数码管显示内容为9
when "1010"=>seg7<="11001000"; --数码管显示内容为H
when "1011"=>seg7<="10110000"; --数码管显示内容为E
When "1100"=>seg7<="11110001"; --数码管显示内容为L
when "1101"=>seg7<="10001000"; --数码管显示内容为R
When others =>seg7<="11111110"; --数码管显示内容为-
end case;
end process;
给数码管引脚赋值,进行显示
process(clk_in1) --数码管显示模块,固定显示4位密码
variable n,m,x:std_logic_vector(2 downto 0):="000";
begin
if(clk_in1'event and clk_in1= '1') then --1khz的时钟信号触发,无法改变
if (state = sopen) then --显示开锁信号
case m is
when "000"=> segselect8<="01111111";data<="1010"; --显示H
when "001" =>segselect8<="10111111";data<="1011"; --显示E
when "010" =>segselect8<="11011111";data<="1100"; --显示L
when "011" =>segselect8<="11101111";data<="1100"; --显示L
when "100" =>segselect8<="11110111";data<="0000"; --显示O
when others =>segselect8<="11111111";data<="1111";
end case;
m := m+1;
if(m="101") then
m:="000";
end if; --显示错误
elsif (state = serror or state = salarming)then
case x is
when "000"=> segselect8<="01111111";data<="1011"; --显示E
when "001" =>segselect8<="10111111";data<="1101"; --显示R
when "010" =>segselect8<="11011111";data<="1101"; --显示R
when "011" =>segselect8<="11101111";data<="0000"; --显示O
when "100" =>segselect8<="11110111";data<="1101"; --显示R
when others =>segselect8<="11111111";data<="1111";
end case;
x := x+1;
If(x="101") then
x:="000";
end if; --显示开锁信号
else
case n is
when "000"=> segselect8<="01111111";data<=code3; --显示第一位密码
when "001" =>segselect8<="10111111";data<=code2; --显示第二位密码
when "010" =>segselect8<="11011111";data<=code1; --显示第三位密码
when "011" =>segselect8<="11101111";data<=code0; --显示第四位密码
when others =>segselect8<="11111111";data<="1111";
end case;
n := n+1;
if(n="100") then
n:="000";
end if;
end if;
end if;
end process;
密码锁分频计数模块:
时钟分频信号2,产生1000HZ的时钟信号,用于数码管的显示
PROCESS(clk)
Variable count:integer range 0 to 100000; --
BEGIN
IF (clk'event AND clk='1') THEN --时钟上升沿
IF(count<=49999) THEN
clk_in1<='1';
count := count +1;
elsif(count=100000) then
count:=0;
else
count := count +1;
clk_in1<= '0';
End if;
End if;
End process; --时钟分频信号验证成功
系统仿真波形
输入初始密码“1234”,从上述波形可以看到yonghumima代表正确用户密码,out_code代表输入的密码,这里可以看到密码输入成功,密码锁打开。
修改输入密码,首先输入初始密码“1234”,开锁后按下改密码键,将密码修改为“2345”;可以看到yonghumima用户密码从“1234”变为“2345”,表示修改密码成功。
Data[3~0]代表输入的4位密码,从图中也可以看到每次输入的密码。
仿真波形为:
硬件测试
正确输入密码“1234”,数码管显示:
按下确定键,验证密码正确,数码显示“HELLO”表示开锁成功。
密码输入错误,数码管显示“ERROR”提示输入密码错误:
三次密码输入错误,10个LED灯闪烁报警:
分析与总结
1.多时钟问题:
在写代码过程,在控制模块的进程使用了多个时钟信号来满足不同的功能,例子如下:在主进程中同时使用了判断条件(clk’event and clk = ‘1’)和(back’EVENT and back=‘1’),逻辑上并无错误,仿真也可以正常进行,并无错误,但是在综合布线时报错,
解决方案:
经查证,这个错误主要是由于一个process不可以由两个时钟触发,会产生竞争冒险,综合时会报错,因此可以给clk以外的时钟信号,增加一级状态,利用信号的值在进程结束以后才会更新的特点,利用寄存器来判断信号是否出现上升沿,例如(back’EVENT and back=‘1’)可以改写为
Process(clk)
Begin
If(clk’event and clk = ‘1’) then
Myback<=back;
If(Myback = ‘0’and back = ‘1’) then
……
End if;
End if;
这样就可以将back上升沿的判定改写为(Myback = ‘0’and back = ‘1’)。
2.数码管的显示问题
由于共阳极数码管每次只能点亮一个,因此需要将数码管按一定的频率依次点亮,利用视觉停留效果实现多个数码管的点亮,但是在实验中发现如果使用100Mhz的频率点亮数码管,数码管的显示会出现极大地错误,并不能显示相应的数字,而是会出现以下的效果,数码管出现混叠的状况,无法正常显示。
分工:
程序与仿真:慌慌,张张
硬件调试:慌慌,张张
实验报告:慌慌,张张
完整工程代码和实验报告:https://download.csdn.net/download/qq_41663196/20429906?spm=1001.2014.3001.5501