当前位置:文档之家› 数字钟设计报告

数字钟设计报告

课程名称: EDA技术实用教程

题目:基于FPGA的数字钟设计系、专业:电子系应用电子技术年级、班级:

学生姓名:

指导老师:

时间: 2008年12月

目录

1、系统设计………………………………………………………..

1.1设计要求……………………………………………………

1.1.1任务………………………………………………..

1.1.2要求……………………………………………….

1.1.3题目分析…………………………………………

2、总体设计方案……………………………………………………

2.1方案一…………………………………………………………

2.2 方案二…………………………………………

2.3 方案三…………………………………………

2.4 方案四………………………………………

3、设计思路……………………………………………………

4、硬件电路的介绍……………………………………………

5、软件模块………………………………………………………

6、心得体会……………………………………………………... 7、参考文献……………………………………………………..

用VHDL语言编写的数字钟程序…………………………

摘要:EDA技术在电子系统设计领域越来越普及,本设计主要利用VHDL语言

在EDA平台上设计一个电子数字钟,它的计时周期为24小时,显示满刻度为23时59分59秒,另外还具有校时功能和闹钟功能。总的程序由几个各具不同功能的单元模块程序拼接而成,其中包括分频程序模块、时分秒计数和设置程序模块、比较器程序模块、三输入数据选择器程序模块、译码显示程序模块和拼接程序模块。并且使用QuartusII软件进行电路波形仿真,下载到EDA实验箱进行验证。该设计采用自顶向下、混合输入方式(原理图输入—顶层文件连接和VHDL语言输入—各模块程序设计)实现数字钟的设计、下载和调试。

关键词: FPGA芯片、VHDL语言、闹钟、模块程序

一、系统设计

1.1 设计要求

1.1.1 任务

设计并制作一个数字钟,通过设计,掌握电子设计的一般思路,学习电子设计的一般方法。

1.1.2要求

(1)基本要求

①计时功能:这是数字钟的基本功能,每隔一秒钟计时一次,并在显示屏上显示当前时间。

②校时功能:能设置实时时间作为数字钟的当前时间,具有小时、分钟的手动校准时间功能。

(2)发挥部分

①计时进制的选择功能:十二小时制或二十四小时制可选择控制;

②整点报警功能:每逢整点自动报警;

③其他创新功能。

1.1.3题目分析

题目要求设计一个能每隔一秒钟计时一次,并在显示屏上显示当前时间, 能设置实时时间作为数字钟的当前时间,具有小时、分钟的手动校准时间功能的数字钟。小时由24进制计数器、分秒由60进制计数器产生,频率是用1Hz方波频率输入组成的电路。

二、总体设计方案

方案一采用74LS90数码管译码电路构成硬件数字钟

晶体振荡器是构成数字式时钟的核心,它保证了时钟的走时准确及稳定. 下图所示电路通过晶振构成的输出为方波的数字式晶体振荡电路,这个电路中,电容C1,C2与晶体构成一个谐振型网络,完成对振荡频率的控制功能,由于晶体具有较高的频率稳定性及准确性,从而保证了输出频率的稳定和准确. 晶体XTAL的频率选为32768HZ.该元件专为数字钟电路而设计,其频率较低,有利于减少分频器级数. 从有关手册中,可查得C1,C2均为20pF.当要求频率准确度和稳定度更高时,还可接入校正电容并采取温度补偿措施.

晶体振荡器图

通常,数字钟的晶体振荡器输出频率较高,为了得到1Hz的秒信号输入,需要对振荡器的输出信号进行分频. 通常实现分频器的电路是计数器电路,一般采用多级2进制计数器来实现.例如,将32768Hz的振荡信号分频为1HZ的分频倍数为32768(215),即实现该分频功能的计数器相当于15极2进制计数器.

