基于QuartusII软件的数字时钟设计.docx
《基于QuartusII软件的数字时钟设计.docx》由会员分享,可在线阅读,更多相关《基于QuartusII软件的数字时钟设计.docx(22页珍藏版)》请在冰豆网上搜索。
基于QuartusII软件的数字时钟设计
实验名称:
数字时钟设计
姓名:
杨龙成班级:
电子与通信工程学号:
**********成绩:
一、实验目的
1.掌握各类计数器及它们相连的设计方法;
2.掌握多个数码管显示的原理与方法;
3.掌握模块化设计方式;
4.掌握用VHDL语言的设计思想以及整个数字系统的设计。
二、实验内容
1.设计要求
1)具有时、分、秒计数显示功能,在数码管显示00:
00:
00~23:
59:
59,以24小时循环计时。
2)完成可以计时的数字时钟时钟计数显示时有LED灯的花样显示。
3)具有调节小时、分钟及清零的功能。
4)具有整点报时功能。
2.性能指标及功能设计
1)时钟计数:
完成时、分、秒的正确计时并且显示所计的数字;对秒、分
60进制计数,时钟—24进制计数,并且在数码管上显示数值。
2)时间设置:
手动调节分钟、小时,可以对所设计的时钟任意调时间。
可以通过实验板上的键7和键4进行任意的调整,因为时钟信号均是1HZ的,所以LED灯每变化一次就来一个脉冲,即计数一次。
3)清零功能:
reset为复位键,低电平时实现清零功能,高电平时正常计数。
4)蜂鸣器在整点时有报时信号产生,产生“滴答.滴答”的报警声音。
5)根据进位情况,LED灯在时钟显示时有花样显示信号产生。
3.系统方框图
三、设计原理和过程
3.1硬件设计
本设计使用VHDL硬件开发板,可编程逻辑器件EMP1270T144C5系列。
设计过程中用到的外围电路的设计有电源部分,可编程器件EMP1270T144C5,CPLD–JTAG接口,晶振和蜂鸣器,LED数码管显示,DIP开关与按键输入(具体电路见附录)
3.2软件设计
3.2..1程序包my_pkg的设计说明
为了简化程序设计增加可读性,系统采用模块化的设计方法,重复使用的组件以元件(component)的形式存在,以便相关块的调用。
下面列出my_pkg组件包的代码。
libraryieee;
useieee.std_logic_1164.all;
packagemy_pkgis
componentdiv40M------------------------------------------------------------------元器件1
Port(clk:
instd_logic;
f1hz:
outstd_logic);
endcomponent;
componentcount60-----------------------------------------------------------------元器件2
Port(clr,clk:
instd_logic;
one:
bufferstd_logic_vector(3downto0);
ten:
bufferstd_logic_vector(3downto0);
full:
outstd_logic;
dout:
bufferstd_logic_vector(7downto0));
endcomponent;
componentcount24-----------------------------------------------------------------元器件3
Port(clr,clk:
instd_logic;
one:
bufferstd_logic_vector(3downto0);
ten:
bufferstd_logic_vector(3downto0);
full:
outstd_logic);
endcomponent;
componentscan6----------------------------------------------------------------元器件4
port(clr,clk:
inSTD_LOGIC;
h_ten,h_one,m_ten,m_one,s_ten,s_one:
inSTD_LOGIC_vector(3downto0);
cs:
outSTD_LOGIC_vector(5downto0);
mux_out:
outSTD_LOGIC_vector(3downto0));
endcomponent;
componentbin2led---------------------------------------------------------------元器件5
port(bin:
instd_logic_vector(3downto0);
led:
outstd_logic_vector(7downto0));
endcomponent;
componentsh1k----------------------------------------------------------------------元器件6
Port(clk:
instd_logic;--fromsystemclock(40MHz)
f1hz:
outstd_logic);--1Hzoutputsignal
endcomponent;
componentalarm_set------------------------------------------------------------------元器件7
Port(rst,hz1:
instd_logic;--systemclock1Hz
alarm,ok:
instd_logic;--keeppushingtodeclarealarmset
sec_tune:
instd_logic;
sec_one,sec_ten:
outstd_logic_vector(3downto0));
endcomponent;
endmy_pkg;
3.2.2count60组件
由此提供分(秒)计数值,当分计数器计数到59再来一个脉冲信号秒计数器清零从新开始计数,而进位则作为小时计数器的计数脉冲,使小时计数器计数加1,同时分计数器在分设置时钟信号的响应下设置分计数器的数值。
在count60组件中,个位(one)和十位(ten)分别计数,都设为二进制四位矢量形式,当个位从0计到9时,在下一个clk上升沿来临后,十位进1,个位变0,十位从0到5计数,在十位为5,个位9的时候,下一个上升沿来临后,十位个位都变0,进位full加1。
因此在程序设计中需要两个进程process来分别完成计数,秒计数以1Hz的输入为触发信号,分计数以秒的full信号为触发信号。
具体的count60的组件代码如下:
Libraryieee;
Useieee.std_logic_1164.all;
Useieee.std_logic_unsigned.all;
Entitycount60is
Port(clr,clk:
instd_logic;
one:
bufferstd_logic_vector(3downto0);
ten:
bufferstd_logic_vector(3downto0);
full:
outstd_logic;
dout:
bufferstd_logic_vector(7downto0));
endcount60;
architecturebehavofcount60is
begin
process(clr,clk)
begin
if(clr='0')then
one<="0000";
elsif(rising_edge(clk))then
if(one="1001")then
one<="0000";
else
one<=one+1;
endif;
endif;
endprocess;
process(clr,clk)
begin
if(clr='0')then
ten<="0000";
elsif(rising_edge(clk))then
if(one="1001")then
if(ten="0101")then
ten<="0000";
else
ten<=ten+1;
endif;
endif;
endif;
endprocess;
dout<=ten&one;
process(clk)-----------------满59进位(置full值
begin
if(rising_edge(clk))then
iften="0101"then
ifone="1001"then
full<='1';
elsefull<='0';
endif;
elsefull<='0';
endif;
endif;
endprocess;
endbehav;
设定clk与clr两个系统的输入后,课观察到one和ten的波形,在计数值达到59后,即ten为0101,one为1001以后,即进位到00000000,full进1,波形如下。
3.2.3count24组件
由此提供时计数值,当时计数器计数到23再来一个脉冲信号秒计数器清零从新开始计数,而进位则作为小时计数器的计数脉冲,使小时计数器计数加1,同时分计数器在分设置时钟信号的响应下设置时计数器的数值。
在count24组件中,个位(one)和十位(ten)分别计数,都设为二进制四位矢量形式,在ten小于2的时候,个位从0计到9时,满9ten加1,在ten为2的时候,one从0到3计数,one为3时候,在下一个clk上升沿来临后,ten与one都变0,进位full加1。
因此在程序设计中需要多个个进程process来分别完成计数,时计数以分的full的输入为触发信号,分计数以秒的full信号为触发信号。
具体的count24的组件代码如下:
Libraryieee;
Useieee.std_logic_1164.all;
Useieee.std_logic_unsigned.all;
Entitycount24is
Port(clr,clk:
instd_logic;
one:
bufferstd_logic_vector(3downto0);
ten:
bufferstd_logic_vector(3downto0);
full:
outstd_logic
);
endcount24;
architecturebehavofcount24is
begin
process(clr,clk)-------------------------计数0到23
begin
if(clr='0')then
ten<="0000";
one<="0000";
elsif(rising_edge(clk))then
if(ten<"0010")then
if(one<"1001")then
one<=one+"0001";
endif;
ifone="1001"then
one<="0000";
ten<=ten+"0001";
endif;
endif;
if(ten="0010")then
if(one<"0011")then
one<=one+"0001";
endif;
ifone="0011"then
one<="0000";
ten<="0000";
endif;
endif;
endif;
endprocess;
process(clk)---------------------------------满23进位
begin
if(rising_edge(clk))then
iften="0010"then
ifone="0011"then
full<='1';
elsefull<='0';
endif;
elsefull<='0';
endif;
endif;
endprocess;
endbehav;
小时计数模块图形分析:
用来对时进行计数,当记到计数器的低四位小于2时,one从0到9计数,ten为2时,one从0到3计数,所以完成了24进制的计数,clk为系统时钟信号,具体波形如下:
3.2.4div40M分频组件
为了便于时钟计数,需要1Hz的时钟信号。
为了节省电力耗电,输出采用7段LED数码管来显示。
要提供秒钟的源信号,以便正常的计数,另外,6个led数码管要都显示,利用人眼的视觉暂留效应,需要1000hZ的时钟扫描信号。
在本系统中,时钟信号发生器的信号频率为40MHz,因此要将其进行分频,产生1HZ和1KHz的信号。
代码如下:
LibraryIEEE;
UseIEEE.std_logic_1164.all;
Useieee.std_logic_unsigned.all;
UseIEEE.std_logic_arith.all;
Entitydiv40Mis
Port(clk:
instd_logic;--fromsystemclock(40MHz)
f1hz:
outstd_logic);--1Hzoutputsignal
enddiv40M;
architecturearchofdiv40Mis
signalcount:
integerrange0to19999999;
begin
process(clk)
begin
ifrising_edge(clk)then
count<=count+1;
ifcount>=10000000thenf1hz<='1';
elsef1hz<='0';
endif;
endif;
endprocess;
endarch;
-----------------本模块将40MHZ分频,分成1000HZ,提供扫描(片选)的时间-----------------------
LibraryIEEE;
UseIEEE.std_logic_1164.all;
Useieee.std_logic_unsigned.all;
UseIEEE.std_logic_arith.all;
Entitysh1kis
Port(clk:
instd_logic;
f1hz:
outstd_logic);
endsh1k;
architecturearchofsh1kis
signalcount:
integerrange0to39999;
begin
process(clk)
begin
ifrising_edge(clk)then
count<=count+1;
ifcount>=20000thenf1hz<='1';
elsef1hz<='0';
endif;
endif;
endprocess;
endarch;
波形分析:
具体的分频波形如下,由于这里的40MHZ太大,仿真时不便观察这里我们以40KHZ来分频,效果如下:
3.2.5scan6扫描组件
由于LED使用动态显示,因此要采用扫描的方式来点亮各个LED管,人眼的视觉延迟1/32秒。
在本模块中,时、分、秒的每一位数都作为输入,同时提供一个片选(6位),每来一个clk进行一次选位循环,即依次点亮6个LED灯管。
在点亮的对应管上将该位的数字送给一个输出端口max_out.送到显示模块显示。
具体的代码如下:
libraryIEEE;
useIEEE.std_logic_1164.all;
useIEEE.std_logic_arith.all;
useIEEE.std_logic_unsigned.all;
entityscan6is
port(clr,clk:
inSTD_LOGIC;
h_ten,h_one,m_ten,m_one,s_ten,s_one:
inSTD_LOGIC_vector(3downto0);
cs:
outSTD_LOGIC_vector(5downto0);----------------------------片选
mux_out:
outSTD_LOGIC_vector(3downto0));--要显示的那一个时钟位
endscan6;
architecturearchofscan6is
signalsel:
std_logic_vector(2downto0);
begin
process(clr,clk,h_ten,h_one,m_ten,m_one,s_ten,s_one)
begin
ifclr='0'thensel<="000";
elsifrising_edge(clk)then
sel<=sel+"001";
caseselis
when"000"=>mux_out<=s_one;cs<="100000";
when"001"=>mux_out<=s_ten;cs<="010000";
when"010"=>mux_out<=m_one;cs<="001000";
when"011"=>mux_out<=m_ten;cs<="000100";
when"100"=>mux_out<=h_one;cs<="000010";
when"101"=>mux_out<=h_ten;cs<="000001";
whenothers=>mux_out<="1110";
endcase;
endif;
endprocess;
endarch;
波形仿真如下:
其中为23时46分28秒
3.2.6bin2led组件
该组件的作用是将4位的二进制码转为八位的LED数码管的显示码,即译码模块。
将二进制数变为显示的0~9的数值。
Bin为输入,led为输出,具体代码如下:
LibraryIEEE;
UseIEEE.std_logic_1164.all;
UseIEEE.std_logic_unsigned.all;
UseIEEE.std_logic_arith.all;
entitybin2ledis
port(bin:
instd_logic_vector(3downto0);
led:
outstd_logic_vector(7downto0));
endbin2led;
architecturearchofbin2ledis
begin
PROCESS(bin)
BEGIN
CASEbinIS
WHEN"0000"=>led<="00111111";-----0
WHEN"0001"=>led<="00000110";-----1
WHEN"0010"=>led<="01011011";-----2
WHEN"0011"=>led<="01001111";-----3
WHEN"0100"=>led<="01100110";
WHEN"0101"=>led<="01101101";
WHEN"0110"=>led<="01111101";
WHEN"0111"=>led<="00000111";
WHEN"1000"=>led<="01111111";
WHEN"1001"=>led<="01101111";-----9
WHENOTHERS=>NULL;
ENDCASE;
ENDPROCESS;
endarch;
仿真波形如下:
3.2.7alarm_set组件
为了设定闹钟,我们设计一个目标调整程序,以1Hz的显示速率来调整时分秒的显示。
这里的alarm为指拨开关,当为on时,六个数字即显示00:
00:
00,以等待输入,当持续按键后,秒从0到59依次增加,再返回0,任何时刻松开按键,即为要显示的值。
调分键和调时键的动作原理相同。
此时OK指拨开关的然在off状态。
代码如下:
libraryIEEE;
useIEEE.std_logic_1164.all;
useIEEE.std_logic_arith.all;
useIEEE.std_logic_unsigned.all;
Entityalarm_setis
Port(rst,hz1:
instd_logic;--systemclock1Hz
alarm,ok:
instd_logic;--keeppushingtodeclarealarmset
sec_tune:
instd_logic;
sec_one,sec_ten:
outstd_logic_vector(3downto0));
End;
----definethesignal_structureand_flowofthedevice
architecturearchofalarm_setis
signalsec_one_tmp:
std_logic_vector(3downto0);
signalsec_ten_tmp:
std_logic_vector(3downto0);
begin
tuning:
process(rst,hz1,alarm,ok)
begin
ifrst='1'thensec_one_tmp<="0000";sec_ten_tmp<="0000";
elsifrising_edge(hz1)then
ifalarm='0'andok='1'then
ifsec_tune='1'then
ifsec_one_tmp="1001"thensec_one_tmp<="0000";
ifsec_ten_tmp<"0101"then
sec_ten_tmp<=sec_ten_tmp+"0001";
elsesec_ten_tmp<="0000";
endif;
elsesec_one_tmp<=sec_one_tmp+"0001";
endif;
endif;
else
null;
endif;
endif;
endprocesstuning;
sec_one<=sec_one_tmp;
sec_ten<=sec_ten_tmp;
endarch;
仿真波形图如下:
3.2.8entity顶层模块
最后我们将各模块结合起来,已完成最后的系统功能。
并