数字电路设计实验简易密码锁.docx
《数字电路设计实验简易密码锁.docx》由会员分享,可在线阅读,更多相关《数字电路设计实验简易密码锁.docx(35页珍藏版)》请在冰豆网上搜索。
数字电路设计实验简易密码锁
数字电路设计实验报告
——简易密码锁
学院:
班级:
学号:
姓名:
目录
●任务要求
●系统设计
✓设计思路
✓总体框图
✓分块设计
●波形仿真及波形分析
●源代码
●功能分析
●故障分析及问题解决
●总结及结论
●任务要求
设计并实现一个数字密码锁,密码锁有四位数字密码和一个确认开锁按键,密码输入正确,密码锁打开,密码输入错误进行警示。
基本要求:
1、密码设置:
通过键盘进行4位数字密码设定输入,在数码管上显示所输入数字。
通过密码设置确定键(BTN键)进行锁定。
2、开锁:
在闭锁状态下,可以输入密码开锁,且每输入一位密码,在数码管上显示“-”,提示已输入密码的位数。
输入四位核对密码后,按“开锁”键,若密码正确则系统
开锁,若密码错误系统仍然处于闭锁状态,并用蜂鸣器或led闪烁报警。
3、在开锁状态下,可以通过密码复位键(BTN键)来清除密码,恢复初始密码“0000”。
闭锁状态下不能清除密码。
4、用点阵显示开锁和闭锁状态。
提高要求:
1、输入密码数字由右向左依次显示,即:
每输入一数字显示在最右边的数码管上,同时将先前输入的所有数字向左移动一位。
2、密码锁的密码位数(4~6位)可调。
3、自拟其它功能。
●系统设计
Ø设计思路
将电子密码锁系统分为三个部分来进行设计,数字密码输入部分、密码锁控制电路和密码锁显示电路。
密码锁输入电路包括时序产生电路,键盘扫描电路,键盘译码电路等,将用户手动输入的相关密码信息转换为软件所能识别的编码,作为整个电路的输入。
密码锁控制电路包括相应的数据存储电路,密码核对电路,能够进行数值的比较,进行电路解锁,开锁,密码的重新设置等。
密码锁显示电路包括将待显示数据的BCD码转换成数码管的七段显示驱动编码,密码锁在相应的状态下的点阵输出以及蜂鸣器的报警输出。
Ø总体框图
按复位键
键入初始密码0000
密码错误
密码正确
按确认键
按复位键
按确认键
Ø分块设计
✓键盘扫描电路
首先,向列扫描地址逐列输出低电平,然后从行码地址读回,如果有键摁下,则相应行的值应为低,如果没有按键按下,由于上拉的作用,行码为高。
这样就可以通过输出列码和读取的行码来判断按下的是什么键。
在判断有按键的按下后,要有一定的延时,防止键盘抖动。
entitykeyboardis
port(
row:
instd_logic_vector(3downto0);
col:
outstd_logic_vector(3downto0);
keyout:
outstd_logic_vector(3downto0);
q:
outstd_logic;
clk:
instd_logic
);
endkeyboard;
architecturestructofkeyboardis
signalcol_buffer1:
std_logic_vector(3downto0);
signalcol_buffer2:
std_logic_vector(3downto0);
signalkey:
std_logic_vector(7downto0);
signalcounter:
integerrange0to3;
signaldelay:
integerrange0to10;
signalstop:
std_logic;
begin
col<=col_buffer2;
q<=stop;
process(CLK,row,stop)
begin
ifclk'eventandclk='1'then
ifcounter=3then
counter<=0;
else
counter<=counter+1;//由于只要求输入四个数字所以需要计数
endif;
casecounteris
when0=>col_buffer1<="1110";
when1=>col_buffer1<="1101";
when2=>col_buffer1<="1011";
when3=>col_buffer1<="0111";
endcase;
endif;
endprocess;
key<=row&col_buffer2;
process(clk,key)
begin
ifclk'eventandclk='0'then
casekeyis
when"01111110"=>stop<='1';keyout<="0000";
when"01111101"=>stop<='1';keyout<="0001";
when"01111011"=>stop<='1';keyout<="0010";
when"01110111"=>stop<='1';keyout<="0011";
when"10111110"=>stop<='1';keyout<="0100";
when"10111101"=>stop<='1';keyout<="0101";
when"10111011"=>stop<='1';keyout<="0110";
when"10110111"=>stop<='1';keyout<="0111";
when"11011110"=>stop<='1';keyout<="1000";
when"11011101"=>stop<='1';keyout<="1001";
whenothers=>stop<='0';//仅仅在摁0~9的时候会有显示,在摁除了这十个键之外的键的时候是不会有反应的,将keyout的值转换为相应的数码管值,来控制数码管的显示
endcase;
endif;
endprocess;
process(clk,stop)
begin
ifclk'eventandclk='1'then
ifstop='0'then
col_buffer2<=col_buffer1;
endif;
endif;
endprocess;
endstruct;
✓点阵显示电路
采用行扫描的方式,每经过一段时间,给一行一个低电平。
则若在列的方向上如果接入高电平,则会使相应的二极管发光。
由于人眼的的暂留效应就回使我们看到我们想要的图案。
libraryieee;
useieee.std_logic_1164.all;
entityledis
port(
row:
outstd_logic_vector(7downto0);
num:
instd_logic_vector(1downto0);
clk:
instd_logic;
col:
outstd_logic_vector(7downto0)
);
endentity;
architecturestructofledis
signalcounter:
integerrange0to7;
begin
process(clk)
begin
ifclk'eventandclk='1'then
ifcounter=7then
counter<=0;
else
counter<=counter+1;
endif;
endif;
endprocess;
process(clk,counter)
begin
ifclk'eventandclk='0'then
ifnum<="00"then//键入状态
casecounteris
when0=>row<="11111110";col<="00111100";
when1=>row<="11111101";col<="00111100";
when2=>row<="11111011";col<="00111100";
when3=>row<="11110111";col<="00111100";
when4=>row<="11101111";col<="00111100";
when5=>row<="11011111";col<="00011000";
when6=>row<="10111111";col<="00111100";
when7=>row<="01111111";col<="00011000";
endcase;
elsifnum="01"then//闭锁状态
casecounteris
when0=>row<="11111110";col<="11111111";
when1=>row<="11111101";col<="11111111";
when2=>row<="11111011";col<="11111111";
when3=>row<="11110111";col<="11111111";
when4=>row<="11101111";col<="01000010";
when5=>row<="11011111";col<="01000010";
when6=>row<="10111111";col<="01000010";
when7=>row<="01111111";col<="00111100";
endcase;
elsifnum="10"then//开锁状态
casecounteris
when0=>row<="11111110";col<="00000000";
when1=>row<="11111101";col<="00011111";
when2=>row<="11111011";col<="00011111";
when3=>row<="11110111";col<="00011111";
when4=>row<="11101111";col<="10011111";
when5=>row<="11011111";col<="10001000";
when6=>row<="10111111";col<="10001000";
when7=>row<="01111111";col<="01110000";
endcase;
else
casecounteris//报警状态
when0=>row<="11111110";col<="00011000";
when1=>row<="11111101";col<="00111100";
when2=>row<="11111011";col<="00011000";
when3=>row<="11110111";col<="00011000";
when4=>row<="11101111";col<="00111100";
when5=>row<="11011111";col<="00111100";
when6=>row<="10111111";col<="00111100";
when7=>row<="01111111";col<="00011000";
endcase;
endif;
endif;
endprocess;
endstruct;
✓数码管显示
其中引脚图的两个COM端连在一起,是公共端,共阴数码管要将其接地,共阳数码管将其接正5伏电源。
一个八段数码管称为一位,多个数码管并列在一起可构成多位数码管,它们的段选线(即a,b,c,d,e,f,g,dp)连在一起,而各自的公共端称为位选线。
显示时,都从段选线送入字符编码,而选中哪个位选线,那个数码管便会被点亮。
数码管的8段,对应一个字节的8位,a对应最低位,dp对应最高位。
所以如果想让数码管显示数字0,那么共阴数码管的字符编码为00111111;共阳数码管的字符编码为11000000。
process(clk,counter)
begin
ifclk'eventandclk='0'then
casecounteris//选通,可使数码管只单独亮一位
when0=>cat<="111110";ao<=a0;
when1=>cat<="111101";ao<=a1;
when2=>cat<="111011";ao<=a2;
when3=>cat<="110111";ao<=a3;
when4=>cat<="101111";ao<=a4;
when5=>cat<="011111";ao<=a5;
endcase;
endif;
endprocess;
process(ao)
begin
caseaois//将键盘输入的一系列值翻译成接通数码管值
when"0000"=>a<="1111110";
when"0001"=>a<="0110000";
when"0010"=>a<="1101101";
when"0011"=>a<="1111001";
when"0100"=>a<="0110011";
when"0101"=>a<="1011011";
when"0110"=>a<="1011111";
when"0111"=>a<="1110000";
when"1000"=>a<="1111111";
when"1001"=>a<="1111011";
when"1010"=>a<="0000001";
whenothers=>a<="0000000";
endcase;
endprocess;
endstruct;
●仿真波形及波形分析
如图,程序开始运行的时候,给键盘扫描,系统会给出相应的键盘输出,是点阵显示出输入状态
图为一系列当键盘键入的时候,一系列数码管显示
在键入改变的初始密码之后,系统会变成闭锁状态,点阵如图显示
当输入的密码错误的时候,摁清零键的时候,会发出警报
●源代码
libraryieee;
useieee.std_logic_1164.all;
entitylockis
port(
clk:
instd_logic;//时钟信号
rr:
instd_logic;//重置清零键
s:
instd_logic;//确认键
warn:
outstd_logic;//警报信号
ou:
outstd_logic_vector(3downto0);
----key
key_row:
instd_logic_vector(3downto0);//键盘扫描行列
key_col:
outstd_logic_vector(3downto0);
----led
led_col:
outstd_logic_vector(7downto0);//点阵扫描行列
led_row:
outstd_logic_vector(7downto0);
----seg
cat:
outstd_logic_vector(5downto0);//数码管选通
a:
outstd_logic_vector(6downto0)//数码管显示
);
endentity;
architecturestructoflockis
signalkeynum:
integerrange0to9;
signalwarn_on:
std_logic;
signalstatus:
integerrange0to3;
signalnum_counter:
integerrange0to5;
signalclk_1000:
std_logic;
signalclk_1:
std_logic;
signalq:
std_logic;
signalr:
std_logic;
signalw:
std_logic;
signalnum:
std_logic_vector(1downto0);
signalkey:
std_logic_vector(3downto0);
signalinput:
std_logic_vector(3downto0);
signalseg_num:
std_logic_vector(2downto0);
signalp1,p2,p3,p4:
std_logic_vector(3downto0);
signalpassword:
std_logic_vector(15downto0);
signaldelay:
integerrange0to31;
componentdivis//分频器
port(
clk_in:
instd_logic;
clk_1000:
outstd_logic;
clk_1:
outstd_logic
);
endcomponent;
componentkeyboardis//键盘扫描
port(
row:
instd_logic_vector(3downto0);
col:
outstd_logic_vector(3downto0);
keyout:
outstd_logic_vector(3downto0);
q:
outstd_logic;
clk:
instd_logic
);
endcomponent;
componentledis//点阵显示
port(
row:
outstd_logic_vector(7downto0);
num:
instd_logic_vector(1downto0);
clk:
instd_logic;
col:
outstd_logic_vector(7downto0)
);
endcomponent;
componentsegis//数码管
port(
r:
instd_logic;
clk:
instd_logic;
cat:
outstd_logic_vector(5downto0);
a:
outstd_logic_vector(6downto0);
w:
instd_logic;
input:
instd_logic_vector(3downto0);
num:
instd_logic_vector(2downto0)
);
endcomponent;
componentOneis
port(
clk:
instd_logic;
i:
instd_logic;
o:
outstd_logic
);
endcomponent;
begin
IC1:
divportmap(clk,clk_1000,clk_1);
IC2:
keyboardportmap(key_row,key_col,key,q,clk_1000);
IC3:
ledportmap(row=>led_row,num=>num,clk=>clk_1000,col=>led_col);
IC4:
segportmap(r=>r,clk=>clk_1000,cat=>cat,a=>a,w=>w,input=>input,num=>seg_num);
--status
process(s,rr,status)
begin
ifrr='1'then
ifstatus=2then
status<=0;
elsifstatus=3then
status<=1;
endif;
elsifs'eventands='1'then
ifstatus=0then
status<=1;
password<=p1&p2&p3&p4;
elsifstatus=1then
ifpassword=p1&p2&p3&p4then
status<=2;
else
status<=3;
endif;
else
status<=1;
endif;
endif;
endprocess;
//statue0代表的是输入状态,statue1是闭锁状态,statue2是开锁状态,statue3是报警状态,状态转移图在前面已经画出
process(s,rr,clk_1000)
begin
ifrr='1'then
r<='1';
elsifs='1'then
r<='1';
elsifclk_1000'eventandclk_1000='0'then
r<='0';
endif;
endprocess;
---num_counter
process(s,rr,q,clk_1000)
begin
ifs='1'then
num_counter<=0;
elsifrr='1'then
num_counter<=0;
elsifq'eventandq='0'then
ifstatus=0orstatus=1then
i