本实验中采用CD4060来构成分频电路.CD4060在数字集成电路中可实现的分频次数最高,而且CD4060还包含振荡电路所需的非门,使用更为方便. 2进制计数器,可以将32768HZ的信号分频为2HZ,其内部框图如图3-3所示,从图中可以看出,CD4060的时钟输入端两个串接的非门,因此可以直接实现振荡和分频的功能. 此方案采用中小模块集成电路,十分复杂,而且元件又难以购买,成功率不高,也不经济。

原理图如下:

方案一的电路图

方案二:采用AT89C52单片机、数码管设计数字钟。

本方案采用AT89C52单片机,单片机的P1口接数码管显示电路,P0口接键控制数码管的显示,P3口接入整点报时电路,P2接入复位和晶振电路。我们还未学习单片机的应用,所以不可取。

方案二电路图

方案三:采用555和74LS49设计数字钟

利用555设计一个多谐振荡器,其产生的秒脉冲触发计数,一个60进制的秒计数器和一个10进制的分计数器,校时电路采用秒清零后分计数,最后通过74LS49译码在数码管上显示输出。

此设计方法在实现校时步骤较多,先将秒计数器清零,然后移除由秒计数器Qc传给分计数器的脉冲CP1,将555产生的秒脉冲传给分计数器CP1,实现时借助与非逻辑门来实现,开关让电路图意思明了,三个与非门让电路更加完善。但是,此方案采用555设计的多谐振荡器,其振荡频率与实际的数字钟频率略有出入,虽然可以通过校时装置校时,但是电路原件颇多,难以调节.

方案三电路图

方案四:采用EDA实验箱设计数字钟

利用FPGA芯片,采用VHDL语言实现数字逻辑功能。设计分频模块、秒模块程序、扫描模块程序、显示模块程序、定时闹钟模块程序等模块实现其功能。此方案采用EDA实验箱来实现数字钟的各项功能,成功率比较高,操作也方便,也符合我们该学期的教学.

方案四整体原理框图

三、设计思路

题目要求设计要求一个12进制或24进制的具有时、分、秒计时功能,并要求能进行时、分、秒调整,每逢时有报时功能的数字钟。根据设计要求和方案比较,设计思路如下:

总体设计思路方框图

该设计中由12MHZ时钟信号、闹钟时钟切换键、调时键、调分键,四个输入信号进FPGA,FPGA输出信号送给蜂鸣器和数码管模块,在FPGA里由时、分、

秒构成计数器模块,校时功能调时、调分模块,闹钟\时钟切换模块还能调时、分准确闹铃模块,再由调时、调分、闹钟\时钟切换进行按键去抖模块,时钟信号进行分频送给时、分、秒计数器模块,整个设计逐步达到设计要求,得到具有时、分、秒可调可闹铃的数字钟。

四、硬件电路的介绍

4.1分频模块(原理图输入)

用12MHZ的时钟信号进行12000000分频得到1HZ的时钟信号,为秒计数器的个位提供时钟信号;另一路将12MHZ的时钟信号分频得到1000HZ的时钟信号,为数码管提供扫描基准频率; 另一路将12MHZ的时钟信号分频得到2HZ的时钟信号,为蜂鸣器提供闹铃信号; 另一路将12MHZ的时钟信号分频得到60HZ的时钟信号,为蜂鸣器提供闹铃信号。

4.2 去抖模块

通过设置一个移位寄存器完成延时20ms来解决按键抖动引起的乱码.

4.3 按键设置模块

通过设置两个两位的拨码开关,来控制进入秒表计时或者时间校准或者闹铃设置或者微妙计时状态。

4.4 扫描模块

通过用高频1000HZ的时钟信号来选中8位数码管,使人眼产生错觉认为8位数码管是同时亮。

4.5 秒表计时模块

通过设置秒表计时模块来实现秒表计算功能。

4.6 校时模块

通过设置四个按键来完成校时模块从而实现对分钟、小时进行校准。

4.7 闹铃设置模块

通过设置四个按键来完成校时模块从而实现对分钟、小时进行设置闹铃。

4.8 微妙计时(0.01S计时)模块

通过设置0.01S计时模块来完成马表计时。

4.9 数码管显示模块

