基于FPGA的电子时钟方案设计书.docx
《基于FPGA的电子时钟方案设计书.docx》由会员分享,可在线阅读,更多相关《基于FPGA的电子时钟方案设计书.docx(28页珍藏版)》请在冰点文库上搜索。
基于FPGA的电子时钟方案设计书
CivilAviationUniversityofChina
电子技术应用设计报告
基于FPGA的电子时钟设计
专业:
通信工程
学号:
xxxxxxx
学生姓名:
xxx
所属学院:
电信学院
任课教师:
xxx
摘要
本设计采用EDA技术,采用原理图和硬件描述语言VHDL混合编程设计时钟逻辑系统,在QuartusII5.0工具软件环境下,采用自顶向下的设计方法,由各个基本模块共同构建了一个基于FPGA的电子时钟。
本时钟系统主芯片采用EP1C6Q240C8N,具有显示时间、日期、时间及日期校准、整点报时、定时闹钟等功能。
其中时间采用24小时循环计数,日期计数器具有闰年、月大、月小的判断并准确计数功能。
通过按键控制可以实现:
日期和时间的切换显示、日期和时间的校准、闹钟的开关控制。
关键词:
FPGA;电子时钟;原理图;VHDL语言;
Abstract
InmydesignEDAtechnologyisused,andIdesignedtheclocklogicsystembymeansofschematicandVHDLhardwaredescriptionlanguage.UnderQuartusII5.0Toolssoftwareenvironment,Iusedthetop-downdesignmethodology,wherevariousbasicmodulesworktogethertobuildaFPGA-basedelectronicclock.
ThemainchipoftheclocksystemisEP1C6Q240C8N,whichhasthefunctionoftimedisplay,datedisplay,timeanddatecalibration,thewholepointoftime,andregularalarmclock.Furthermore,24-hourcycle,datecounterwhichtimehasleap-year,month,asmallmonth'sjudgmentandaccuratecountingfunctionaredesigned.Whatwecanachievethroughthecontrolbuttonsareasfollows:
switchingthedisplayofdateandtime,calibrationofdateandtime,andthealarmswitchcontrol.
Keywords:
FPGA。
electronicclock。
schematic。
VHDLlanguage。
基于FPGA的电子时钟设计
1.FPGA介绍
FPGA(Field-ProgrammableGateArray),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。
它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
FPGA采用了逻辑单元阵列LCA(LogicCellArray)这样一个概念,内部包括可配置逻辑模块CLB(ConfigurableLogicBlock)、输出输入模块IOB(InputOutputBlock)和内部连线(Interconnect)三个部分。
现场可编程门阵列(FPGA)是可编程器件。
与传统逻辑电路和门阵列(如PAL,GAL及CPLD器件)相比,FPGA具有不同的结构,FPGA利用小型查找表(16×1RAM)来实现组合逻辑,每个查找表连接到一个D触发器的输入端,触发器再来驱动其他逻辑电路或驱动I/O,由此构成了既可实现组合逻辑功能又可实现时序逻辑功能的基本逻辑单元模块,这些模块间利用金属连线互相连接或连接到I/O模块。
FPGA的逻辑是通过向内部静态存储单元加载编程数据来实现的,存储在存储器单元中的值决定了逻辑单元的逻辑功能以及各模块之间或模块与I/O间的联接方式,并最终决定了FPGA所能实现的功能,FPGA允许无限次的编程。
2.电子时钟的设计方案
2.1时钟系统整体介绍
本时钟系统主要由分频器模块、计数模块、译码模块、显示模块、校时模块以及闹钟模块构成。
由分频器从48MHZ晶振中得到1HZ信号给计数器提供标准时钟,译码器将计数器数据译码数码管能显示的信号,显示模块扫描译码器数据并显示。
由于计数的起始时间不可能与标准时间(如北京时间)一致,故需要在电路上加一个校时电路,同时标准的1HZ时间信号必须做到准确稳定。
系统框图如下:
图2-1时钟系统框图
2.2分频器
本分频器采用偶数分频,使占空比达到50%很简单,只要使用一个计数器,在计数器的前一半时间里,使输出电平低电平,在计数器的后一半时间里,使输出电平为低电平,这样输出的时钟信号就是占空比为50%的偶数分频时钟信号。
图2-2-1分频器电路设计
本分频器有48分频、100分频、10分频三个程序模块构成,输入48MHz,输出1KHz、100Hz、1Hz时钟信号。
由于本分频器的判断条件为ifcount<(integer(N/2))then,所以当N为奇数时,得到脉冲占空比不为50%。
(VHDL程序见附录1)
图2-2-2分频器电路模块
2.3时间计数模块
时间计数模块由60进制计数器和24进制计数器构成。
当秒计数器到59后,进位并归零,分计数器得到秒计数器的进位信号后计数加1,时计数器同理。
(VHDL程序见附录2)
图2-3-1六十进制计数器图2-3-2二十四进制计数器
Ø
1khz为蜂鸣器信号输入端;
Øclk为1HZ时钟信号输入端;
Øreset为异步清零信号输入端;
Øsadd、sdec、madd、mdec、hadd、hdec均为同步校时控制信号输入端,其中sadd为秒加,sdec为秒减,madd为分加,mdec为分减,hadd为时加,hdec为时减。
图2-3-3计数器模块
2.4日期计数模块
本日期计数模块具有闰年、闰月、月大、月小判断并计数功能。
日期控制信号为sel[2..0]输入端,当sel[0]=0时,表示闰年,当sel[1]=1表示4,6,9,11四个月就,sel[1]=0则表示1、2、3、5、7、8、10、12八个月,当sel[2]=1则表示2月。
(VHDL程序见附录3)
图2-4-1年月日计数模块
2.5译码器模块
本译码器模块采用VHDL语言编写,译码具有灵活性,方便更改译码结果。
输入数据为4位,输出数据为8位。
输入0000到1001译码为0到9,输入1010到1110译码为A、b、C、D、E,输入1111译码为横线。
(VHDL程序见附录4)
图2-5译码器模块
2.6显示模块
本显示模块由一个74161计数器构成8进制计数模块,输入1KHz信号,计数器通过74138使数码管轮流工作,同时通过宏模块选通时间数据在数码管上显示。
由于数码管只有8个,要想在8个数码管上显示时分秒年月日这么多数据,必须要有切换显示模块。
本系统利用按键控制宏模块选通时间和日期两路数据分别在数码管上显示。
图2-6-1显示模块电路图
图2-6-2显示模块
2.7校时模块
校时模块由8个按键组成。
当按键按下输出低电平,未按下时输出高电平。
图2-7-1按键消抖模块
按键消抖模块由1KHz时钟信号控制,经过D触发器和与非门处理后,使得按键按下后输出高电平。
未按下时输出低电平。
图2-7-2八路按键模块
图2-7-3按键选通模块
由于时分秒信息和年月日信息分开显示,所以调整时间时必须分别对时分秒、年月日进行校准。
然而控制信号只有八路,这样就必须使按键信号能分别送进时间计数模块和日期计数模块。
于是编写下面这部分程序:
LIBRARYIEEE。
USEIEEE.STD_LOGIC_1164.ALL。
ENTITYchannelIS
PORT(s:
INSTD_LOGIC。
data_in:
INSTD_LOGIC_VECTOR(6DOWNTO0)。
cal_out:
OUTSTD_LOGIC_VECTOR(6DOWNTO0)。
time_out:
OUTSTD_LOGIC_VECTOR(6DOWNTO0))。
ENDENTITY。
ARCHITECTUREoneOFchannelIS
BEGIN
PROCESS(s)
BEGIN
CASEsIS
WHEN'0'=>cal_out<=data_in。
time_out<="0000000"。
WHENOTHERS=>time_out<=data_in。
cal_out<="0000000"。
ENDCASE。
ENDPROCESS。
ENDARCHITECTURE。
这样就使得当控制按钮按下时,通过显示模块切换显示画面,同时按键分别控制时间计数模块和日期计数模块。
2.8闹钟模块
闹钟模块由整点报时和定时闹钟两部分组成。
图2-8-1整点报时模块
当时计数器进位时,进位信号被取出送到蜂鸣器控制端,控制端使能输入1KHz信号到蜂鸣器,这样就到达整点报时功能。
图2-8-2定时闹钟模块
为了便于演示本闹钟模块定时时间为10秒,具有开启和关闭功能。
当按键按下时T触发器翻转,使能计数器,当计数器计满10秒时进位使能蜂鸣器实现闹钟效果。
当再次按下按键,T触发器再次翻转,计数器关闭,闹钟关闭。
3实习总结
3.1本系统的优点
1.分频器实现容易,可以任意分频,连线少。
2.时间计数器和日期计数器具有校准信号输入端,能实现校时和重启功能
3.日期计数器能准确的实现闰年、闰月、月大、月小的计数
4.译码器具有灵活性,不受器件限制,可以任意译码,实现自己想要的效果。
3.2本系统的不足
1.分频器具有局限性,不能很好的对奇数个脉冲进行分频。
2.进位信号与归零信号不能同步。
计数器计满归零时,进位信号不能立即进位,要晚一个时钟信号。
3.校时操作比较繁琐。
首先是控制按键比较多,然后是校准时间时,需要等到秒时钟信号到来时计数器才会加一或减一,使得校准时间比较慢。
4.闹钟不能设定,为了便于演示,只做了一个10秒计数器。
3.3想实现却又没实现的功能
1.对时间进行校准时,由于受秒时钟限制,校准操作比较慢。
因此尝试过以下两种方案:
i.输入1Hz、2Hz两个时钟信号,1Hz信号用于计数器计数,2Hz信号用于校准时间,但是程序老是报错,实验失败。
ii.校准信号不受时钟信号控制,当按键按下时,就使计数器加一或减一。
由于按键消抖不是很好,每按下一次按键,计数器增加几十位,不是预期效果,实验失败。
2.闹钟模块有两个预想功能没有实现:
i.定时时间可以设定。
ii.闹钟工作时播放一首歌曲。
失败原因:
1.时间不足;2.对电子琴不了解,要完成电子琴模块,需要大量时间。
附录1:
分频器
以下是100分频程序:
libraryieee。
useieee.std_logic_1164.all。
useieee.std_logic_arith.all。
useieee.std_logic_unsigned.all。
entitydivider100is
GENERIC(N:
integer:
=100)。
port(clk:
instd_logic。
outclk:
outstd_logic)。
enddivider100。
architectureoneofdivider100is
signalcount:
integer。
begin
process(clk)
begin
if(clk'eventandclk='1')then
if(count=N-1)then
count<=0。
else
count<=count+1。
ifcount<(integer(N/2))then
outclk<='0'。
else
outclk<='1'。
endif。
endif。
endif。
endprocess。
endone。
附录2:
时间计数器
附录2.1:
六十进制计数器
libraryieee。
useieee.std_logic_1164.all。
useieee.std_logic_unsigned.all。
entitysecondis
port(enl,res,clk,sadd,sdec:
instd_logic。
a,b:
outstd_logic_vector(3downto0)。
ca:
outstd_logic)。
endsecond。
--enl使能--res清零--clk时钟--sadd加--sdec减--a低位--b高位--ca进位
architectureSECofsecondis
begin
process(enl,clk,res)
variablem0,m1:
std_logic_vector(3downto0)。
begin
ifres='1'thenm0:
="0000"。
m1:
="0000"。
ca<='0'。
elsifclk'eventandclk='1'then
ca<='0'。
ifsadd='1'orenl='1'then
ifm0="1000"andm1="0101"thenca<='1'。
--实际是第59个--脉冲
endif。
ifm0<"1001"thenm0:
=m0+1。
elsem0:
="0000"。
m1:
=m1+1。
ifm1>"0101"thenm0:
="0000"。
m1:
="0000"。
ca<='0'。
endif。
endif。
elsifsdec='1'then
ifm0="0000"andm1="0000"thenm0:
="1001"。
m1:
="0101"。
elsifm0>"0000"thenm0:
=m0-1。
elsem0:
="1001"。
m1:
=m1-1。
endif。
endif。
endif。
a<=m0。
b<=m1。
endprocess。
endSEC。
附录2.1:
二十四进制计数器
libraryieee。
useieee.std_logic_1164.all。
useieee.std_logic_unsigned.all。
entityhouris
port(enl,res,clk,hadd,hdec:
instd_logic。
a,b:
outstd_logic_vector(3downto0)。
ca:
outstd_logic)。
endhour。
--enl使能--res清零--clk时钟--hadd加--hdec减--a低位--b高位--ca进位
architectureSECofhouris
begin
process(enl,clk,res)
variablem0,m1:
std_logic_vector(3downto0)。
begin
ifres='1'thenm0:
="0000"。
m1:
="0000"。
ca<='0'。
elsifclk'eventandclk='1'then
ca<='0'。
ifhadd='1'orenl='1'then
ifm0="0011"andm1="0010"thenca<='1'。
m0:
="0000"。
m1:
="0000"。
endif。
ifm0<"1001"thenm0:
=m0+1。
elsem0:
="0000"。
m1:
=m1+1。
endif。
elsifhdec='1'then
ifm0="0000"andm1="0000"thenm0:
="0011"。
m1:
="0010"。
elsifm0>"0000"thenm0:
=m0-1。
elsem0:
="1001"。
m1:
=m1-1。
endif。
endif。
endif。
a<=m0。
b<=m1。
endprocess。
endSEC。
附录3:
日期计数器
附录3.1:
天计数器
libraryieee。
useieee.std_logic_1164.all。
useieee.std_logic_unsigned.all。
entitydayis
port(enl,res,clk,dadd,ddec:
instd_logic。
sel:
instd_logic_vector(2downto0)。
a,b:
outstd_logic_vector(3downto0)。
ca:
outstd_logic)。
endday。
--sel[0]-year--0表示闰年
--sel[1]-month,1表示4,6,9,11
---------------0表示1、2、3、5、7、8、10、12
--sel[2]-Feb,1表示2月
architectureSECofdayis
signalsr0,sr1:
std_logic_vector(3downto0)。
begin
process(sel)
begin
ifsel="001"orsel="000"thensr0<="0001"。
sr1<="0011"。
-----------31
elsifsel="100"thensr0<="1001"。
sr1<="0010"。
------------29
elsifsel="101"thensr0<="1000"。
sr1<="0010"。
-----------28
elsesr0<="0000"。
sr1<="0011"。
---------------------30
endif。
endprocess。
process(enl,clk,res)
variabler0,r1:
std_logic_vector(3downto0)。
begin
ifres='1'thenr0:
="0001"。
r1:
="0000"。
ca<='0'。
elsifclk'eventandclk='1'then
ca<='0'。
ifdadd='1'orenl='1'then
ifr0=sr0andr1=sr1thenr0:
="0001"。
r1:
="0000"。
ca<='1'。
elsifr0<"1001"thenr0:
=r0+1。
ca<='0'。
elser0:
="0000"。
r1:
=r1+1。
endif。
elsifddec='1'then
ifr0="0001"andr1="0000"thenr0:
=sr0。
r1:
=sr1。
elsifr0>"0000"thenr0:
=r0-1。
elser0:
="1001"。
r1:
=r1-1。
endif。
endif。
endif。
a<=r0。
b<=r1。
endprocess。
endSEC。
附录3.2:
月计数器
libraryieee。
useieee.std_logic_1164.all。
useieee.std_logic_unsigned.all。
entitymonthis
port(enl,res,clk,madd,mdec:
instd_logic。
a,b:
outstd_logic_vector(3downto0)。
ermonth,msel,ca:
outstd_logic)。
endmonth。
--ermonthconnecttosel[2]
--mselconnecttosel[1]
architectureSECofmonthis
begin
process(enl,clk,res)
variabley0,y1:
std_logic_vector(3downto0)。
begin
ifres='1'theny0:
="0001"。
y1:
="0000"。
ca<='0'。
elsifclk'eventandclk='1'then
ca<='0'。
ifmadd='1'orenl='1'then
ify0="0010"andy1="0001"theny0:
="0001"。
y1:
="0000"。
ca<='1'。
elsify0<"1001"theny0:
=y0+1。
ca<='0'。
elsey0:
="0000"。
y1:
=y1+1。
endif。
elsifmdec='1'then
ify0="0001"andy1="0000"theny0:
="0010"。
y1:
="0001"。
elsify0>"0000"theny0:
=y0-1。
elsey0:
="1001"。
y1:
=y1-1。
endif。
endif。
endif。
if((y0="0100"ory0="0110"ory0="1001")andy1="0000")or(y0="0001"andy1="0001")thenmsel<='1'。
else
msel<='0'。
endif。
ify0="0010"andy1="0000"thenermonth<='1'。
else
ermonth<='0'。
endif。
a<=y0。
b<=y1。
endprocess。
endSEC。
附录3.3:
年计数器
libraryieee。
useieee.std_logic_1164.all。
useieee.std_logic_arith.all。
useieee.std_logic_unsigned.all。
entityyearis
port(enl,res,clk,yadd,ydec:
instd_logic。
a,b,c,d:
outs