vhdl 实现时钟整点报时功能

1.具有整点报时功能,每当59分55秒,56秒,57秒,58秒,59秒报时,前5秒低音,最后一秒高音

1、完成秒/分/时的依次显示并正确计数;
2、秒/分/时各段个位满10正确进位,秒/分能做到满60向前进位;
3、定时闹钟:实现每到整点时报时,扬声器发出报时声音;
4、时间设置,也就是手动调时功能:当认为时钟不准确时,可以分别对分/时钟进行调整;秒还可以手动调0;
分频模块:
源代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity yxfrequencydivider is
port(clk:in std_logic;
hz512,hz256,hz64,hz4,hz1:out std_logic);
end yxfrequencydivider ;
architecture hz of yxfrequencydivider is
signal count:std_logic_vector(9 downto 0);
begin
process(clk)
begin
if (clk'event and clk='1') then
if (count="1111111111") then
count<="0000000000";
else
count<= count+1;
end if;
end if;
end process;
hz512 <= count(0);
hz256 <= count(1);
hz64 <= count(3);
hz4<=count(7);
hz1<=count(9);
end architecture;

模块说明:由于clk的频率为1024hz,所以可以定义一个std_logic_vecture(9 downto 0),使它不停地从0000000000加到1111111111然后又返回000000000,由于最低位在clk脉冲到来时从0变成1,然后又在下一个脉冲变回0,因此最低位的时钟周期为clk的时钟周期的两倍,它的频率就为clk频率的1/2即512HZ。同理,次高位的频率就为clk频率的1/2*1/2=1/4,用这种方法就可以得到各种能整除1024的频率,从而实现分频功能。
24进制模块
源程序
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity m24 is
port(cp:in std_logic;
sqmsl,sqmsh:out std_logic_vector(3 downto 0));
end m24;
architecture arh_m24 of m24 is
signal stempl,stemph:std_logic_vector(3 downto 0);
begin
process(cp)
begin
if cp='1' then
if stempl="0011" and stemph="0010" then
stempl<="0000";
stemph<="0000";
else
if stempl=9 then
stempl<="0000";
stemph<=stemph+1;
else
stempl<=stempl+1;
end if;
end if;
end if;
end process;
sqmsl<=stempl;
sqmsh<=stemph;
end architecture;
本模块端口说明:cp为脉冲输入端;sqmsh和sqmsl分别为小时的高位和低位输出,用来在数码管中分别显示小时的高位和低位数值,定义为std_logic_vector(3 downto 0).
功能实现:在cp高脉冲到时执行以下程序块,如果高位为2,低位为3则高位各低位都变回0,不然再低位进行判断,若为9低位变回0,高位加1,若不为9则低位直接加1即可同样实现.

60进制模块
源程序

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity m60 is
port(cp,clr:in std_logic;
co:out std_logic;
sqmsl,sqmsh:out std_logic_vector(3 downto 0));
end m60;
architecture arh_m60 of m60 is
signal stempl,stemph:std_logic_vector(3 downto 0);
signal stempco:std_logic;
begin
process(cp,clr)
begin
if clr='0' then
stemph<="0000";
stempl<="0000";
else
if cp'event and cp='1' then
stempco<='0';
if stempl=9 then
if stemph=5 then
stempco<='1';
stempl<="0000";
stemph<="0000";
else
stempl<="0000";
stemph<=stemph+1;
end if;
else
stempl<=stempl+1;
end if;
end if;
end if;
end process;
co<=stempco;
sqmsl<=stempl;
sqmsh<=stemph;
end architecture;
本模块端口说明:cp为脉冲信号输入端;clr为置0端,并且低电平有效,用来在校时时秒位清零;co为进位输入端;sqmsh和sqmsl分别是秒或分的高位或低位,定义为std_logic_vector(3 downto 0),用来分别在数码管中显示读数.
功能说明:以cp和clr而敏感变量,先判断clr是否为0,若为0则stemph种stempl都为0000,然后分别赋值给sqmsh和sqmsl;如果不为0,则执行累加;否则,再判断高位是否为5,若为5则进位输出为1、低位和高位都赋予0,若不为5则高位加1,低位赋予0.从而实现了60进制的累加.

扫描显示及译码模块
源程序

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity dongtaism is
port(clk:in std_logic;
s:in std_logic_vector(7 downto 0);
f:in std_logic_vector(7 downto 0);
m:in std_logic_vector(7 downto 0);
selout:out std_logic_vector(5 downto 0);
segout:out std_logic_vector(6 downto 0));
end dongtaism;

architecture a of dongtaism is
signal temp:std_logic_vector(2 downto 0);
signal seg:std_logic_vector(6 downto 0);
signal sel:std_logic_vector(5 downto 0);

begin
process(clk)
variable num:std_logic_vector(3 downto 0);
begin
if (clk'event and clk='1' ) then

if temp>=5 then
temp<="000";
else
temp<=temp+1;
end if;

case temp is
when "101" =>num:=s(7 downto 4);
sel<="100000";
when "100" =>num:=s(3 downto 0);
sel<="010000";
when "011" =>num:=f(7 downto 4);
sel<="001000";
when "010" =>num:=f(3 downto 0);
sel<="000100";
when "001" =>num:=m(7 downto 4);
sel<="000010";
when "000" =>num:=m(3 downto 0);
sel<="000001";
when others=>sel<="000000";
end case;

case num is
when"0000"=>seg<="0111111";
when"0001"=>seg<="0000110";
when"0010"=>seg<="1011011";
when"0011"=>seg<="1001111";
when"0100"=>seg<="1100110";
when"0101"=>seg<="1101101";
when"0110"=>seg<="1111101";
when"0111"=>seg<="0000111";
when"1000"=>seg<="1111111";
when"1001"=>seg<="1101111";
when others=>seg<="0000000";
end case;

end if;
end process;
selout<=sel;
segout<=seg;
end architecture;
本模块端口说明:stempl、stemph、ftempl 、ftemph、mtempl、mtemph
分别为时,分,秒的输入端,定义为std_logic_vector(7 downto 0);segout为七端显示管的输出,定义为std_logic_vector(6 downto 0);selout为扫描地址端,定义为std_logic_vector(5 downto 0),某一时刻只有一个为1,对应的数组号即为当前扫描的数码管的编号.
功能实现:定义一个std_signal_vector(2 downto 0)变量addr,它在0和5之间不断的循环,用来指示当前扫描的哪一根管,循环用if addr>=5 then addr<=”000”; else addr<=addr+1;end if;实现.再定义一个类型为std_logic_vector(5 downto 0)的tempaddr信号,它用来产生一个长度为6的数,该数在同一时刻只有一位是高电平表示正在扫描该显示管,在进程结束时它的值将赋给selout输出.定义一个std_logic_vector(6 downto 0)类型的temp_display,用来存放将由4位BCD码编码而来的7段显示码.最后在进程中定义一个std_logic_vector(3 downto 0)类型的tempnum变量,用来存放时、分、秒的高位或低位,然后将该数编码成7段显示码,并赋给temp_display信号。具体算法如下:
建立一个以cp脉冲为敏感变量的进程,先判断是否是cp的高电平脉冲,若不是则什么也不执行,若是高电平脉冲,则执行以下程序。Adder加1,用case语句根据adder的值,给tempnum赋予当前要扫描的数码管的值,用case语句根据tempnum的值编译成对应的7段显示管的值并赋给temp_display,当进程结束时把temp_display的值赋给segout,把tempaddr的值赋给selout,然后由这两个端口输出。

整点报时模块:
源程序

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity baoshi is
port(m1,m0,s1,s0:in std_logic_vector(3 downto 0);
sig500,sig1k:out std_logic);
end baoshi;

architecture behave of baoshi is
begin
process(m0)
begin
sig500<='0';
sig1k<='0';
if m1="0101" and m0="1001" then
if s1="0101"and (s0="0000" or s0="0010" or s0="0100" or s0="0110" or s0="1000") then
sig500<='1';
else
sig500<='0';
end if;
end if;
if m1="0000" and m0="0000"and s1="0000" and s0="0000" then
sig1k<='1';
else
sig1k<='0';
end if;
end process;
end behave;
本模块端口说明:m1,m0,s1,s0分别为分和秒的高低位的输入;sig500,sig1k分别为500hz和1khz鸣叫的控制信号。
功能实现:定义temp500,temp1k信号,用于存放两种频率报时的控制信号;定义一个以m0为敏感信号的一个比较进程,在进程一开始的时候先给temp500和temp1k赋予初值0,然后判断分是否为59分,若是则判断秒的高位是否是5,若是则如果秒的低位为0、2、6、8则temp500为1;若分不是59则判断分和秒是否都为0,若都为0则temp1k为1。进程结束时把temp500,temp1k的值分别赋给sig500,sig1k。
然后连接顶层图
温馨提示:答案为网友推荐,仅供参考