通过设置数码管显示模块来完成对整个数字钟计时显示。

外部输入信号有1kHz/1Hz时钟信号、低电平有效的秒/微秒清零信号

CLR、低电平有效的调分信号SETmin、低电平有效的调时信号SEThour;

4.10 总体模块电路

五、软件设置

五、软件模块

本程序分为三大部分:头文件、实体、结构体。

本程序主要由7个进程完成了基本数字钟的秒表计时、校时、闹铃设置、复位、微妙计时的强大功能。

具体程序请见附件(1)。

六、心得体会

这次FPGA数字钟的设计历时十多天,在一周多的日子里,可以说是苦多于甜,但是可以学到很多很多的东西.在此次设计中,在收获知识的同时,还收获了阅历,收获了成熟,在此过程中,我们通过查找大量资料,请教老师,以及不懈的努力,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在设计中,我们学会了很多学习的方法。而这是日后最实用的,真的是受益匪浅。

此次课程设计与以往不同,没有分组一个人独立完成,这应该是老师为了更好的锻炼我们,提高我们的综合能力,当然压力就蛮大了,所以在设计中遇到了很多的难题,首先就是电路的设计, 本设计要求一个12进制或24进制的具有时、分、秒计时功能的数字钟,并要求能进行时、分、秒调整,设置闹铃功能。在方案的选择上就出难题了,通过查资料,找老师讲解,自己实验后,终于把总体模块电路图制出来,写报告到没有多大的难题,很顺利的完成,其实不管怎样,这些都是一种锻炼,一种知识的积累,能力的提高。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,从而提高自己的实际动手能力和独立思考的能力。由于时间的紧缺,并没有做到最好,但是,最起码我没有放弃,它是我的骄傲!相信以后我会以更加积极地态度对待学习、对待生活。我们的激情永远不会结束,相反,我们会更加努力,努力的去弥补自己的缺点,发展自己的优点,去充实自己,只有在了解了自己的长短之后,我们会更加珍惜拥有的,更加努力的去完善它,增进它。只有不断的测试自己,挑战自己,才能拥有更多的成功和快乐!快乐至上,享受过程,而不是结果!认真对待每一个过程,珍惜每一分一秒,学到最多的知识和方法,锻炼自己的能力,这个是我在此次课程设计上学到的最重要的东西,也是以后的一笔宝贵的财富.

总的来说,这次的FPGA数字钟设计还是比较成功的,在设计中遇到了很多问题,最后在老师的辛勤的指导下,终于游逆而解,有点小小的成就感,终于觉得平时所学的知识有了实用的价值,达到了理论与实际相结合的目的,不仅学到了不少知识,而且锻炼了自己的能力,使自己对以后的路有了更加清楚的认识,同时,对未来有了更多的信心。最后,对给过我帮助的各位指导老师和所有同学再次表示忠心的感谢!

七、参考文献

1. 谢自美电子线路设计实验测试(第二版) 华中科技大学出版社 2002

2. 潘松黄继业. EDA技术实用教程(第二版) 北京科学出版社 2005

3. 王锁萍电子设计自动化(EDA)教程西安电子科技大学出版社2006

4. 劳五一、劳佳编著《EDA技术实用教程》,清华大学出版社,2007年第1版;

附(1)程序如下:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

use ieee.std_logic_unsigned.all;

entity szz is

port(clk:in std_logic;--12M时钟

rst:in std_logic;--复位

key1,key2:in std_logic;--闹钟时钟切换开关调节

speak:out std_logic;--蜂鸣器

dout:out std_logic_vector(7 downto 0);--段码

selout:out std_logic_vector(2 downto 0));--位选

end szz;

architecture one of szz is

signal count:integer range 0 to 11999999;--1HZ秒

signal count1:integer range 0 to 199999;--60HZ秒

signal counf1:integer range 0 to 59999;--10ms

signal counf:integer range 0 to 1199;--10000HZ

signal sel:std_logic_vector(2 downto 0);--位选

SIGNAL md1: STD_LOGIC_VECTOR (1 downto 0);---

