您的当前位置:首页正文

基于vhdl的万年历设计

来源:画鸵萌宠网
实验报告

基 于 VHDL 的 万 年 历 设 计

学号:1328403035 姓名:吉光宇 班级:13电信

一:实验目的、

设计具有如下功能的万年历:

(1)能进行正常的年、月、日和时、分、秒的日期和时间计时功能,按键KEY1用来进行模式切换,当KEY1=1时,显示年、月、日;当KEY1=0时,显示时、分、 秒。

(2)能利用实验系统上的按键实现年、月、日和时、分、秒的校对功能。

(3)用层次化设计方法设计该电路,编写各个功能模块的程序。 (4)仿真报时功能,通过观察有关波形确认电路设计是否正确。 (5)完成电路设计后,用实验系统下载验证设计的正确性。

二:实验原理、

1.按照模块化的设计思想,要实现万年历的基础功能,必定要包含年、月、日和时、分、秒的功能模块,其中秒和分可以用六十进制计数器来实现,时用二十四进制计数器实现,月用十二进制计数器来实现,年的低两位和高两位都是一百进制计数器,比较特殊的是天的计数器,因为它有四种情况,大月三十一天,小月三十天,平年二月二十八天,闰年二月有二十九天,所以年和月的模块对天的计数都有影响,需要从年和月的输出端引出控制信号来控制天的计数。同时每个计数器都有显示输出端和进位输出端,同时低级别(如秒)的进位输出要给较

高级别(如分)的时钟输入端,以此类推,采用串行工作方式进行连接。从而完成了基础的计时和显示的功能。 再按照由基础功能到增强功能的设计思路,要实现校时功能,要在之前电路的基础之上增加一个校时控制模块,增加两个按键来实现控制,按键1来选择校对哪一个模块,按键2选择校对到何值——检测到按键2的一个上升沿,对应的计数器加1。除此之外还需要有显示模式的切换的功能,需要增加一个模式切换的控制模块,通过增加一个按键3来实现控制,是显示年月日还是时分秒。

三.实验说明

万年历的设计思路与多功能时钟的设计思路相似。多功能时钟的各功能模块及相互之间的连接如下图1所示

图1多功能时钟系统原理框图

年、月、日和时、分、秒的显示格式如图2所示。年、月、日同时显示,时、分、秒同时显示,通过显示模式切换来分别显示。

年/时 月/分 日/秒 图2万年历显示格式

四.实验原理图

万年历时分秒部分的原理图如下图所示,年月日部分与之同理,通过控制可以进行切换。

译码驱动 时十位 计数 译码驱动 时个位 计数 译码驱动 分十位 计数 译码驱动 分个位 计数 译码驱动 秒十位 计数 译码驱动 秒个位 计数 校时控制电路 校分控制电路 1HZ 晶体振荡器电路 分频器电路 分频器电路 图3万年历实验原理图

图4万年历实验结构框图

图5万年历实验结构局部图

原理图说明:

如图4、5所示,K1键是选择万年历工作的模式,K2键提供上升沿(时钟功能)来使各计数模块加一,从而实现校时的功能。LED灯起指示作用。

模式0:正常计时显示 --K1不按,LED1到LED5都不亮 模式1:调整分增加 --K1按下一次,LED1亮其余四个不亮 模式2:调整时增加 -- K1按下两次,LED2亮其余四个不亮 模式3:调整日增加 -- K1按下三次,LED3亮其余四个不亮 模式4:调整月增加 -- K1按下四次,LED4亮其余四个不亮 模式5:调整年增加 -- K1按下五次,LED5亮其余四个不亮 CLK是外部1Hz输入时钟,作为秒的时钟输入,驱动整个万年历工作运行。 K3键是显示模式的选择,显示时分秒时,LEDSHUCHUMOSHI指示灯亮,显示年月日时,LEDSHUCHUMOSHI指示灯灭。

4.工作过程

