基于fpga的数字钟的设计大学论文.docx
《基于fpga的数字钟的设计大学论文.docx》由会员分享,可在线阅读,更多相关《基于fpga的数字钟的设计大学论文.docx(17页珍藏版)》请在冰豆网上搜索。
基于fpga的数字钟的设计大学论文
1设计的要求
本次设计主要是研究基于FPGA的数字钟,要求是以24小时为周期,显示时、分、秒。
采用1HZ的基准脉冲信号产生1S的基准时间,当计数达到60次时,输出1个分钟(min)脉冲;当1min的时钟计数到达60次时,输出1个小时(h)脉冲;若1h的时钟计数达到23次时,并且1min的计数到59次、1s的计数也达到59次,再来1个1s的脉冲,数字钟就自己复位,重新从零开始计时。
为了保证计时的稳定及准确须由晶体振荡器提供时间基准信号。
该系统是基于FPGA的设计,采用VHDL进行系统功能的描述,采用自顶向下的设计方法,用QUARTUSII软件进行仿真。
2设计的基本原理
振荡器产生稳定的高频脉冲信号,作为数字钟的时间基准,然后经过分频器输出标准秒脉冲。
秒计数器满59后向分计数器进位,分计数器满59后向小时计数器进位,小时计数器按照“24翻0”规律计数。
计满后各计数器清零,重新计数。
一般说来,一个比较大的完整的项目应该采用层次化的描述方法:
分为几个较大的模块,定义好各功能模块之间的接口,然后各个模块再细分去具体实现,这就是TOPDOWN(自顶向下)的设计方法。
目前这种高层次的设计方法已被广泛采用。
高层次设计只是定义系统的行为特征,可以不涉及实现工艺,因此还可以在厂家综合库的支持下,利用综合优化工具将高层次描述转换成针对某种工艺优化的网络表,使工艺转化变得轻而易举。
CPLD/FPGA系统设计的工作流程如图1所示。
图1FPGA系统设计流程
流程说明:
1.工程按照“自顶向下”的设计方法进行系统划分。
2.输入VHDL代码,这是设计中最为普遍的输入方式。
此外,还可以采用图形输入方式(框图、状态图等),这种输入方式具有直观、容易理解的优点。
3.将以上的设计输入编译成标准的VHDL文件。
4.进行代码级的功能仿真,主要是检验系统功能设计的正确性。
这一步骤适用于大型设计,因为对于大型设计来说,在综合前对源代码仿真,就可以大大减少设计重复的次数和时间。
一般情况下,这一仿真步骤可略去。
5.利用综合器对VHDL源代码进行综合优化处理,生成门级描述的网络表文件,这是将高层次描述转化为硬件电路的关键步骤。
综合优化是针对ASIC芯片供应商的某一产品系列进行的,所以综合的过程要在相应的厂家综合库的支持下才能完成。
6.利用产生的网络表文件进行适配前的时序仿真,仿真过程不涉及具体器件的硬件特性,是较为粗略的。
一般的设计,也可略去这一步骤。
7.利用适配器将综合后的网络表文件针对某一具体的目标器件进行逻辑映射操作,包括底层器件配置、逻辑分割、逻辑优化和布局布线。
8.在适配完成后,产生多项设计结果:
(a)适配报告,包括芯片内部资源利用情况,设计的布尔方程描述情况等;(b)适配后的仿真模型;(c)器件编程文件。
根据适配后的仿真模型,可以进行适配后时序仿真,因为已经得到器件的实际硬件特性(如时延特性),所以仿真结果能比较精确的预期未来芯片的实际性能。
如果仿真结果达不到设计要求,就修改VHDL源代码或选择不同速度和品质的器件,直至满足设计要求。
最后将适配器产生的器件编程文件通过编程器或下载电缆载入到目标芯片CPLD/FPGA中。
3设计方案
3.1设计思路
本次设计采用分模块设计的方法,再用一个顶层文件将各模块联系起来,如下图2所示。
图2数字钟模块图
3.2各模块的模块图与功能
分频器模块
晶体振荡器是构成数字式时钟的核心,振荡器的稳定度及频率的精度决定了数字钟计时的准确程度,它保证了时钟的走时准确及稳定。
石英晶体的选频特性非常好,只有某一频率点的信号可以通过它,其它频率段的信号均会被它所衰减,而且,振荡信号的频率与振荡电路中的R、C元件的数值无关。
因此,这种振荡电路输出的是准确度极高的信号。
然后再利用分频电路,将其输出信号转变为秒信号,其组成框图如下图3所示。
图3秒信号产生框图
本系统使用的晶体振荡器电路给数字钟提供一个频率稳定准确的12MHz的方波信号,其输出至分频电路。
分频电路的逻辑框图如下图4所示。
图4分频电路逻辑框图
六进制计数模块
对秒和分的十位进行计数,计数满六便变为0,产生进位。
六进制计数器的逻辑框图如下图5所示。
图5六进制计数器逻辑框图
十进制计数器模块
对秒和分的个位进行计数,计满10便变为0,并产生进位。
十进制计数器逻辑框图如下图6所示。
图6十进制计数器逻辑框图
二十四进制计数器模块
对时进行计数,计满24便变为0。
二十四进制计数器逻辑框图如下图7所示。
图7二十四进制计数器逻辑框图
译码器模块
将时、分、秒个位的输出译为七段输出。
译码器的逻辑框图如下图8所示。
图8译码器逻辑框图
顶层文件模块
将各模块连接起来,实现整个时钟功能。
顶层文件的逻辑框图如下图9所示。
图9顶层文件逻辑框图
LED七段共阴极数码管显示模块
常见的数码管由七个条状和一个点状发光二极管管芯组成,共阴极LED是指笔画显示器各段发光管的阴极是公共的,而阳极是相互隔离的。
LED数码管模块如下图10所示。
图10LED数码管模块图
4各模块的仿真
4.1分频器模块仿真图
图11分频器模块仿真图
4.2六进制计数器模块仿真图
图12六进制计数器模块仿真图
4.3十进制计数器模块仿真图
图13十进制计数器模块仿真图
4.4二十四进制计数器模块仿真图
图14二十四进制计数器模块仿真图
4.5译码器模块仿真图
图15译码器模块仿真图
4.6顶层文件模块仿真图
图16顶层文件模块仿真图
4.7LED七段共阴极数码管显示模块仿真图
图17数字钟准备状态仿真图
图18数字钟运行状态仿真图
5结论与感悟
本次设计实验经过各模块和整体程序的仿真运行,达到了设计的要求。
运行数字时钟,首先对1s的时钟进行计数,当计数达到60次时,输出1个分钟(min)脉冲;当1min的时钟计数到达60次时,输出1个小时(h)脉冲;若1h的时钟计数达到23次时,并且1min的计数到59次、1s的计数也达到59次,再来1个1s的脉冲,数字钟就自己复位,重新从零开始计时。
在此次设计中,运用了自顶向下的模块化设计,使程序清晰易懂。
虽然程序在设计师具备一定的优点,但是也有着一定的不足,比方说延时问题,这使得数字钟在实际运行时并不十分准确。
所以设计并不完美,还需要一定的改善。
此次课程设计查阅了很多与FPGA,VHDL语言等有关的资料,极大的提高了自己的查询与阅读能力,为以后的毕业设计打下一定的基础。
在此次的数字钟设计过程中,我更进一步地熟悉有关数字电路的知识和具体应用。
学会了利用QuarterII软件进行原理图的绘制,硬件描述语言VHDL的编写,程序的仿真等工作。
并能根据仿真结果分析设计的存在的问题和缺陷,从而进行程序的调试和完善,使自己的设计达到要求。
在此感谢指导老师对我的问题一一解答,使我的课程设计能够顺利的完成。
本次课程设计圆满完成。
参考文献:
【1】刘爱荣,王振成.EDA技术与CPLD/FPGA开发应用简明教程.清华大学出版社.
【2】陈忠平,高金定,高见芳.基于QuuartusⅡ的FPGA/CPLD设计与实践.电子工业出版社.
【3】刘君,常明,秦娟.基于硬件描述语言(VHDL)的数字时钟设计.天津理工大学报.
【4】王开军,姜宇柏.面向CPLD/FPGA的VHDL设计.机械工业出版社.
【5】杨军,蔡光卉,黄倩,陈成.基于FPGA的数字系统设计与实践.电子工业出版社.
附:
各模块程序
分频器程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYDIVIS
PORT(CLK,RESET:
INSTD_LOGIC;
F:
OUTSTD_LOGIC);
ENDDIV;
ARCHITECTUREARTOFDIVIS
SIGNALQ:
INTEGERRANGE0TO10;
BEGIN
PROCESS(CLK)
BEGIN
IF(CLK'EVENTANDCLK='1')THEN
IF(RESET='0')THENQ<=0;
ELSIFQ<=4THENF<='1';
Q<=Q+1;
ELSIFQ=9THENF<='0';
Q<=0;
ELSEF<='0';
Q<=Q+1;
ENDIF;
ENDIF;
ENDPROCESS;
ENDART;
六进制计数器程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCOUNTER6IS
PORT(CLK:
INSTD_LOGIC;
RESET:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(2DOWNTO0);
DOUT:
OUTSTD_LOGIC_VECTOR(2DOWNTO0);
C:
OUTSTD_LOGIC);
ENDCOUNTER6;
ARCHITECTUREBEHAVIORALOFCOUNTER6IS
SIGNALCOUNT:
STD_LOGIC_VECTOR(2DOWNTO0);
BEGIN
DOUT<=COUNT;
PROCESS(CLK,RESET,DIN)
BEGIN
IFRESET='0'THEN
COUNT<=DIN;
C<='0';
ELSIFRISING_EDGE(CLK)THEN
IFCOUNT="101"THEN
COUNT<="000";
C<='1';
ELSE
COUNT<=COUNT+1;
C<='0';
ENDIF;
ENDIF;
ENDPROCESS;
ENDBEHAVIORAL;
十进制计数器程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCOUNTER10IS
PORT(CLK:
INSTD_LOGIC;
RESET:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(3DOWNTO0);
DOUT:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
C:
OUTSTD_LOGIC);
ENDCOUNTER10;
ARCHITECTUREBEHAVIORALOFCOUNTER10IS
SIGNALCOUNT:
STD_LOGIC_VECTOR(3DOWNTO0);
BEGIN
DOUT<=COUNT;
PROCESS(CLK,RESET,DIN)
BEGIN
IFRESET='0'THEN
COUNT<=DIN;
C<='0';
ELSIFRISING_EDGE(CLK)THEN
IFCOUNT="1001"THEN
COUNT<="0000";
C<='1';
ELSE
COUNT<=COUNT+1;
C<='0';
ENDIF;
ENDIF;
ENDPROCESS;
ENDBEHAVIORAL;
二十四进制计数器程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCOUNTER24IS
PORT(CLK:
INSTD_LOGIC;
RESET:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(5DOWNTO0);
DOUTL:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
DOUTH:
OUTSTD_LOGIC_VECTOR(1DOWNTO0));
ENDCOUNTER24;
ARCHITECTUREBEHAVIORALOFCOUNTER24IS
SIGNALCOUNT1:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALCOUNT2:
STD_LOGIC_VECTOR(1DOWNTO0);
BEGIN
DOUTL<=COUNT1;
DOUTH<=COUNT2;
PROCESS(CLK,RESET,DIN)
BEGIN
IFRESET='0'THEN
COUNT1<=DIN(3DOWNTO0);
COUNT2<=DIN(5DOWNTO4);
ELSIFCLK'EVENTANDCLK='1'THEN
IFCOUNT1="1001"THEN
COUNT1<="0000";
COUNT2<=COUNT2+1;
ELSE
COUNT1<=COUNT1+1;
ENDIF;
IFCOUNT2="10"THEN
IFCOUNT1="0011"THEN
COUNT1<="0000";
COUNT2<="00";
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
ENDBEHAVIORAL;
译码器程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYDECODERIS
PORT(DIN:
INSTD_LOGIC_VECTOR(3DOWNTO0);--四位二进制码输入
DOUT:
OUTSTD_LOGIC_VECTOR(6DOWNTO0));--输出LED七段码
ENDDECODER;
ARCHITECTUREBEHAVIORALOFDECODERIS
BEGIN
PROCESS(DIN)
BEGIN
CASEDINIS
WHEN"0000"=>DOUT<="0000001";--0
WHEN"0001"=>DOUT<="1001111";--1
WHEN"0010"=>DOUT<="0010010";--2
WHEN"0011"=>DOUT<="0000110";--3
WHEN"0100"=>DOUT<="1001100";--4
WHEN"0101"=>DOUT<="0100100";--5
WHEN"0110"=>DOUT<="0100000";--6
WHEN"0111"=>DOUT<="0001111";--7
WHEN"1000"=>DOUT<="0000000";--8
WHEN"1001"=>DOUT<="0000100";--9
WHENOTHERS=>DOUT<="1111111";
ENDCASE;
ENDPROCESS;
顶层文件程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCLOCKIS
PORT(CLK:
INSTD_LOGIC;--1HZ
RESET:
INSTD_LOGIC;--复位信号
DINS:
INSTD_LOGIC_VECTOR(6DOWNTO0);--秒钟预置
DINM:
INSTD_LOGIC_VECTOR(6DOWNTO0);--分钟预置
DINH:
INSTD_LOGIC_VECTOR(5DOWNTO0);--时钟预置
SECONDL:
OUTSTD_LOGIC_VECTOR(6DOWNTO0);--秒钟低位输出
SECONDH:
OUTSTD_LOGIC_VECTOR(6DOWNTO0);--秒钟高位输出
MINUTEL:
OUTSTD_LOGIC_VECTOR(6DOWNTO0);--分钟低位输出
MINUTEH:
OUTSTD_LOGIC_VECTOR(6DOWNTO0);--分钟高位输出
HOURL:
OUTSTD_LOGIC_VECTOR(6DOWNTO0);--小时低位输出
HOURH:
OUTSTD_LOGIC_VECTOR(6DOWNTO0));--小时高位输出
ENDCLOCK;
ARCHITECTUREBEHAVIORALOFCLOCKIS
COMPONENTDIVIS
PORT(CLK,RESET:
INSTD_LOGIC;
F:
OUTSTD_LOGIC);
ENDCOMPONENT;
COMPONENTCOUNTER10IS
PORT(CLK:
INSTD_LOGIC;
RESET:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(3DOWNTO0);
DOUT:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
C:
OUTSTD_LOGIC);
ENDCOMPONENT;
COMPONENTCOUNTER6IS
PORT(CLK:
INSTD_LOGIC;
RESET:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(2DOWNTO0);
DOUT:
OUTSTD_LOGIC_VECTOR(2DOWNTO0);
C:
OUTSTD_LOGIC);
ENDCOMPONENT;
COMPONENTCOUNTER24IS
PORT(CLK:
INSTD_LOGIC;
RESET:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(5DOWNTO0);
DOUTL:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
DOUTH:
OUTSTD_LOGIC_VECTOR(1DOWNTO0));
ENDCOMPONENT;
COMPONENTDECODERIS
PORT(DIN:
INSTD_LOGIC_VECTOR(3DOWNTO0);
DOUT:
OUTSTD_LOGIC_VECTOR(6DOWNTO0));
ENDCOMPONENT;
SIGNALCLK1HZ,C1,C2,C3,C4:
STD_LOGIC;
SIGNALDOUTSL,DOUTML:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALDOUTSH,DOUTMH:
STD_LOGIC_VECTOR(2DOWNTO0);
SIGNALRDOUTL:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALRDOUTSH,RDOUTMH:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALRDOUTH:
STD_LOGIC_VECTOR(1DOWNTO0);
SIGNALRRDOUTH:
STD_LOGIC_VECTOR(3DOWNTO0);
BEGIN
RDOUTSH<='0'&DOUTSH;--将秒钟高位数据变为4位,再进行译码
RDOUTMH<='0'&DOUTMH;--将分钟高位数据变为4位,再进行译码
RRDOUTH<="00"&RDOUTH;--将时钟高位数据变为4位,再进行译码
U0:
DIVPORTMAP(CLK=>CLK,RESET=>RESET,F=>CLK1HZ);
U1:
COUNTER10PORTMAP(CLK=>CLK1HZ,RESET=>RESET,
DIN=>DINS(3DOWNTO0),DOUT=>DOUTSL,C=>C1);
U2:
COUNTER6PORTMAP(CLK=>C1,RESET=>RESET,
DIN=>DINS(6DOWNTO4),DOUT=>DOUTSH,C=>C2);
U3:
COUNTER10PORTMAP(CLK=>C2,RESET=>RESET,
DIN=>DINM(3DOWNTO0),DOUT=>DOUTML,C=>C3);
U4:
COUNTER6PORTMAP(CLK=>C3,RESET=>RESET,
DIN=>DINM(6DOWNTO4),DOUT=>DOUTMH,C=>C4);
U5:
COUNTER24PORTMAP(CLK=>C4,RESET=>RESET,
DIN=>DINH,DOUTL=>RDOUTL,DOUTH=>RDOUTH);
U6:
DECODERPORTMAP(DIN=>DOUTSL,DOUT=>SECONDL);
U7:
DECODERPORTMAP(DIN=>RDOUTSH,DOUT=>SECONDH);
U8:
DECODERPORTMAP(DIN=>DOUTML,DOUT=>MINUTEL);
U9:
DECODERPORTMAP(DIN=>RDOUTMH,DOUT=>MINUTEH);
U10:
DECODERPORTMAP(DIN=>RDOUTL(3DOWNTO0),DOUT=>HOURL);
U11:
DECODERPORTMAP(DIN=>RRDOUTH(3DOWNTO0),DOUT=>HOURH);
ENDBEHAVIORAL;