(1) 拥有正常的时、分、秒计时功能。
(2) 能利用实验板上的按键实现校时、校分及秒清零功能。 (3) 能利用实验板上的扬声器做整点报时。 (4) 闹钟功能。
(5) 在QUARTUS Ⅱ中采用层次化设计方法进行设计。
(6) 完成全部电路设计后在实验板上下载,验证设计课题的正确性。
二、 多功能数字钟的总体设计方案
根据总体设计框图,可以将整个系统分成6个模块来实现,分别是计时模块、校时模块、整点报时模块,分频模块,动态显示模块,闹钟模块。
设计总图:
1. 计时模块
该模块的设计相对简单,使用一个二十四进制和两个六十进制计数器级联,构成数字钟的基本框架。二十四进制的计数器用于计时,六十进制计数器用于计分和计秒。只要给秒计数器一个1Hz的时钟脉冲,则可以进行正常计时。分计数器以秒计数器的进位作为计数脉冲,小时计数器以分计数器的进位作为计数脉冲。
cnt24jh[3..0]clkql[3..0]qh[3..0]tcinstVCCjh[7..4]cnt60jm[3..0]clkql[3..0]clrqh[3..0]tcjm[7..4]NOTinst15inst1
(24进制计数器构成时计数器,60进制计数器构成的秒、分计数器)
24进制的仿真图:
1
60进制的仿真图
以下是计时模块设计VHDL语言: (1)library ieee;
use ieee.std_logic_11.all; use ieee.std_logic_unsigned.all; entity cnt24 is
port(clk:in std_logic;
ql,qh:out std_logic_vector(3 downto 0); tc:out std_logic); end cnt24;
architecture one of cnt24 is
begin
process(clk)
variable iql,iqh:std_logic_vector(3 downto 0); begin
if clk'event and clk='1' then iql:=iql+1;
if iql=\"1010\" then iqh:=iqh+1; iql:=\"0000\"; end if;
2
if (iqh=\"0010\")and(iql=\"0100\") then tc<='0'; iqh:=\"0000\"; iql:=\"0000\"; end if;
end if;
ql<=iql; qh<=iqh;
end process; end one;
(2)library ieee;
use ieee.std_logic_11.all; use ieee.std_logic_unsigned.all; entity cnt60 is
port(clk,clr:in std_logic;
ql,qh:buffer std_logic_vector(3 downto 0); tc:out std_logic ); end cnt60;
architecture behavor of cnt60 is begin
tc<='0' when(clk='1' and ql=\"0000\" and qh=\"0110\") else '1'; process(clk,clr,ql,qh)
variable iql,iqh:std_logic_vector(3 downto 0); begin
if(clr='0'or (iql=\"0000\" and iqh=\"0110\"))then iql:=\"0000\"; iqh:=\"0000\";
else if(clk'event and clk='1')then iql:=iql+1;
if(iql=\"1010\")then iql:=\"0000\"; iqh:=qh+1; end if; end if; end if;
ql<=iql;qh<=iqh; end process; END behavor;
3
2. 校时模块
该模块设计要求实现校时、校分及秒清零的功能。
① 按下校时键,小时计数器迅速递增以调至所需要的小时位。 ② 按下校分键,分计数器迅速递增以调至所需要的分位。 ③ 按下清零键,将秒计数器清零。
可以选择实验板上的3个脉冲按键进行锁定。
对于此模块的设计,有3个需要注意的问题:
① 在校分时,分计数器的计数不应对小时位产生影响。因而需要屏蔽此时分计数器的进位信号以防止小
时计数器计数。具体方法是在分计数器的进位输出时外加一个组合电路。详见下图。
hinputhz4hinputs21muxABSinst6YMULTIPLEXERNAND2hz4tcminputsNOTminputABSinst7YMULTIPLEXERNOTAND2inst13inst10inst9inst1421mux
(二路选择器与计数器之间连了一个组合电路,以屏蔽进位信号)
② 按键的“抖动”的消除。
所谓的“抖动”是指一次按键时的弹跳现象,通常实验板中按键所用的开关为机械性开关,由于机械触点的弹性作用,按键开关在闭合时并不能马上接通,而断开的时候也不能马上断开,使得闭合及断开的瞬间伴随一系列的电压抖动,从而导致本来一次按键,希望计数一次,结果因为抖动计数多次,且次数随机,这样严重影响了时间的校对。
消除抖动较为简单的方法是利用触发器,比如可以使用D触发器进行消抖。原因在于,D触发器边沿触发,则在除去时钟边沿到来前一瞬间之外的绝大部分时间都不接受输入,自然消除了抖动。详见下图
DFFDPRNNOThinputQinst8CLRNinst3DFFDPRNQCLRNinst4NOTinst9
(加D触发器防抖动)
4
③ 计时采用1Hz的脉冲驱动计数器计数,而校对时间时应选用相对高频率的信号驱动计数器以达到快速
校对时间的目的。显然,这两种计数脉冲之间需要进行相应的选择切换。于是将计时和校时模块合起来的电路实现可以实现(见图3)。两种脉冲信号用两路选择器进行选择,选择条件为是否按键。按键输出经过了消抖的过程。
3.整点报时模块
该模块的功能要求是:计时到59分52秒时,每两秒一次低音报时,整点时进行高音报时,可以将报时信号接到实验板上的扬声器输出。而以不同频率的脉冲信号区分低音和高音报时。进行报时的条件是计数器计数至所要求的时间点,因而需要实现一个比较模块,将分计数器和秒计数器的输出连至比较模块输入端完成比较过程。
zdbsjm[7..4]jm[3..0]js[7..4]js[3..0]mh[3..0]ml[3..0]sh[3..0]sl[3..0]sig500sig1kinst16
(整点报时顶层图)
以下是整点报时的比较模块设计VHDL语言 library ieee;
use ieee.std_logic_11.all; use ieee.std_logic_unsigned.all; entity zdbs is
port(mh,ml,sh,sl:in std_logic_vector(3 downto 0); sig500,sig1k: out std_logic );
end zdbs;
architecture behavior of zdbs is begin
sig500<='1' when mh=\"0101\"and ml=\"1001\"and sh=\"0101\"and (sl=\"0010\" or sl=\"0100\" or sl=\"0110\"or sl=\"1000\") ----------------------------------比较,当时间为59分2、4、6、8钞时,sig500端输出为高电平。
else '0';
sig1k<='1' when mh=\"0000\"and ml=\"0000\"and sh=\"0000\"and sl=\"0000\"
else '0'; ------------------------------比较,当时间为0分0钞时,sig1k端输出为高电平。 end behavior;
4.分频模块
在本系统中需要用到多种不同频率的脉冲信号,上至高音报时,下至1Hz的计秒脉冲。所有这些脉冲信号均可以通过一个基准频率分频器生成。基准频率分频器就是一个进制很大的计数器,利用计数器的分频功能,从不同的输出位得到所需要的脉冲信号。
5
freq_dividerhz1clkhz1hz4hzhz512hzhz512hz4inst12 (分频模块顶层图)
以下是分频模块设计VHDL语言
LIBRARY IEEE;
USE IEEE.STD_LOGIC_11.ALL; USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY freq_divider IS
PORT(clk : IN STD_LOGIC; hz1 : OUT STD_LOGIC; hz4 : OUT STD_LOGIC; hz : OUT STD_LOGIC; hz512 : OUT STD_LOGIC); END freq_divider;
ARCHITECTURE rtl OF freq_divider IS
SIGNAL count : STD_LOGIC_VECTOR(9 DOWNTO 0); BEGIN
PROCESS(clk) BEGIN
IF (clk'event and clk='1') THEN IF(count=\"1111111111\") THEN Count <= (OTHERS =>'0'); ELSE
Count <= count +1; END IF ; END IF ; END PROCESS;
hz512 <= count(0); --------------------每2个时钟产生一个时钟输出 hz <= count(3);---------------------每16个时钟产生一个时钟输出 hz4 <= count(7);---------------------每256个时钟产生一个时钟输出 hz1 <= count(9);---------------------每1024个时钟产生一个时钟输出 END rtl;
5.动态显示模块
在动态方式下,所有的数码管对应同一组七段码,每一个数码管由一个选择段控制点亮或熄灭,如果全部点亮,则都显示相同的数字。若要实现6位不同时间的显示。则需要利用人的视觉缺陷。
具体来讲,可以在6个不同的时间段分别将每组时间经过七段译码后输出到6个数码管,当某一组时间的
6
七段码到达时,只点亮对应位置上的数码管,显示相应的数字;下一个循环将相邻一组时间的七段码送至数码管,同样只点亮相应位置的数码管,6次一个循环,形成一个扫描序列。只要扫描频率超过人眼的视觉暂留频率(24Hz),就可以达到点亮单个数码管,却能享有6个同时显示的视觉效果,人眼辨别不出差别,而且扫描频率越高,显示越稳定。
dtsmclkh[7..0]m[7..0]s[7..0]clkh[7..0]m[7..0]s[7..0]seg7out[6..0]sel[2..0]seg[6..0]sel[2..0]inst17 (动态显示模块顶层图)
以下是动态显示模块设计的VHDL语言 LIBRARY IEEE;
USE IEEE.STD_LOGIC_11.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY dtsm is port(
clk:in std_logic;
h:in std_logic_vector(7 downto 0); m:in std_logic_vector(7 downto 0); s:in std_logic_vector(7 downto 0);
seg7out:out std_logic_vector(6 downto 0); sel:buffer std_logic_vector(2 downto 0) ); END dtsm;
ARCHITECTURE beha of dtsm is
signal key:std_logic_vector(3 downto 0); BEGIN
PROCESS(clk)
variable dount:std_logic_vector(2 downto 0):=\"000\"; BEGIN
IF(rising_edge(clk))then---------------------开始扫描 IF dount=\"101\" then dount:=\"000\"; ELSE
dount:=dount+1; END IF; END IF; sel<=dount; end process;
7
PROCESS(sel) BEGIN
CASE sel IS---------------------------------------多路选择代码 when \"000\"=>key<=h(7 downto 4); when \"001\"=>key<=h(3 downto 0); when \"010\"=>key<=m(7 downto 4); when \"011\"=>key<=m(3 downto 0); when \"100\"=>key<=s(7 downto 4); when \"101\"=>key<=s(3 downto 0); when others=>null; END CASE; END PROCESS; PROCESS (key) BEGIN
case key is-------------------------------------七段显示代码 when\"0000\"=>seg7out<=\"0111111\"; when\"0001\"=>seg7out<=\"0000110\"; when\"0010\"=>seg7out<=\"1011011\"; when\"0011\"=>seg7out<=\"1001111\"; when\"0100\"=>seg7out<=\"1100110\"; when\"0101\"=>seg7out<=\"1101101\"; when\"0110\"=>seg7out<=\"1111101\"; when\"0111\"=>seg7out<=\"0000111\"; when\"1000\"=>seg7out<=\"1111111\"; when\"1001\"=>seg7out<=\"1101111\"; when\"1010\"=>seg7out<=\"1110111\"; when\"1011\"=>seg7out<=\"1111100\"; when\"1100\"=>seg7out<=\"0111001\"; when\"1101\"=>seg7out<=\"1011110\"; when\"1110\"=>seg7out<=\"1111001\"; when\"1111\"=>seg7out<=\"1110001\"; when others=>null; END CASE; END PROCESS; END beha;
8
6、闹钟模块
ahinputhz4cnt24AND2halr[3..0]clkql[3..0]qh[3..0]halr[7..4]inst23inst22tcVCChz4aminputAND2cnt60malr[3..0]clkql[3..0]inst25malr[7..4]clrqh[3..0]tc (通过24进制计数器置入时信号,通过60进制计数器置入分信号)
selalarmalarmseth[7..0]jh[7..0]jm[7..0]js[7..0]halr[7..0]malr[7..0]js[7..0]selhclo[7..0]mclo[7..0]sclo[7..0]halr[7..0]malr[7..0]salr[7..0]inst18h[7..0]s[7..0]m[7..0]s[7..0]m[7..0]inst24 (时钟-闹钟信号选择模块)
以下是时钟闹钟信号选择模块设计的VHDL语言: library ieee;
use ieee.std_logic_11.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity alarmset is port(sel:in std_logic;
hclo,mclo,sclo,halr,malr,salr: in std_logic_vector(7 downto 0); h,s,m:out std_logic_vector(7 downto 0)); end alarmset;
architecture beh of alarmset is begin
process(sel) begin
if(sel='0')then h<=hclo; --------------------------------当sel输入端为低电平时,把时钟信号传递到输出端 m<=mclo; s<=sclo;
else h<=halr; --------------------------------当sel输入端为高电平时,把闹钟置入的信号传递到输出端 m<=malr;
9
s<=salr; end if;
end process; end beh;
(当选择开关输入为低电平时,把时钟信号传递到动态显示模块;当选择开关输入为高电平时,把闹钟信号传递到动态显示模块。)
alarmcmpjh[7..0]jm[7..0]halr[7..0]malr[7..0]h[7..0]m[7..0]halr[7..0]malr[7..0]stopinst11sig
(比较模块)
以下是比较模块设计的VHDL语言 library ieee;
use ieee.std_logic_11.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity alarmcmp is
port( h,m,halr,malr: in std_logic_vector(7 downto 0); stop:in std_logic;
sig:out std_logic); end alarmcmp;
architecture beh of alarmcmp is
begin
process(h,m,halr,malr,stop) begin
if stop='1'then
sig<='0'; -----------------当stop端输入为高电平,输出为低电平 end if;
if h=halr and m=malr and stop='0' then
sig<='1'; -----------------当stop端输入为低电平、时钟传来的信号与闹钟置入的信号一致时,输出为高电平 else sig<='0'; --------------------------------当时钟传来的信号与闹钟置入的信号不一致时,输出为低电平
end if;
end process; end beh;
10
sel2selalarmhinputselipabhinputsahinputinst31sel2selalarmminputminputsselipabaminputinst32
(输入选择电路顶层图)
当selalarm端输入为低电平时,时钟实现计时功能,选择电路把输入信号传递到计时模块,使其调整时间; 当selalarm端输入为高电平时,时钟实现闹钟设置功能,选择电路把输入信号传递到闹钟模块,使其设置闹钟。
三、总结
通过这次的数逻课程设计后,我学到了很多,对于VHDL语言有了进一步的认识,掌握了实验板上某些按键的功能。我明白了很多东西都是事在人为,因为一开始弄得时候,什么也不会,后来通过询问同学和找资料,才慢慢的懂了一些。会了以后,感觉还是很好玩的,当报时的声音响起的时候,心里面还是很有成就感的。本次试验不是很困难,用心的话还是挺好玩的,毕竟的合成图老师已给出,只需要按照步骤来就可以了。
然后因为这次实验,我也明白了自己需要学的东西还是很多的,毕竟很多东西都需要询问和查资料才懂,但对于QuartusⅡ还是会比之前更加熟练了,熟能生巧的缘故吧,反正操作起来挺顺手的。但一开始没有将文件置顶,又建立了很多工程名,后来经过老师的指导,才弄好了,因为学的不好的缘故,所以今后还是好好学习吧。总而言之,这次实验给了我很大的学习动力。
11
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo6.cn 版权所有 赣ICP备2024042791号-9
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务