资源描述
VHDL 课程设计
题 目 多功能万年历的数字钟设计
专业名称
学生姓名
指导教师
完成时间
一: 课程设计的任务
设计一个多功能的数字时钟,具有以下功能:
1. 正常的显示功能:显示AM、PM、时、分、秒(24进制或者12进制)。
2. 手动校时功能:按动方式键,将电路置于校时状态,则计时电路可用手动方式校准,每按一下校时键,时计数器加1;按动方式键,将电路置于校分状态,以同样方式手动校分。按动按键有滴滴声,并且数码管显示的数字会闪动。
3. 万年历功能:显示年、月、日、星期、是否闰年。
4. 手动校正日历功能。按动方式键,将电路置于校年状态,则计时电路可用手动方式校准,每按一下校年键,时计数器加1;按动方式键,将电路置于校月状态,以同样方式手动校月。按动按键有滴滴声,并且数码管显示的数字会闪动。
5. 闹钟功能:按动方式键进入闹钟设定模块,设定闹钟时间。闹铃信号到达播放音乐《两只蝴蝶》,按动停止键则立即停止播放音乐,若不按动停止键则自动播放音乐1分钟后停止。
6. 整点播报功能,从59分50秒开始发出播报,每隔2秒发出一声(信号名叫持续时间1秒,间隙1秒)连续发出5次,到达整点时停止播报。
7. 秒表功能:按动开始键开始计时,按动停止键数字保持不变,按动复位键从新计时
二:系统设计
根据以上对于多功能数字钟的功能的描述,可以将整个的电路设计分为以下几个模块:
1. 分频模块:由于实验电路板上所能提供的只有1Khz和6Mhz的信号,而本设计过
程的即时以及跑表模块需要1hz、100hz和4hz的时钟信号。
2. 控制模块:为达到多动能数字钟在计时、校时、显示日历、跑表等不同的模块之间
切换,需要控制模块产生时序要不相冲突的控制信号,保证各个模块的功能有序的执行。
3. 计时模块:在输入的1hz时钟信号,产生显示的AM、PM、时、分、秒信号,由
于要涉及到后面的校时模块,这里采用带有置数的计时模块,在load信号控制下将校时模块设定的时间转载至初始值,在初始值的基础上正常计时。
4. 校时模块:当功能切换至校时模块时,本程序采用在外部按键的上升沿即:每按动
一次校时键对应显示相应加1。
5. 万年历模块:在计时模块的进位输出信号(每次跳动代表一年),产生显示的年、月、
日、星期、是否闰年信号,同样类似于计时模块考虑到后面的校正日历模块,这里同样采用带有置数的计时模块,在load信号控制下将校正日历模块设定的日历转载至初始值,在初始值的基础上正常计时。
6. 校正日历模块:切换至该模块时,采用外部按键的上升沿:每按动一次校正键对应的显示相应的加1。
7. 闹钟模块:这里采用和校时模块同样的电路设定闹钟的时间,一旦触发信号为高电
平,触发音乐播放模块,播放歌曲《两只蝴蝶》,不按停止键播放一分钟自动停止。
8. 跑表模块:采用显示毫秒、秒、分的显示格式,并设有stop按钮和reset按钮。
9. 显示模块:采用从控制模块中出来的mode 信号为变量,跟随该信号的变化,选着不同的模块的输出信号,通过两个译码器输出数据连接到数码管显示。
以上简单的介绍了构成电路的几大模块,下面给出本设计电路的总的模块化示意图:
图 一 系统总模块化示意图
三:模块实现
根据以上的介绍可知闹钟的设计的组成模块:分频模块、控制模块、计时模块、校时模块、万年历模块、校正日历模块、闹钟模块(包块音乐模块)、跑表模块、显示模块。以下将就着上面的模块电路的各个模块加以详细的说明。对以上模块的实现进行具体的VHDL的设计。注:(在前面定义的子模块,后面不再定义而是直接的例化使用)
一:分频模块
由于开发板系统提供的时钟只有1Khz和6Mhz(专用于音乐模块),而本实验的计时模块、音乐模块、跑表模块等需要1hz、100hz的时钟信号,故需要加以分频实现所需信号。分频电路的模块化示意图如下:
图 二 分频电路模块图
下面给出分频模块的RTL级的描述:
1)10分频模块:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity fenpin10 is
port (clk_in:in std_logic;- - 输入时钟信号
clk_out:buffer std_logic);- -输出时钟信号
end fenpin10;
architecture rtl of fenpin10 is
signal cnt:std_logic_vector(3 downto 0);- -定义计数器模值
begin
process (clk_in)
begin
if (clk_in'event and clk_in='1') then
if (cnt="0100") then
clk_out<=not clk_out;
cnt<="0000";
else
cnt<=cnt+'1';
end if;
end if;
end process ;
end rtl;
2)分频模块的RTL描述:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity fenpin is
port (clk_1khz:in std_logic;- -输入1Khz时钟信号
clk_1hz,clk_100hz:buffer std_logic);- - 输出的1hz和100hz信号
end fenpin;
architecture rtl of fenpin is
signal clk_10hz:std_logic;
component fenpin10 is- - 例化10分频电路,在本设计中调用
port (clk_in:in std_logic;
clk_out:buffer std_logic);
end component;
begin
u0: fenpin10
port map(clk_in=>clk_1khz,- - 时钟输入
clk_out=>clk_100hz);- - 时钟输出
u1: fenpin10
port map (clk_in=>clk_100hz, - - 时钟输入
clk_out=>clk_10hz); - - 时钟输出
u2: fenpin10
port map (clk_in=>clk_10hz, - - 时钟输入
clk_out=>clk_1hz); - - 时钟输出
end rtl;
3)分频模块的仿真图
图 三 分频模块仿真图
仿真图分析:输入信号为1Khz经过分频成功产生100hz和1hz时钟信号
二:计时模块
本计时完成时间输出功能,根据秒、分、时(24进制)计时原理故需要设计到60、24进制的BCD计数器,并在此基础上构成RTL级的计时描述,模块图如下所示:
图四 计时电路模块图
下面给出计时模块的RTL级的描述:
由于考虑到后面的跑表和校时模块的预置数,这里的模60、24BCD计数器均设计成带有预置数端口,和暂停计数功能。同时考虑到现实AM、PM,以及整点报时以及对于报时声音时宽的要求,加入实现上述功能的子模块。
1)模60BCD计数器 循环的进行0-59计数,产生秒、分信号输出
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cnt60 is
port (clk_in,reset,load,stop,en:in std_logic;--输入的时钟、清0、置数、暂停、使能信号
l_in,h_in:in std_logic_vector(3 downto 0);--预置数,高4位和低4位
enout:out std_logic;--输出地进位信号
h,l:out std_logic_vector(3 downto 0));---输出信号的高4位和低4位
end cnt60;
architecture rtl of cnt60 is
signal h_temp,l_temp:std_logic_vector(3 downto 0)
begin
process (clk_in,en) ----个位计数进程(0-9)循环计数
begin
if (reset='1') then---清0
l_temp<="0000";
elsif (load='1') then---下载预置数
l_temp<=l_in;
elsif (clk_in'event and clk_in='0') then---正常计数
if((en='1')and(stop='0')) then
if (l_temp="1001") then
l_temp<="0000";
else
l_temp<=l_temp+'1';
end if;
end if;
end if;
end process low_proc;
l<=l_temp;
process (clk_in,en)----十位计数进程(0~5)循环计数
begin
if (reset='1') then---清0
h_temp<="0000";
elsif (load='1') then---下载预置数
h_temp<=h_in;
elsif (clk_in'event and clk_in='0') then---正常计数
if((en='1')and(stop='0')) then
if (l_temp="1001") then
if (h_temp="0101") then
h_temp<="0000";
else
h_temp<=h_temp+'1';
end if;
end if;
end if;
end if;
end process high_proc;
h<=h_temp;
enout<='1' when l_temp="1001" and h_temp="0101" else---计满60产生进位输出
'0';
end rtl;
2)模24BCD计数器 循环进行0-23计数 产生时输出信号
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cnt24 is
port ( clk_in,reset,load,stop,en:in std_logic; ---输入的时钟、清0、置数、暂停、使能信号
h_in,l_in:in std_logic_vector(3 downto 0);---输入的预置数
enout:out std_logic;---输出进位信号
h,l:out std_logic_vector(3 downto 0));---输出信号的高4位和低4位
end cnt24;
architecture rtl of cnt24 is
signal l_temp:std_logic_vector(3 downto 0);
signal h_temp:std_logic_vector(3 downto 0);
signal clr:std_logic:='0';---计满模24产生的清0信号
begin
process (clk_in,en,clr)---个位的计数进程(0~9)循环计数
begin
if (reset='1') then---清0信号
l_temp<="0000";
elsif (load='1') then---下载预置数
l_temp<=l_in;
elsif (clk_in'event and clk_in='0') then---正常计数
if ((en='1')and(stop='0')) then
if ((l_temp="1001") or (clr='1')) then
l_temp<="0000";
else
l_temp<=l_temp+'1';
end if;
end if;
end if;
end process low_proc;
l<=l_temp;
process (clk_in,en,clr)---十位计数进程(0~2)循环计数
begin
if (reset='1') then
h_temp<="0000";
elsif (load='1') then
h_temp<=h_in;
elsif (clk_in'event and clk_in='0') then
if ((en='1')and(stop='0')) then
if (clr='1') then
h_temp<="0000";
elsif (l_temp="1001") then
h_temp<=h_temp+'1';
end if;
end if;
end if;
end process high_proc;
h<=h_temp;
clr<='1' when l_temp="0011" and h_temp="0010" else---计满模24产生清0信号
'0';
enout<=clr;---计满24产生进位信号
end rtl;
3)整点模块 时刻为59分50秒开始报时,知道00分00秒停止
library ieee;
use ieee.std_logic_1164.all;
entity zd is
port (clk_in,en:in std_logic;---输入时钟,使能信号
cmh,cml,csh,csl:in std_logic_vector(3 downto 0);---输入的分、秒
voiceon:out std_logic);---声音信号输出
end zd;
architecture rtl of zd is
signal key:std_logic:='0';
signal temp:std_logic_vector(3 downto 0);
begin
process (clk_in)---判断时间是否为59分50秒
begin
if (clk_in'event and clk_in='1') then
if ((csl="0000")and(csh="0101")and(cml="1001")and(cmh="0101")and(en='1')) then
voiceon<='1';
temp<="0000";
key<='1';
end if;
if ((temp=csl)and(key='1')) then---声音持续十秒停止
voiceon<='0';
key<='0';
end if;
end if;
end process;
end rtl;
4)二分频电路
因为整点报时10秒,为达到报时信号周期2s,每周期响铃1s,故需通过二分频电路
library ieee;
use ieee.std_logic_1164.all;
entity fenpin2 is
port (clk_1hz,en:in std_logic;---输入时钟信号、使能信号(整点报时信号)
clk_out:buffer std_logic);---输出周期2s,闹铃1s闹钟信号
end fenpin2;
architecture rtl of fenpin2 is
begin
process (clk_1hz)---模2计数
begin
if (en='1') then
if (clk_1hz'event and clk_1hz='1') then
clk_out<=not clk_out;
end if;
end if;
end process ;
end rtl;
5)AM、PM电路
当时信号的十进制值为0~11显示AM,12~23显示PM
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity duan is
port (hh,hl:in std_logic_vector(3 downto 0);---输入的时信号的高4位和低4位
b:out std_logic_vector(3 downto 0));---输出的AM或PM信号
end duan;
architecture rtl of duan is
signal temp1:std_logic_vector(7 downto 0);
signal temp2:integer range 0 to 35;
signal a_on:std_logic;
signal b_on:std_logic;
signal ab_on:std_logic_vector(1 downto 0):="00";
begin
temp1<=hh&hl;---将高4位和低4位连接
temp2<=conv_integer(temp1);---转换为十进制数
process (temp1,temp2)
begin
if ((temp2>=0)and(temp2<18)) then---十进制值在(0~11)显示AM
a_on<='1';
b_on<='0';
elsif ((temp2>=18)and(temp2<=35)) then---十进制值在(12-23)显示PM
a_on<='0';
b_on<='1';
end if;
end process ;
ab_on<=a_on&b_on;
process (ab_on)
begin
case ab_on is---译码成4位信号,使得能直接接至显示模块
when "10"=>b<="1010";---AM显示为 A
when "01"=>b<="1111";---PM 显示为 P
when others=>b<="0000";
end case ;
end process;
end rtl;
6)计时模块的RTL描述:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity blockcnt is
port (reset,clk_in,load,stop,en:in std_logic;---输入的时钟、清0、下载预置数、暂停、停止信号
enout:out std_logic;---输出天进位信号
hh_in,hl_in,mh_in,ml_in,sh_in,sl_in:in std_logic_vector(3downto0);--预置时、分、秒
hh,hl,mh,ml,sh,sl:buffer std_logic_vector(3 downto 0);--输出地时、分、秒信号
b:buffer std_logic_vector(3 downto 0);---AM、PM输出显示
voiceon:buffer std_logic);---整点报时信号输出
end blockcnt;
architecture rtl of blockcnt is
component fenpin2 is---例化二分频电路
port (clk_in,en:in std_logic;
clk_out:buffer std_logic);
end component;
component zd is---例化整点报时电路
port (clk_in,en:in std_logic;
cmh,cml,csh,csl:in std_logic_vector(3 downto 0);
voiceon:out std_logic);
end component;
component cnt60 is---例化模60BCD计数电路
port (clk_in,reset,load,stop,en:in std_logic;
h_in,l_in:in std_logic_vector(3 downto 0);
enout:out std_logic;
h,l:out std_logic_vector(3 downto 0);
end component;
component cnt24 is ---例化模24BCD计数电路
port (clk_in,reset,load,stop,en:in std_logic;
h_in,l_in:in std_logic_vector(3 downto 0);
enout:out std_logic;
h,l:out std_logic_vector(3 downto 0));
end component;
component duan is---例化AM、PM电路
port (hh,hl:in std_logic_vector(3 downto 0);
b:out std_logic_vector(3 downto 0));
end component;
signal voiceon_temp:std_logic;
signal enout_temp:std_logic;
signal enout_temp1:std_logic;
signal enout_temp2:std_logic;
begin
u0: cnt60----下载预置秒信号,并产生秒时间信号
port map (clk_in=>clk_in,reset=>reset,load=>load,stop=>stop,en=>en,
l_in=>sl_in,h_in=>sh_in,
enout=>enout_temp1,
l=>sl,h=>sh);
u1: cnt60----下载预置分信号,并产生分时间信号
port map (clk_in=>enout_temp1,reset=>reset,load=>load,stop=>stop,en=>en,
l_in=>ml_in,h_in=>mh_in,
enout=>enout_temp2,
l=>ml,h=>mh);
u2: cnt24----下载预置时信号,并产生时信号
port map (clk_in=>enout_temp2,reset=>reset,en=>en,load=>load,stop=>stop,
l_in=>hl_in,h_in=>hh_in,
enout=>enout_temp,
l=>hl,h=>hh);
enout<=enout_temp;
u3: duan----根据产生的时信号判断AM、PM
port map (hl=>hl,hh=>hh,
b=>b);
u4: zd----根据产生的秒、分信号,在59分50秒开始报时,并持续10秒
port map (clk_in=>clk_in,en=>en,csl=>sl,csh=>sh,cml=>ml,cmh=>mh,
voiceon=>voiceon_temp);
u5: fenpin2---根据产生的报时信号,产生周期2s,报时信号1s的声音信号
port map (en=>voiceon_temp,clk_in=>clk_in,clk_out=>voiceon);
end rtl;
7)计时模块的仿真图:
图五 计时模块仿真图
仿真图分析:
图中reset、stop均处于失效,en有效,在load信号有效下,将预置数22时58分58秒预置给计时模块(相当于调时间),然后load信号失效,进行正常的计数,分、秒进行60进制,时进行24进制计数,当时间为59分50秒时进行整点报时,持续10秒,并按照要求分频产生周期为2s,闹铃时间为1s的声音信号。图中b代表AM、PM显示,图中时间显示应为PM,完全正确。
三:校时模块
本模块的功能是在外部按键的操作下,实现对计时器的设定初始的时、分、秒预置值,并在load信号的作用下,下载到计时器模块,由于这里涉及的任然是计数过程,过直接采用即时模块中的模60、24进制BCD计数器,AM、PM显示电路,整点报时电路。同时由于在校时过程中要求实时显示,并且呈现闪动的状态,这里采用沿触发的D触发器,将输出信号加以刷新,达到功能要求。
下图为校时模块的模块图:
图 六 校时电路模块图
下面给出给出校时电路的RTL级描述,由于模60、24计数器等电路在上述计时模块已经详细设计过了,这里不再加以详细介绍,只介绍D触发器
1)D 触发器模块:在时钟沿跳变起到刷新输出值,同时设定输入之中为4hz,能达到闪动的目的。
library ieee;
use ieee.std_logic_1164.all;
entity df is
port (clk_in,en:in std_logic;---输入时钟,使能信号
d_in:in std_logic_vector(3 downto 0);---输入的时、分、秒预置值
d_out:out std_logic_vector(3 downto 0));---输出至显示模块的时、分、秒预置值
end df;
architecture rtl of df is
begin
process (clk_in,en)
begin
if (clk_in'event and clk_in='1') then---时钟上升沿触发
if (en='1') then
d_out<=d_in;
end if;
end if;
end process;
end rtl;
2)校时模块的RTL级描述:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity blocksettime is
port (clk_in,reset,en,sclock,mclock,hclock:in std_logic;---输入时钟、重置、调秒、调分、调时
voiceon:out std_logic;----按键声音输出
hh,hl,mh,ml,sh,sl:out std_logic_vector(3 downto 0);----预置时、分、秒输出
b:out std_logic_vector(3 downto 0));----预置时间AM、PM输出
end blocksettime;
architecture rtl of blocksettime is
component cnt60 is---例化模60计数器
port (clk_in,reset,load,stop,en:in std_logic;
h_in,l_in:in std_logic_vector(3 downto 0);
enout:out std_logic;
h,l:out std_logic_vector(3 downto 0));
end component;
component cnt24 is ----例化模24计数器
port (clk_in,reset,load,stop,en:in std_logic;
h_in,l_in:in std_logic_vector(3 downto 0);
enout:out std_logic;
h,l:out std_logic_vector(3 downto 0));
end component;
component duan is----例化AM、PM电路
port (hh,hl:in std_logic_vector(3 downto 0);
b:out std_logic_vector(3 downto 0));
end component;
component df is----例化D触发器电路
port (clk_in,d_in,:in std_logic;
en:in std_logic;
d_out:out std_logic_vector(3 downto 0));
end component;
signal enout_temp1:std_logic;
signal enout_temp2:std_logic;
signal enout_temp3:std_logic;
signal sl_temp:std_logic_vector(3 downto 0):="0000";
signal sh_temp:std_logic_vector(3 downto 0):="0000";
signal mh_temp:std_logic_vector(3 downto 0):="0000";
signal ml_temp:std_logic_vector(3 downto 0):="0000";
signal hh_temp:std_logic_vector(3 downto 0):="0000";
signal hl_temp:std_logic_vector(3 downto 0):="0000";
begin
u0: cnt60----产生预置秒信号
port map (clk_in=>sclock,reset=>reset,load=>'0',stop=>'0',en=>en,
l_in=>"0000",h_in=>"0000",
enout=>enout_temp1,
l=>sl_temp,h=>sh_temp);
u1: cnt60----产生预置分信号
port map (clk_in=>mclock,reset=>reset,load=>'0',stop=>'0',en=>en,
l_in=>"0000",h_in=>"0000",
enout=>enout_temp2,
l=>ml_temp,h=>mh_temp);
u2: cnt24----产生预置时信号
port map (clk_in=>hclock,reset=>reset,en=>en,load=>'0',stop=>'0',
l_in=>"0000",h_in=>"0000",
enout=>enout_temp3,l=>hl_temp,h=>hh_temp);
voiceon<='1' when sclock='1' or mclock='1' or hclock='1' else----产生按键声音信号
'0';
u3: df port map (clk_in=>clk_in,d_in=>sl_temp,en=>en,d_out=>sl);--刷新以及闪动显示功能
u4: df port map (clk_in=>clk_in,d_in=>sh_temp,en=>en,d_out=>sh);--同上
u5: df port map (clk_in=>clk_in,d_in=>ml_temp,en=>en,d_out=>ml); --同上
u6: df port map (clk_in=>clk_in,d_in=>mh_temp,en=>en,d_out=>mh); --同上
u7: df port map (clk_in=>clk_in,d_in=>hl_temp,en=>en,d_out=>hl); --同上
u8: df port map (clk_in=>clk_in,d_in=>hh_temp,en=>en,d_out=>hh); --同上
u9: duan port map(hl=>hl_temp,hh=>hh_temp,b=>b);---产生AM、PM显示
end rtl;
3)校时模块的仿真图:
图七 校时模块仿真图
仿真结果分析:
从以上仿真图可以明显的看出sclock、mclock、hclock 的每一次按动都会给相应的模块预置值加1,而且按键的同时伴有按键声音,sclock按动6次,mclock按动11次,hclock按动一次,最终显示的时间为01时11分06秒,显示为AM,同预期结果完全吻合。
四:万年历模块
本模块实现万年历功能,根据用户设定的初始的
展开阅读全文