signal md2:std_logic_vector(1 downto 0);--时分加减开关调节signal zhou1:std_logic_vector(3 downto 0);--计数中小时的十位signal zhou2:std_logic_vector(3 downto 0);--小时的个位

signal zmin1:std_logic_vector(3 downto 0);--分钟的十位

signal zmin2:std_logic_vector(3 downto 0);--分钟的个位

signal zsec1:std_logic_vector(3 downto 0);--秒的十位

signal zsec2:std_logic_vector(3 downto 0);--秒的个位

signal seth1:std_logic_vector(3 downto 0);--设时中小时的十位signal seth2:std_logic_vector(3 downto 0);--小时的个位

signal setm1:std_logic_vector(3 downto 0);--分钟的十位

signal setm2:std_logic_vector(3 downto 0);--分钟的个位

signal h1:std_logic_vector(3 downto 0); ---显示小时十位

signal h2:std_logic_vector(3 downto 0);---小时的个位

signal m1:std_logic_vector(3 downto 0);--分钟的十位

signal m2:std_logic_vector(3 downto 0);--分钟的个位

signal s1:std_logic_vector(3 downto 0);--秒的十位

signal s2:std_logic_vector(3 downto 0);--秒的个位

signal s01:std_logic_vector(3 downto 0);--0.1秒

signal s02:std_logic_vector(3 downto 0);--0.01秒

SIGNAL a,b,c: STD_LOGIC_VECTOR (0 TO 3);---

signal clk1,clkk,clk60,clk5,beep,a1,b1,a2,b2,a3,b3:std_logic;

------------------------------------------------

begin

-----------------------------------------------分频

fp:process(clk)

begin

if rising_edge(clk) then

count<=count+1;

counf<=counf+1;

count1<=count1+1;

counf1<=counf1+1;

if count=11999999 then clk1<='1';---1Hz

count<=0;

beep<='1';

elsif count>5999999 then beep<='0'; ---2Hz

else clk1<='0';

end if;

if count1=199999 then clk60<='1';--60HZ

count1<=0;

else clk60<='0';

end if;

if counf1=59999 then

counf1<=0;

clk5<=not clk5;

end if;

if counf=1199 then clkk<='1';--10000HZ

counf<=0;

else clkk<='0';

end if;

end if;

end process fp;----------------------------------------------去抖PROCESS (clk5,a1,b1)

V ARIABLE a: INTEGER RANGE 0 to 3;

BEGIN

IF CLK5'EVENT AND CLK5='1' THEN

a:=a+1;

case a is

when 1 => a1<=key1;

when 2 => b1<=a1;

a1<=key1;

when others =>null;

end case;

end if;

end process;-------------------------------------------- PROCESS (clk5,a2,b2)

V ARIABLE b: INTEGER RANGE 0 to 3;

BEGIN

IF CLK5'EVENT AND CLK5='1' THEN

b:=b+1;

case b is

when 1 => a2<=key2;

when 2 => b2<=a2;

a2<=key2;

when others =>null;

end case;

end if;

end process;----------------------------------------------- PROCESS (clk5,a3,b3)

V ARIABLE c: INTEGER RANGE 0 to 3;

BEGIN

IF CLK5'EVENT AND CLK5='1' THEN

c:=c+1;

case c is

when 1 => a3<=rst;

when 2 => b3<=a3;

a3<=rst;

when others =>null;

end case;

end if;

end process;---------------------------------------------按键设置process (key1,key2)

begin

if clk1'event and clk1='1' then

if (key1='0' and a1='0' and b1='0') then

if md1="11" then

md1<="00";

else

md1<=md1+1;

end if;

end if;

if (key2='0' and a2='0' and b2='0') then

if md2="10" then

md2<="00";

else

md2<=md2+1;

end if;

end if;

end if;

end process;----------------------------------------------模8计数choice:process(clkk)---位选

begin

if clkk'event and clkk='1' then

if sel="111" then

sel<="000";

else

