VHDL密码锁6位串行输入Word格式.docx
《VHDL密码锁6位串行输入Word格式.docx》由会员分享,可在线阅读,更多相关《VHDL密码锁6位串行输入Word格式.docx(23页珍藏版)》请在冰豆网上搜索。
同时,在计数器之前需要加入消抖模块,使实验板能够稳定输入;
在LED模块之前需要添加译码器,以输出正确显示。
下图为密码锁各个模块及接线。
完成难度密码锁之后设计一个计数器,通过对密码输入确认和输出状态的计数,当输入错误达到三次时,开始一个一刻钟的计时,由另外一个计数器完成。
该计数器的输入还需要一个50m分频模块,得到一个稳定的每秒输出一个电平跳变的输入;
为了将900秒的计时显示到LED上,需要用除法器将计时的各个位拆分出来,再通过译码器显示到LED上。
最后还需要一个输出选择模块,通过对3计数器的数据识别,选择当前LED输出的是900秒计时还是当前输入数据。
下图为难度密码锁最终的各个模块及接线。
其他方案:
除上述方法外,还可以将比较器放在输出选择模块之前,这样能够让程序在开发板上仿真时,位选之后不会将上一位的输入连带到本位;
如果去掉输入选择模块,可以增加一个输入为设置密码输入,即将输入密码和设置密码的输入分开;
倒计时模块采用的是从900倒计时到0,即“1110000110”到“0000000000”,然后输出cout为1;
该程序也可以从“0000000000”累加到“1110000110”计数;
单元电路设计
消抖模块:
消除按键难以避免的抖动,以得到稳定的输入;
计数器:
本实验分别用到了3进制、6进制和10进制的计数器,每计数到一定量时计数器清零并输出一个高电平;
密码合成及选择模块:
将得到的6个4位的密码合成一个24位的密码并输出,方便之后的密码比较,密码合成通过&
完成,通过对输出状态反馈(开锁输出‘1’,锁存输出‘0’)的识别,判断当前输入的数据是设置密码还是输入密码,作两个输出;
确认模块:
将得到的输入密码和设置密码确认输出到比较器,同时在程序载入实验板时,还未有输入的情况下,能够默认输入密码和设置密码都是24位0,使两者初始值相等(此时比较器输出为‘1’,反馈到该模块,输入的数据为设置密码),达到能设置密码的状态;
比较模块:
对得到的输入密码和设置密码进行比较,输出显示当前密码锁是锁存‘0’还是开锁状态‘1’;
译码器:
将得到的数据读取,使其输出的数据能够显示到LED上;
LED:
将6位密码显示在LED上;
50m分频:
每秒稳定输出一个电平跳变;
输出选择:
通过对3进制计数器的数据读取(输入错误三次输出cout为‘1’,否则为‘0’),选择输出是当前密码输入、设置密码输入还是900秒计时;
除法器:
将900秒计时的百位、十位和个位拆分出来,使其能通过译码器显示到LED上。
(该模块主要通过lpm_divide和lpm_constant实现,900秒的计时数据分别除常数100和10,再通过对商的后四位数据的读取得到各个位的大小)下图为除法器各模块及接线:
LED第二位显示默认为0模块:
将实验没有用到的led第二位显示输出默认为不显示;
LED输出选择模块:
选择led是显示倒计时还是此时输入密码
软件设计
软件:
QuartusⅡ(CycloneⅡEP2C5T144C8);
硬件:
对应的FPGA开发板
程序清单
1.消抖模块
LIBRARYIEEE;
USExiaodouIS
PORT(K_IN,CLK:
INSTD_LOGIC;
K_OUT:
OUTSTD_LOGIC);
END;
ARCHITECTUREoneOFxiaodouIS
SIGNALK_PRE:
STD_LOGIC;
SIGNALCOUNT:
INTEGERRANGE0TO3999999;
BEGIN
PROCESS(CLK,K_IN)BEGIN
IFCLK'
EVENTANDCLK='
1'
THEN
IFK_IN=K_PRETHEN
IFCOUNT<
3999999THEN
COUNT<
=COUNT+1;
ELSECOUNT<
=3999999;
ENDIF;
=0;
K_PRE<
=K_IN;
IFCOUNT=3999999THEN
K_OUT<
ENDPROCESS;
2.十进制计数器
USEcnt10IS
PORT(CLK,RST,EN:
INSTD_LOGIC;
CQ:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
COUT:
OUTSTD_LOGIC);
ENDcnt10;
ARCHITECTUREbehavOFcnt10IS
BEGIN
PROCESS(CLK,RST,EN)
VARIABLECQI:
STD_LOGIC_VECTOR(3DOWNTO0);
BEGIN
IFRST='
0'
THENCQI:
=(OTHERS=>
'
);
--计数器异步复位
ELSIFCLK'
THEN--检测时钟上升沿
IFEN='
THEN--检测是否允许计数(同步使能)
IFCQI<
9THENCQI:
=CQI+1;
--允许计数,检测是否小于9
ELSECQI:
);
--大于9,计数值清零
IFCQI=9THENCOUT<
='
;
--计数大于9,输出进位信号
ELSECOUT<
CQ<
=CQI;
--将计数值向端口输出
ENDPROCESS;
ENDbehav;
3.六进制计数器
USECNT6IS
ENDCNT6;
ARCHITECTUREbehavOFCNT6IS
5THENCQI:
IFCQI=5THENCOUT<
4.倒计时的三进制计数器
libraryieee;
usecnt3is
port(c,clk,rst:
instd_logic;
y:
outstd_logic);
endcnt3;
architectureoneofcnt3is
begin
process(clk,c)
variableb:
std_logic_vector(1downto0);
IF(c='
orrst='
)THENb:
THEN
IFb<
3THENb:
=b+1;
ELSEb:
IFb=3THENy<
ELSEy<
endone;
5.输入模块
USE
ENTITYzongxuanIS
PORT(
D:
INSTD_LOGIC_VECTOR(3DOWNTO0);
B:
code0,code1,code2,code3,code4,code5:
OUTSTD_LOGIC_VECTOR(3DOWNTO0));
ENDENTITYzongxuan;
ARCHITECTUREbehavOFzongxuanIS
BEGIN
PROCESS(B)
IFB="
0000"
THENcode0<
=D;
ELSIFB="
0001"
THENcode1<
0010"
THENcode2<
0011"
THENcode3<
0100"
THENcode4<
ELSEcode5<
6.密码合成及选择模块
ENTITYjicunIS
PORT(P0,P1,P2,P3,P4,P5:
INSTD_LOGIC_VECTOR(3DOWNTO0);
CHANGE:
RCODE,ICODE:
OUTSTD_LOGIC_VECTOR(23DOWNTO0));
ENDjicun;
ARCHITECTUREbhvOFjicunIS
SIGNALCODE:
STD_LOGIC_VECTOR(23DOWNTO0);
BEGINPROCESS(CHANGE)
CODE<
=p0&
p1&
p2&
p3&
p4&
p5;
IFCHANGE='
RCODE<
=CODE;
ELSE
ICODE<
ENDbhv;
7.输出确认模块
ENTITYquerenIS
PORT(
INCODE:
INSTD_LOGIC_VECTOR(23DOWNTO0);
OUTCODE:
OUTSTD_LOGIC_VECTOR(23DOWNTO0);
K:
INSTD_LOGIC);
endqueren;
ARCHITECTUREbhvOFquerenIS
BEGINPROCESS(k)
IFk='
OUTCODE<
=INCODE;
ENDIF;
8.比较模块
ENTITYbijiaoIS
L:
endbijiao;
ARCHITECTUREbhvOFbijiaoIS
BEGINPROCESS(RCODE,ICODE)
IFICODE/=RCODETHEN
L<
ELSE
9.译码器
USEyimaqiIS
PORT(A:
Y:
OUTSTD_LOGIC_VECTOR(6DOWNTO0));
ENDENTITYyimaqi;
ARCHITECTUREoneOFyimaqiIS
Y<
="
1000000"
WHENA="
ELSE
"
1111001"
0100100"
0110000"
0011001"
0010010"
0101"
0000010"
0110"
1111000"
0111"
0000000"
1000"
0010000"
1001"
0001000"
1010"
0000011"
1011"
1000110"
1100"
0100001"
1101"
0000110"
1110"
0001110"
1111"
NULL;
ENDARCHITECTUREone;
秒计时
usedaojishiis
port(clk,en:
led0:
outstd_logic_vector(9downto0);
cout:
outstd_logic);
enddaojishi;
architecturebehavofdaojishiis
process(clk,en)
variableled:
std_logic_vector(9downto0);
begin
ifen='
thenled:
1110000100"
led0<
elsifclk'
eventandclk='
then
led:
=led-1;
endif;
ifled="
0000000000"
thencout<
='
elsecout<
endif;
led0<
=led;
endprocess;
endbehav;
11.计时除100得商取后四位
usejiusiis
port(a:
instd_logic_vector(9downto0);
b:
outstd_logic_vector(3downto0));
endjiusi;
architectureoneofjiusiis
process(a)
begin
b<
=a(3downto0);
end;
12.计时除100得余数再除10得商取后四位
useqisiis
port(a:
instd_logic_vector(6downto0);
endqisi;
architectureoneofqisiis
分频
usecnt50Mis
port(clk:
endcnt50M;
architectureoneofcnt50Mis
process(clk)
variablec:
integerrange0to49999999;
ifclk'
then
ifc=49999999then
cout<
c:
else
=c+1;
end;
14.选择是否读取输出状态
USExuanIS
PORT(A:
OUTSTD_LOGIC);
ENDENTITYxuan;
ARCHITECTUREoneOFxuanIS
PROCESS(B,A)
IFB='
THENY<
=A;
Y<
ENDARCHITECTUREone;
15.输出选择模块
usexuanzeis
port(a,b:
s:
outstd_logic_vector(6downto0));
endxuanze;
architectureoneofxuanzeis
begin
process(s)
ifs<
theny<
=a;
elsey<
=b;
endprocess;
16.LED显示
libraryIEEE;
useLED_ctrlis
port(clk_50M:
instd_logic;
D1,D2,D3,D4,D5,D6,D7,D8:
instd_logic_vector(6downto0);
LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8:
outstd_logic;
Dout:
outstd_logic_vector(6downto0));
endLED_ctrl;
architectureoneofLED_ctrlis
signalcnt:
integerrange49999downto0;
signalseg_num:
integerrange7downto0;
process(clk_50M)
ifclk_50M'
eventandclk_50M='
ifcnt<
49999th