当1Hz时钟信号从CLK输入端输入时,K1,K2,K3都没有按下时,系统从零(闰年)开始处于正常的计时模式,显示时分秒部分,LEDSHUCHUMOSHI指示灯亮。低位计满归零并且向高位进1,如果月份是二月,则天计满29就向月进1。如果按下按键3,LEDSHUCHUMOSHI指示灯不亮,显示年月日部分。如果此时按一下按键1,那么万年历停止计时,工作于模式1,再通过按键2对分进行校时,通过同样的方法可以对时、日、月、年进行校时。当校时完毕,需要万年历重新计时工作时,通过按下键1使LED1到LED5都不亮时,系统工作与正常计时模式。

五、实验结果

4.1VHDL程序与仿真 4.1.1秒与分模块

秒与分模块为六十进制的计数器 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY CNT60 IS

PORT(CLK:IN STD_LOGIC;

Q1,Q2:OUT STD_LOGIC_VECTOR(3 DOWNTO 0); COUT:OUT STD_LOGIC);

END CNT60;

ARCHITECTURE ONE OF CNT60 IS

SIGNAL Q11,Q22:STD_LOGIC_VECTOR(3 DOWNTO 0); PROCESS(CLK)

BEGIN

IF CLK'EVENT AND CLK='1' THEN

Q11<=Q11+1; Q22<=Q22+1;

IF Q11=9 THEN Q11<=(OTHERS=>'0'); END IF;

IF Q22=5 AND Q11=9 THEN

Q22<=\"0000\";Q11<=\"0000\";COUT<='1'; ELSE COUT<='0'; END IF; END IF;

BEGIN

END PROCESS;

Q1<=Q11;Q2<=Q22;

END; 仿真结果:

图6 60进制计数器仿真图

如上图所示当Q1、Q2计满60时,Q1、Q2都归零同时有一个进位输出脉冲,完成了六十进制计数器的功能,设计正确。

4.1.2小时模块

时模块为24进制计数器。 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY CNT24 IS

ARCHITECTURE ONE OF CNT24 IS

SIGNAL Q11,Q22:STD_LOGIC_VECTOR(3 DOWNTO 0); PROCESS(CLK)

BEGIN

IF CLK'EVENT AND CLK='1' THEN

Q11<=Q11+1; Q22<=Q22+1;

IF Q11=9 THEN Q11<=(OTHERS=>'0'); END IF;

IF Q22=2 AND Q11=3 THEN

Q22<=\"0000\";Q11<=\"0000\";COUT<='1'; ELSE COUT<='0'; END IF; END IF;

BEGIN

PORT(CLK:IN STD_LOGIC;

Q1,Q2:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

COUT:OUT STD_LOGIC);

END CNT24;

END PROCESS;

Q1<=Q11;Q2<=Q22;

END; 仿真结果:

图7 24进制计数器仿真图

如上图所示当Q1、Q2计满24时,Q1、Q2都归零同时有一个进位输出脉冲,完成了六十进制计数器的功能,设计正确。

4.1.3日(天)模块

日模块有四种情况,大月为31进制计数器,小月为30进制计数器,平年二月为28进制计数器,闰年二月为29进制计数器,需要有一个二位判断输入信号来进行进制数的选择。 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY DAY IS

PORT( PANDUAN :IN STD_LOGIC_VECTOR(1 DOWNTO 0);--两位判断输入信号 CLK :IN STD_LOGIC;

CQ1 :OUT STD_LOGIC_VECTOR (3 DOWNTO 0); CQ2 :OUT STD_LOGIC_VECTOR (3 DOWNTO 0); COUT :OUT STD_LOGIC); END;

ARCHITECTURE ONE OF DAY IS

SIGNAL CQ3,CQ4:STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL PAN:STD_LOGIC_VECTOR(1 DOWNTO 0); PROCESS(CLK,PANDUAN)

BEGIN

BEGIN IF CLK'EVENT AND CLK='1' THEN --上升沿

CQ3<=CQ3+1;

IF CQ3=9 THEN CQ3<=(OTHERS=>'0'); CQ4<=CQ4+1; END IF;

PAN<=PANDUAN;

CASE PAN IS

WHEN \"00\"=>IF CQ3=\"0001\" AND CQ4=\"0011\" --时为31进

THEN CQ3<=\"0001\";CQ4<=\"0000\";COUT<='1'; -- ELSE COUT<='0';END IF;