sel<=sel+1;

end if;

end if;

end process choice;-------------------------------------秒个位

s2201:process(clk1,rst)

begin

if clk1'event and clk1='1' then

if zsec2="1001" then ---其中sec2是秒的个位

zsec2<="0000";

else

zsec2<=zsec2+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0')then zsec2<="0000"; ---秒个位复位

end if;

end process s2201;

---------------------------------------------秒十位

s1101:process(clk1,rst)

begin

if clk1'event and clk1='1' then

if (zsec1="0101" and zsec2="1001" ) then

zsec1<="0000";

elsif zsec2="1001" then

zsec1<=zsec1+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then zsec1<="0000"; ---秒十位复位

end if;

end process s1101;

----------------------------------------------分钟个位

zm220:process(clk1,zsec1,zsec2,md1,md2,rst)

begin

if clk1'event and clk1='1' then

if zmin2="1001"and (zsec1="0101" and zsec2="1001") then----其中min2是分钟的个位

zmin2<="0000";

elsif zmin2="1001" and (md1="01" and md2="00") then---

zmin2<="0000";

else if (zsec1="0101" and zsec2="1001" ) or(md1="01" and md2="00") or(md1="01" and md2="10")then

zmin2<=zmin2+1;

end if;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then zmin2<="0000";

end if;

end process zm220;

-----------------------------------------------分钟十位

zm110:process(clk1,zsec1,zsec2,md1,md2,rst)

begin

if clk1'event and clk1='1' then

if (zmin1="0101" and zmin2="1001") and (zsec1="0101" and zsec2="1001") then zmin1<="0000";

elsif zmin1="0101" and zmin2="1001"and (md1="01" and md2="00") then zmin1<="0000";

elsif (zmin2="1001" and (zsec1="0101" and zsec2="1001")) or (zmin2="1001"and md1="01" and md2="00") or (zmin2="1001" and md1="01" and md2="10") then

zmin1<=zmin1+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then zmin1<="0000";

end if;

end process zm110;

-----------------------------------------------小时个位

zh220:process(clk1,zmin1,zmin2,zsec1,zsec2,md1,md2,zhou1,rst)

begin

if clk1'event and clk1='1' then

if (zhou1="0010" and zhou2="0011")and(zmin1="0101" and zmin2="1001") and (zsec1="0101" and zsec2="1001") then

zhou2<="0000";

elsif zhou2="1001"and(zmin1="0101" and zmin2="1001") and (zsec1="0101" and zsec2="1001") then

zhou2<="0000";

elsif (zhou2="1001")or (zhou1="0010" and zhou2="0011" and md1="01" and md2="01") then

zhou2<="0000";

elsif ((zmin1="0101" and zmin2="1001") and (zsec1="0101" and zsec2="1001") )or (md1="01" and md2="01") then

zhou2<=zhou2+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then zhou2<="0000";

end if;

end process zh220;

-----------------------------------------------小时十位

zh110:process(clk1,zhou2,zmin1,zmin2,zsec1,zsec2,md1,md2,rst)

begin

if clk1'event and clk1='1' then

if (zhou1="0010" and zhou2="0011")and(zmin1="0101" and zmin2="1001") and (zsec1="0101" and zsec2="1001") then

zhou1<="0000";

elsif zhou1="0010"and zhou2="0011"and md1="01" and md2="01" then--当时间为23点且处于校时状态时

zhou1<="0000";

elsif (zhou2="1001"and(zmin1="0101" and zmin2="1001") and (zsec1="0101" and zsec2="1001"))or ((zhou2="1001"and md1="01" and md2="01")) then zhou1<=zhou1+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then zhou1<="0000";

end if;

end process zh110;

-------------------------------------------时间设置小时部分

sethour1:process(clk1,seth1,seth2,rst)

begin

if clk1'event and clk1='1' then

if seth1="0010"and seth2="0011" then

seth1<="0000";

elsif seth2="1001" then

seth1<=seth1+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then seth1<="0000";

end if;

end process sethour1;

