VHDL数字钟设计
题目:VHDL数字钟设计
1 设计要求
1:可以正常计时,能够准确实现由秒到分,由分到时的进位;
2:具有修改时间功能,可以对分位和时位置数;
3:具有整点报时功能,分位向时位进位时响铃;
4:具有闹钟功能,可以设置闹钟时间,当闹钟时间与计时时间一样时响铃;
2 设计分析及系统方案设计
1:正常计时,采用三个进程,分别控制秒、分、时,低位进程走满时产生进位信号控制高位。
2:修改时间,采用键5、6、7、8和键4配合,当键4按下方可保存修改值。四键中某一个按下时,每一个时钟沿,分别对应分加1、分减1、时加1、时减1。
3:整点报时,当秒个位为9、秒十位为5,、分个位为9、分十位为5时,再来一个时钟信号则时个位加1以上各位都清零,同时响铃,响铃持续一分钟。
4:闹钟,设置一个闹钟位,当闹钟位置1时调整时间是设置闹钟时间,当闹钟位置0时调整时间是设置正常计时的时间。设置好闹钟时间后,当正常计时的分个位、分十位、时个位、时十位均与设置的闹钟时间相等时响铃一分钟。
3系统以及模块硬件电路设计
下载时选择的开发系统模式以及管脚定义(注:采用模式“0”)
4 系统的VHDL设计
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity dc_1 is
port( clk,alarm,close,set:in std_logic;
--走时频率,闹钟频率,修改控制键,脑中设置控制键
choice: in std_logic_vector(3 downto 0);
--模式选择键组合
speak : out std_logic; --喇叭频率来源
s1,s2,m1,m2,h1,h2 :out std_logic_vector(3 downto 0));
--时间输出,依次是秒个位,秒十位,分个位,分十位,时个位,时十位end;
architecture a of dc_1 is
signal s_1,s_2,m_1,h_1,m_2,h_2 : std_logic_vector(3 downto 0);
--存正常走时的时间,不能存修改的时间
signal ss1,ss2,mm1,hh1,mm2,hh2 : std_logic_vector(3 downto 0);
--转存所有时间,赋值给输出
signal as1,as2,am1,ah1,am2,ah2 : std_logic_vector(3 downto 0):
--存放闹钟设定值
signal clksp,x,y: std_logic;
--整点报时低频信号,分走满的进位信号,时走满的进位信号signal n:std_logic_vector(1 downto 0); --控制分频产生clksp begin
process(alarm)
begin --get low frequency of strike on the hour if alarm'event and alarm='1' then
if n="10" then
n<="00";clksp<=not clksp;
else n<=n+1;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk='1' then --second if(s_1="0101" and s_2="1001") then
s_1<="0000";s_2<="0000";x<='1';
elsif (s_2="1001") then
s_2<="0000";s_1<=s_1+1;x<='0';
else s_2<=s_2+1;x<='0';
end if;
end if;
end process;
process(clk) --adjust the second to match minute and hour begin
if clk'event and clk='1' then ss1<=s_1;ss2<=s_2;
end if;
end process;
process(clk)
begin if close='1' then m_1<=mm1;m_2<=mm2; --minute elsif clk'event and clk='0' then
if s_2="1001" and s_1="0101" then
if m_2="1001" then
m_2<="0000";
if (m_1="0101") then
m_1<="0000";y<='1';
else m_1<=m_1+1;y<='0';
end if;
else m_2<=m_2+1;y<='0';
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk='1' then ---change minute if set='0' then
if choice="0000" then
mm1<=m_1;mm2<=m_2;
elsif choice="0001" then
if (mm2="1001" and mm1="0101") then
mm2<="0000";mm1<="0000";
elsif mm2="1001" then
mm2<="0000";mm1<=mm1+1;
else mm2<=mm2+1;
end if;
elsif choice="0010" then
if (mm2="0000" and mm1="0000") then
mm2<="1001";mm1<="0101";
elsif (mm2="0000") then
mm2<="1001";mm1<=mm1-1;
else mm2<=mm2-1;
end if;
end if;
end if;
end if;
end process;
process(clk) --hour begin
if close='1' then h_1<=hh1;h_2<=hh2;
elsif clk'event and clk='0' then
if x='1' and y='1' then
if (h_1="0010" and h_2="0100") then
h_1<="0000" ;h_2<="0000";
elsif(h_2="1001") then
h_2<="0000";h_1<=h_1+1;
else h_2<=h_2+1;
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk=’1’ then --change hour if set='0' then
if choice="0000" then
hh1<=h_1;hh2<=h_2;
elsif choice="0100" then
if (hh2="0100" and hh1="0010") then
hh2<="0000";hh1<="0000";
elsif hh2="1001" then
hh2<="0000";hh1<=hh1+1;
else hh2<=hh2+1;
end if;
elsif choice="1000" then
if (hh2="0000" and hh1="0000") then
hh2<="0100";hh1<="0010";
elsif (hh2="0000") then
hh2<="1001";hh1<=hh1-1;
else hh2<=hh2-1;
end if;
end if;
end if;
end if;
end process;
process(clk,set) --set alarm begin
if clk'event and clk='1' then
if set='1' then
if choice="0001" then --set second if (as2="1001" and as1="0101") then
as2<="0000";as1<="0000";
elsif as2="1001" then
as2<="0000";as1<=as1+1;
else as2<=as2+1;
end if;
elsif choice="0010" then --set min
if (am2="1001" and am1="0101") then
am2<="0000";am1<="0000";
elsif am2="1001" then
am2<="0000";am1<=am1+1;
else am2<=am2+1;
end if;
elsif choice="0100" then --set hour if (ah2="0100" and ah1="0010") then
ah2<="0000";ah1<="0000";
elsif ah2="1001" then
ah2<="0000";ah1<=ah1+1;
else ah2<=ah2+1;
end if;
end if;
end if;
end if;
end process;
process(clk)
begin --display if set='1' then
s1<=as1;s2<=as2;m1<=am1;m2<=am2;h1<=ah1;h2<=ah2;
else
s1<=s_1;s2<=s_2;m1<=mm1;m2<=mm2;h1<=hh1;h2<=hh2;
end if;
end process;
process(clk)
begin --alarm control and speaker control if set='0' then
if (mm1=am1 and mm2=am2 and hh1=ah1 and hh2=ah2) then
speak<=alarm;
elsif mm1="0101" and mm2="1001" and ss1="0101" then
if ss2="0010" or ss2="0100" or ss2="0110" or ss2="1000" then
speak<=clksp;
end if;
elsif mm1="0000" and mm2="0000" and ss1="0000" and ss2="0000" then
if hh1="0000" and hh2="0000" then
speak<='0';
else
speak<=alarm;
end if;
else speak<='0';
end if;
end if;
end process;
end;
5 结论以及结果说明
在windows系统下运行MAX+PLUSII10.2软件,编译仿真成功后,连接引脚,实验箱选择EPF10K10LC84-4。执行程序后,时钟从00:00:00开始计时并且扬声器发出响声,因为初始闹钟设置时间也默认为00:00:00,这时按下alarm键可进入闹钟时间设置状态,数码管显示的为闹钟时间,再按下mdm键设置闹钟的分位,设置完成后弹起mdm键,再按下mdh键设置闹钟的时位,设置完成后弹起mdh 键,这时再弹起alarm键,则闹钟设置完毕,数码管重新显示计时时间,因为闹钟时间与计时时间不再一样,所以扬声器不再发出声音。
假设以上设置的闹钟时间为,23:58:00,在alarm弹起的状态下,按下mdm,将分位设为57,然后弹起mdm,再按下mdh,将时位设为23,然后弹起mdh。这时正常计时的时间已变成23:57:xx,等秒位计数到59然后计数变为23::58:00,
这时扬声器开始发出响声,铃响一分钟,当时间为23:59:00时停止铃响。再计时一分钟,计时变为00:00:00时,扬声器发出短暂铃响,这是整点报时。
以上调试过程已经实现了设计要求的4个功能,既正常计时,设置时间,整点报时,闹钟。但该程序仍有不足之处,因为在设置时钟时间和闹钟时间时,其它位都暂停了计时,如果设置的时间很长将会影响数字钟的准确度。
图1 设置闹钟
图1是闹钟时间设置的仿真波形,将闹钟时间设置成了20:19:00
图2 闹钟铃响
图2是闹钟铃响的波形图,当时间为20:19:00时铃响一分钟
图3 整点报时
图3是整点报时的波形,当23:59:59的时候,全部清零,并且spk短暂置1
图4 调整时间
图4是设置时间的波形,mdm和mdh分别置1,快速将时间从06:04:53调成23:27:03