WHEN \"01\"=>IF CQ3=\"0000\" AND CQ4=\"0011\" --时为30进

THEN CQ3<=\"0001\";CQ4<=\"0000\";COUT<='1'; -- ELSE COUT<='0';END IF;

WHEN \"10\"=>IF CQ3=\"1000\" AND CQ4=\"0010\" --时为28进

THEN CQ3<=\"0001\";CQ4<=\"0000\";COUT<='1'; -- ELSE COUT<='0';END IF;

WHEN \"11\"=>IF CQ3=\"1001\" AND CQ4=\"0010\" --时为29进

THEN CQ3<=\"0001\";CQ4<=\"0000\";COUT<='1'; -- ELSE COUT<='0';END IF; WHEN OTHERS=>NULL; END CASE; END IF;

CQ1<=CQ3; CQ2<=CQ4; END PROCESS; END;

仿真结果:

判断信号为00制计数器 判断信号为01制计数器 判断信号为10制计数器 判断信号为11制计数器

图8 判断信号为00时天模块仿真图

图9 判断信号为01时天模块仿真图

图10 判断信号为10时天模块仿真图

图11 判断信号为11时天模块仿真图

如图8、9、10、11所示,仿真结果与设计要求一致,日模块的设计正确

4.1.4月模块

月模块为12进制计数器,同时其需要为天提供判断信号输出,其与天的判断输入信号相一致。由于二月的判断信号输出要受到平年和闰年的影响,平年时判断信号是10,闰年时判断信号为11,所以它要有接收来之年模块的判断平年闰年的输出信号(run=0时表平年,run=1时表闰年)。 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY MONTH IS

port(clk :IN STD_LOGIC; run :IN STD_LOGIC; cout :OUT STD_LOGIC;

pan :OUT STD_LOGIC_VECTOR(1 DOWNTO 0);

cq1,cq2 :OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); END ;

ARCHITECTURE behav OF MONTH IS

signal cq3,cq4: STD_LOGIC_VECTOR (3 DOWNTO 0); signal cq5: STD_LOGIC_VECTOR (7 DOWNTO 0); BEGIN PROCESS(clk) BEGIN

IF clk'EVENT and clk='1' THEN

cq3<=cq3+1;

IF cq3=9 THEN cq4<=cq4+1;cq3<=\"0000\"; END IF;

IF cq3=2 and cq4=1 THEN cq3<=\"0001\";cq4<=\"0000\";cout<='1';ELSE cout<='0';

END IF;END IF; --十二进制计数器 cq5<=cq4&cq3; --逻辑位相连接 CASE cq5 IS WHEN --一月

WHEN \"00000010\"=>if run='1' then pan<=\"11\";else pan<=\"10\";end if; --—二月 WHEN --三月 WHEN --四月 WHEN --五月 WHEN --六月 WHEN --七月 WHEN --八月 WHEN --七月 WHEN --十月 WHEN --十一月 WHEN --十二月

WHEN others=>NULL; END CASE; cq1<=cq3; cq2<=cq4; END PROCESS; END;

\"00000001\"=>pan<=\"00\";

\"00000011\"=>pan<=\"00\";

\"00000100\"=>pan<=\"01\";

\"00000101\"=>pan<=\"00\";

\"00000110\"=>pan<=\"01\";

\"00000111\"=>pan<=\"00\";

\"00001000\"=>pan<=\"00\";

\"00001001\"=>pan<=\"01\";

\"00001010\"=>pan<=\"00\";

\"00001011\"=>pan<=\"01\";

\"00001100\"=>pan<=\"00\";

仿真结果:

图12 平年(run=0)时月模块仿真图

图13 闰年(run=1)时月模块仿真图

如图12、13所示月模块为12进制计数器,并且1、3、5、7、8、10、12月(大月)判断信号为00,4、6、9平年(run=0)2月的判断输出信号为、11月(小月)判断信号为01,平年(run=0)2月的判断输出信号为10,闰年(run=1)2月的判断输出信号为11,与天模块的判断输入信号相一致,符合设计要求,模块的设计正确。

4.1.5年模块

年的高两位和低两位都为一百进制计数器,功能基本相同,不同的是低两位