-------------------------------------------

sethour2:process(clk1,md1,md2,seth1,rst)

begin

if clk1'event and clk1='1' then

if (seth1="0010"and seth2="0011")or seth2="1001" then ---其中seth1,seth2分别是调时的小时部位的十位与个位

seth2<="0000";

elsif md1="10" and md2="00" then

seth2<=seth2+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then seth2<="0000";

end if;

end process sethour2;

-------------------------------------------时间设置分钟部分

setmin1:process(clk1,setm2,rst)

begin

if clk1'event and clk1='1' then

if setm1="0101"and setm2="1001" then

setm1<="0000";

elsif setm2="1001" then

setm1<=setm1+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then setm1<="0000";

end if;

end process setmin1;

----------------------------------------------

setmin2:process(clk1,md1,md2,rst)

begin

if clk1'event and clk1='1' then

if setm2="1001" then

setm2<="0000";

elsif md1="10" and md2="01" then

setm2<=setm2+1;

end if;

end if;

if (rst='0' and a3='0' and b3='0') then setm2<="0000";

end if;

end process setmin2;

--------------------------------------------闹铃

speaker:process(clkk,zhou1,zhou2,zmin1,zmin2,rst)

begin

if clkk'event and clkk='1' then

if seth1=zhou1 and seth2=zhou2 and setm1=zmin1 and setm2=zmin2 then speak<=beep;

else speak<='0';

end if;

end if;

if (rst='0' and a3='0' and b3='0') then speak<='0';

end if;

end process speaker;

-------------------------------------------

disp:process(sel,md1,zhou1,zhou2,zmin1,zmin2,zsec2,zsec1)---显示

begin

if sel="000" then

selout<="000";--位选

case h1 is ---显示小时的十位

when "0000"=>dout<="00111111";---0

when "0001"=>dout<="00000110";---1

when "0010"=>dout<="01011011";---2

when others =>dout<="00000000";---不显示

end case;

elsif sel="001" then

selout<="001";

case h2 is ---显示小时的个位

when "0000"=>dout<="00111111";---0

when "0001"=>dout<="00000110";---1

when "0010"=>dout<="01011011";---2

when "0011"=>dout<="01001111";---3

when "0100"=>dout<="01100110";---4

when "0101"=>dout<="01101101";---5

when "0110"=>dout<="01111101";---6

when "0111"=>dout<="00000111";---7

when "1000"=>dout<="01111111";---8

when "1001"=>dout<="01101111";---9

when others=>dout<="00000000";---不显示

end case;

elsif sel="010" then

dout<="10000000";

elsif sel="011" then

selout<="011";

case m1 is ---显示分钟的十位

when "0000"=>dout<="00111111";

when "0001"=>dout<="00000110";

when "0010"=>dout<="01011011";

when "0011"=>dout<="01001111";

when "0100"=>dout<="01100110";

when "0101"=>dout<="01101101";

when others=>dout<="00000000";

end case;

elsif sel="100" then

selout<="100";

case m2 is ---显示分钟的个位

when "0000"=>dout<="00111111";

when "0001"=>dout<="00000110";

when "0010"=>dout<="01011011";

when "0011"=>dout<="01001111";

when "0100"=>dout<="01100110";

when "0101"=>dout<="01101101";

when "0110"=>dout<="01111101";

when "0111"=>dout<="00000111";

when "1000"=>dout<="01111111";

when "1001"=>dout<="01101111";

when "1010"=>dout<="10000000";

when others=>dout<="00000000";

end case;

elsif sel="101" then

selout<="101";

dout<="10000000";

elsif sel="110" then

selout<="110";

case s1 is ---显示秒的十位

when "0000"=>dout<="00111111";

when "0001"=>dout<="00000110";

when "0010"=>dout<="01011011";

when "0011"=>dout<="01001111";

when "0100"=>dout<="01100110";

when "0101"=>dout<="01101101";

when others=>dout<="00000000";

end case;

elsif sel="111" then

相关主题
文本预览
相关文档 最新文档