模块有闰年判断输出信号,要传送给月份模块,计满四次就产生一个闰年输出信号,因为闰年数值是4的整倍数。 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY YEAR IS

PORT(CLK:IN STD_LOGIC;

Y1,Y2:OUT STD_LOGIC_VECTOR(3 DOWNTO 0); RUN,COUT:OUT STD_LOGIC);

END YEAR;

ARCHITECTURE ONE OF YEAR IS

SIGNAL Q1,Q2,Q3:STD_LOGIC_VECTOR(3 DOWNTO 0); PROCESS(CLK)

BEGIN

IF CLK'EVENT AND CLK='1' THEN Q1<=Q1+1; IF Q1=9 THEN Q1<=(OTHERS=>'0');

Q2<=Q2+1; END IF;

IF Q2=9 AND Q1=9 THEN

Q2<=\"0000\";Q1<=\"0000\";COUT<='1'; ELSE COUT<='0'; END IF; END IF;

BEGIN

END PROCESS; PROCESS(CLK) BEGIN

IF CLK'EVENT AND CLK='1' THEN Q3<=Q3+1; IF Q3=3 THEN Q3<=(OTHERS=>'0');

RUN<='1'; ELSE RUN <='0'; END IF; END IF; Y1<=Q1;Y2<=Q2;

END PROCESS;

END; 仿真结果:

图14 低两位年模块仿真图

如图14所示,低两位年模块为100进制计数器当T2、T1表示的数为4的整数倍时,判断闰年输出信号就为高电平,与月模块的判断闰年输入信号相一致。符合设计的要求,设计正确。

4.1.6校时模块

如原理图的说明部分所述,校时模块进行工作模式的选择,输入端设有控制按键K1,K2。K1进行模式的选择,K2的功能如同手动时钟脉冲,进行调时设置。 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY JIAODUI IS

PORT( K1,K2 :IN STD_LOGIC; MI,FI,SI,TI,YI:IN STD_LOGIC; FO,SO,TL,YO,NO :OUT STD_LOGIC; L1,L2,L3,L4,L5 :OUT STD_LOGIC); END;

ARCHITECTURE BEHAV OF JIAODUI IS SIGNAL A: STD_LOGIC_VECTOR (3 DOWNTO 0);

BEGIN

PROCESS(K1,K2) BEGIN

IF K1'EVENT AND K1='1' THEN A<=A+1; IF A=5 THEN A<=\"0000\"; END IF; END IF; CASE A IS

WHEN \"0000\"=>FO<=MI;SO<=FI;TL<=SI;YO<=TI;NO<=YI; -- 时

L1<='0';L2<='0';L3<='0';L4<='0';L5<='0';

WHEN \"0001\"=>FO<=K2;SO<='0';TL<='0';YO<='0';NO<='0'; --分

L1<='1';L2<='0';L3<='0';L4<='0';L5<='0';

WHEN \"0010\"=>FO<='0';SO<=K2;TL<='0';YO<='0';NO<='0'; --时

L1<='0';L2<='1';L3<='0';L4<='0';L5<='0';

WHEN \"0011\"=>FO<='0';SO<='0';TL<=K2;YO<='0';NO<='0'; -- 调日

L1<='0';L2<='0';L3<='1';L4<='0';L5<='0';

WHEN \"0100\"=>FO<='0';SO<='0';TL<='0';YO<=K2;NO<='0'; -- 调月

L1<='0';L2<='0';L3<='0';L4<='1';L5<='0';

WHEN \"0101\"=>FO<='0';SO<='0';TL<='0';YO<='0';NO<=K2; --调年

L1<='0';L2<='0';L3<='0';L4<='0';L5<='1'; WHEN OTHERS=>NULL; END CASE; END PROCESS; END; 仿真结果:

模式0正常及选通分模块,调选通时模块,调选通日模块,选通月模块,选通年模块,

图15 校时模块仿真图

图16 校时模块仿真图

如图15、16,按键K1,K2能够完成万年历工作模式的选择与调时校对的功能,满足系统的设计要求,设计正确。

4.1.7显示模式切换模块

显示模式切换模块完成显示年月日和显示时分秒的相互切换,设置一个按键K3对其进行控制,通过检测按键的上升沿,对显示模式进行轮流切换。 源程序: LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY CONTROL IS

PORT(SL,SH,FL,FH,HL,HH,DL,DH,ML,MH,YL,YH,Y1L,Y1H:IN

STD_LOGIC_VECTOR(3 DOWNTO 0);

ARCHITECTURE ONE OF CONTROL IS SIGNAL W:STD_LOGIC_VECTOR(1 DOWNTO 0); BEGIN

PROCESS(K1) BEGIN

IF K1'EVENT AND K1='1' THEN W<=W+1;

IF W=2 THEN W<=\"00\";--二进制计数控制信号 END IF; END IF;

K1:IN STD_LOGIC; led:OUT STD_LOGIC;

Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));

END CONTROL;

CASE W IS

WHEN\"00\"=>

Q8<=Y1H;Q7<=Y1L;Q6<=YH;Q5<=YL;Q4<=MH;Q3<=ML;Q2<=DH;Q1<=DL;led<='0'; --00时显示年月日,指示灯不亮

WHEN\"01\"=>

Q8<=\"0000\";Q7<=\"0000\";Q6<=HH;Q5<=HL;Q4<=FH;Q3<=FL;Q2<=SH;Q1<=SL;led<='1'; --01时显示时分秒,指示灯亮

WHEN OTHERS=>NULL;

END CASE; END PROCESS;

END; 仿真结果:

如图16所示,当按键K1没有按下时Q1到Q6显示的是年月日部分,此时的指示灯LED为零(不亮),当按键K1按下一次,检测到一次上升沿,Q1到Q6显示的是时分秒部分,此时的指示灯LED为1(亮),当K1键再次按下时,上升沿一到,显示年月日,这样通过按键K1可以实现显示模式的切换。设计符合系统的要求,设计正确。

图17 显示模块仿真图

4.2顶层设计与仿真

顶层设计采样原理图输入方法,用以上的各模块的VHDL源程序分别生成元器件,在此基础上用“导线”对元器件进行连接,搭建原理图,完成系统的顶层设计,而不是利用元件例化程序去设计。对于较为复杂的系统而言,采用原理图输入的设计方法思路更加清晰,设计更加直观。

顶层原理图的设计框架如图4所示,有年、月、日、时、分、秒计时模块,调时校对模块,显示模式切换模块,并且由以上讨论知万年历一共有六种工作模式。 仿真结果:

如图18所示,此时万年历工作于模式0,属于正常的计时状态,当低位计满时向高位进1,通过键K3,可以对显示模式进行切换,从显示时分秒转换到显

示年月日,正确的实现了系统的计时功能。

图18 万年历仿真图

图19 万年历仿真图

图20 万年历仿真图

如图19、20所示,通过按键K1可以进行工作模式的选择,按键K2进行数值的校对设定,按键K3进行显示模式的切换,与设计的要求相符合。综上所述,整个系统设计正确,万年历能够正确的实现功能。

六.端口设置、

七.验证、

当K1键没有按下时,万年历正常计时,计满向高位进位,可以通过K3键选择显示模式,显示时分秒时指示灯亮。通过按下K1键的次数来选择校对那一部分,对应的指示灯亮,再通过按下K2键的次数来进行数值选择,进行校对时低位不会向高位进位。当把年设置为闰年,月模块设置为2月,天模块设置为29,时模块设置为23,分模块设置为59,通过按键K1选择正常计时模式,计满60s时,不断往上进位,月份变为3月,证明此时二月为二十九进制计数器。

八.实验总结

通过这次万年历程序的设计,完成了硬件系统设计目标。加深了对EDA技术的理解,熟悉了QuartusII软件环境,熟练地掌握了基于VHDL硬件设计的整个流程,从设计编程到下载验证。通过对具体模块的编写,如CNT60模块,CNT24模块,DAY模块,MONTH模块,YEAR模块,JIAODUI模块,显示模块等,加强了

自己分析问题及编程的能力,掌握编程时该注意的语法规则,理解进行系统设计时的模块化设计思想。最终实现了一个自己动手完成的电子作品,增强了我们分析问题、解决问题的能力,培养了对电子工程设计的浓厚兴趣。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top