【数字钟】课程设计VHDL语言
一、设计要求
1.具有时,分,秒,计数显示功能,以24小时循环计时。
2.具有清零,调节小时、分钟功能。
3.具有整点报时功能。
二、实验目的
1.掌握多位计数器相连的设计方法。
2.掌握十进制,六进制,二十四进制计数器的设计方法。
3.继续巩固多位共阴级扫描显示数码管的驱动,及编码。
4.掌握扬声器的驱动。
5.掌握EPLD技术的层次化设计方法。
三、实验原理
1.时钟计数:
秒——60进制BCD码计数;
分——60进制BCDD码计数;
时——24进制BCDD码计数;
整个计数器有清零,调分,调时功能,在接近整数时间能提供报时信号。
2.具有驱动8位八段共阴扫描数码管的片选驱动信号输出和八段字形译码输出,编码和扫描部分可参照前面实验。
3.扬声器在整点时有报时驱动信号产生。
四、实验内容及步骤
1.根据电路持点,可在教师指导下用层次设计概念,将此设计任务分成若干模块,规定每一模块的功能和各模块之间的接口,让几个学生分做和调试其中之一,然后再将各模块合起来联试,以培养学生之间的合作精神,同时加深层次化设计概念。
2.了解软件的元件管理深层含义,以及模块元件之间的连接概念。了解如何融合不同目录下的统一设计。
模块说明:
各种进制的计数及时钟控制模块(10进制、6进制、24进制);
扫描分时显示,译码模块;
扬声器编码模块;
各模块都是由VHDL语言编写。
图26-1 数字钟各模块连接示意图
五、实验程序和电路图
(component是对要用的已经生成好的原件模块申明,port map是原件的输入输出端口映射,相当于各个元件之间的端口连线。)
【主程序】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
LIBRARY work;
ENTITY clock_tp IS
PORT
(
clkdsp : IN STD_LOGIC;--系统时钟
reset : IN STD_LOGIC;--系统复位
clk : IN STD_LOGIC;--时钟频率
f : OUT STD_LOGIC;--数码管f
g : OUT STD_LOGIC;--数码管g
c : OUT STD_LOGIC;--数码管c
d : OUT STD_LOGIC;--数码管d
e : OUT STD_LOGIC;--数码管e
b : OUT STD_LOGIC;--数码管b
a : OUT STD_LOGIC;--数码管a
speaker : OUT STD_LOGIC;--蜂鸣器
dp : OUT STD_LOGIC;----数码管dp
M : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --模式选择位
selout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) --数码管选择);
END clock_tp;
ARCHITECTURE bdf_type OF clock_tp IS
--分计数模块
COMPONENT minute
PORT(clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
enhour : OUT STD_LOGIC;
daout : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END COMPONENT;
--数码管译码显示功能模块
COMPONENT deled
PORT(num : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
led : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END COMPONENT;
--秒计数模块
COMPONENT second
PORT(clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
--setmin : IN STD_LOGIC;
enmin : OUT STD_LOGIC;
daout : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END COMPONENT;
--时计数模块
COMPONENT hour
PORT(clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
daout : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) );
END COMPONENT;
--报时功能模块
COMPONENT alert
PORT(clk : IN STD_LOGIC;
dain : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
speak : OUT STD_LOGIC
);
END COMPONENT;
--扫描模块
COMPONENT seltime
PORT(clk1 : IN STD_LOGIC;
reset : IN STD_LOGIC;
hour : IN STD_LOGIC_VECTOR(5 DOWNTO 0);
min : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
sec : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
daout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
sel : OUT STD_LOGIC_VECTOR(2 DOWNTO 0) );
END COMPONENT;
--数码管选择模块,38译码
COMPONENT decode3_8
PORT(SEL : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
Q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) );
END COMPONENT;
--
COMPONENT div_clk
PORT(clk_in : IN STD_LOGIC;
div_out : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL led : STD_LOGIC_VECTOR(0 TO 6);
SIGNAL M_line : STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL lINE_0 : STD_LOGIC;
SIGNAL lINE_1 : STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL lINE_2 : STD_LOGIC;
SIGNAL lINE_9 : STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL lINE_4 : STD_LOGIC;
SIGNAL lINE_5 : STD_LOGIC_VECTOR(5 DOWNTO 0); SIGNAL lINE_7 : STD_LOGIC_VECTOR(6 DOWNTO 0); SIGNAL lINE_8 : STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
dp <= '0';
--分计数模块
b2v_2 : minute
PORT MAP(clk => lINE_0,
reset => reset,
enhour => lINE_2,
daout => lINE_9);
--数码管译码显示功能模块
b2v_23 : deled
PORT MAP(num => lINE_1,
led => led);
--秒计数模块
b2v_24 : second
PORT MAP(clk => clk,
reset => reset,
enmin => lINE_0,
daout => lINE_7);
--时计数模块
b2v_3 : hour
PORT MAP(clk => lINE_2,
reset => reset,
daout => lINE_5);
--报时功能模块
b2v_4 : alert
PORT MAP(clk => clk,
dain => lINE_9,
speak => speaker);
--扫描模块
b2v_5 : seltime
PORT MAP(clk1 => lINE_4,
reset => reset,
hour => lINE_5,
min => lINE_9,
sec => lINE_7,
daout => lINE_1,
sel => lINE_8);
--数码管选择模块,38译码
b2v_inst1 : decode3_8
PORT MAP(SEL => lINE_8,
Q => selout);
--
b2v_inst2 : div_clk
PORT MAP(clk_in => clkdsp,
div_out => lINE_4);
f <= led(5);
g <= led(6);
c <= led(2);
d <= led(3);
e <= led(4);
b <= led(1);
a <= led(0);
M <= M_line;
M_line(1) <= '1';
M_line(0) <= '0';
M_line(2) <= '0';
M_line(3) <= '0';
END bdf_type;
【子程序--秒计数】LIBRARY ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;
ENTITY second IS
PORT(
clk : IN STD_LOGIC; --外部时钟频率
reset :IN STD_LOGIC; --复位
enmin : OUT STD_LOGIC; --向分进位
daout: out std_logic_vector (6 downto 0));--秒计数
END entity second;
ARCHITECTURE fun OF second IS
SIGNAL count: STD_LOGIC_VECTOR( 6 downto 0);
BEGIN
daout <= count;
process ( clk , reset )
begin
if (reset='0') then--复位
count <= "0000000";
elsif (clk 'event and clk='1') then --clk上升沿
if (count(3 downto 0)="1001") then --个位计数到9
if (count <16#60#) then --count小于60H
if (count="1011001") then--count等于59H
enmin<='1'; --就给进位置1
count<="0000000"; --count归零初始化
ELSE
count<=count+7; --跳过ah,bh,ch,dh,eh,fh。十六进制调整为十进制。
end if;
else
count<="0000000";--count归零初始化
end if;
elsif (count < 16#60#) then
count <= count+1;--count计数加1
enmin<='0' ;
else
count<="0000000";
end if;
end if;
end process;
END fun;
【子程序—分计数】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY minute IS
PORT(
clk : IN STD_LOGIC;--second进位频率
reset : IN STD_LOGIC;--复位
enhour : OUT STD_LOGIC;--向时进位
daout: out std_logic_vector (6 downto 0));--分计数
END entity minute;
ARCHITECTURE fun OF minute IS
SIGNAL count: STD_LOGIC_VECTOR( 6 downto 0);
BEGIN
daout <= count;
process ( clk,reset)
begin
if (reset='0') then--复位
count <= "0000000";
elsif (clk' event and clk='1') then--clk上升沿
if (count(3 downto 0)="1001") then--个位计数到9
if (count <16#60#) then--count小于60H
if (count="1011001") then--count等于59H
enhour<='1'; --就给进位置1
count<="0000000"; --count归零初始化
ELSE
count<=count+7; --跳过ah,bh,ch,dh,eh,fh。十六进制调整为十进制。
end if;
else
count<="0000000";--count归零初始化
end if;
elsif(count <16#60#) then
count <= count + 1;--count计数加1
enhour<='0' ;
else
count<="0000000";
end if;
end if;
end process;
END fun;
【子程序—时计数】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY hour IS
PORT(
clk: IN STD_LOGIC; --分进位频率
reset: IN STD_LOGIC;--复位
daout: out std_logic_vector (5 downto 0));--十计数
END entity hour;
ARCHITECTURE fun OF hour IS
SIGNAL count: STD_LOGIC_VECTOR( 5 downto 0);
BEGIN
daout <= count;
process ( clk,reset)
begin
if (reset='0') then--复位
count <= "000000";
elsif (clk' event and clk='1') then--clk上升沿
if (count(3 downto 0)="1001") then--个位计数到9
if (count <16#23#) then--count小于23H
count<=count + 7; --跳过ah,bh,ch,dh,eh,fh。十六进制调整为十进制。
else
count<="000000";--count归零初始化
end if;
elsif(count <16#23#) then --count小于23H
count <= count + 1;--count计数加1
else
count<="000000";--count归零初始化
end if;
end if;
end process;
END fun;
【子程序—数码管译码显示】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY deled IS
PORT(num: IN std_logic_vector( 3 downto 0);
led: OUT std_logic_vector(6 downto 0)); END deled;
ARCHITECTURE fun OF deled IS
BEGIN
led <= "1111110" when num= "0000" else--0真值
"0110000" when num= "0001" else--1真值
"1101101" when num= "0010" else--2真值
"1111001" when num= "0011" else--3真值
"0110011" when num= "0100" else--4真值
"1011011" when num= "0101" else--5真值
"1011111" when num= "0110" else--6真值
"1110000" when num= "0111" else--7真值
"1111111" when num= "1000" else--8真值
"1111011" when num= "1001" else--9真值
"1110111" when num= "1010" else--A真值
"0011111" when num= "1011" else--b真值
"1001110" when num= "1100" else--C真值
"0111101" when num= "1101" else--d真值
"1001111" when num= "1110" else--E真值
"1000111" when num= "1111" ;--F真值END fun;
【子程序—报时功能】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY alert IS
PORT(
clk : IN STD_LOGIC;
dain : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
speak: OUT STD_LOGIC
);
END alert ;
ARCHITECTURE fun OF alert IS
signal count: std_logic_vector( 1 downto 0);
BEGIN
speaker:process (clk)
begin
speak <= count(1);
if (dain = "0000000") then--当分计时为0时蜂鸣器开始报数if (clk 'event and clk= '1') then--外部时钟频率为高电平就响
if (count="01") then --3秒循环,响一秒停两秒
count<="11";
else
count <= count - 1;
end if;
end if;
end if;
end process speaker;
END fun ;
【子程序—数码管选择(38译码)】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY decode3_8 IS
PORT(SEL: IN std_logic_vector(2 downto 0);
Q : OUT std_logic_vector(7 downto 0)
);
END decode3_8;
ARCHITECTURE a OF decode3_8 IS
BEGIN
Q <= "11111110" when sel = 0 else--数码管0
"11111101" when sel = 1 else--数码管1
"11111011" when sel = 2 else--数码管2
"11110111" when sel = 3 else--数码管3
"11101111" when sel = 4 else--数码管4
"11011111" when sel = 5 else--数码管5
"11111111";
END a;
【子程序—扫描】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
ENTITY seltime IS
PORT(
clk1: IN STD_LOGIC;--内部时钟频率
reset: IN STD_LOGIC;--复位
sec: IN STD_LOGIC_VECTOR(6 downto 0);--秒计数信号
min : IN STD_LOGIC_VECTOR(6 downto 0);--分计数信号
hour : in std_logic_vector (5 downto 0);--时计数信号
daout : OUT STD_LOGIC_vector (3 downto 0);--BCD数据输出
sel : out std_logic_vector ( 2 downto 0)--扫描信号
);
END seltime;
ARCHITECTURE fun OF seltime IS
SIGNAL count: STD_LOGIC_vector ( 2 downto 0);
BEGIN
sel <= count;
process ( clk1,reset)
begin
if (reset ='0') then
count <= "000";
elsif (clk1 'event and clk1='1') then
if ( count >= "101") then--数码管超过编号5
count <= "000";--count归零
else
count <= count + 1;--count加1.现在sel就在不断扫描0~5这6个数码管。
end if;
end if;
case count is--
when "000" => daout <= sec(3 downto 0);--数码管0,输出秒计数低四位
when "001" => daout(3) <= '0';--daout最高位(第3位)补0
daout(2 downto 0) <= sec (6 downto 4);--数码管1输出秒计数高三位when "010" => daout <= min (3 downto 0);--数码管2,输出分计数低四位
when "011" => daout(3) <= '0';--daout最高位(第3位)补0
daout(2 downto 0) <= min (6 downto 4);--数码管3,输出分计数高三位when "100" => daout <= hour (3 downto 0);--数码管4,输出时计数低四位
when others => daout(3 downto 2) <= "00";--daout高二位(第3位第2位)补00
daout(1 downto 0) <= hour(5 downto 4);--数码管5,输出时计数高二位end case;
end process;
end fun;
【子程序— div_clk 】
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY div_clk IS
PORT(clk_in : IN std_logic;--内部时钟频率
div_out: OUT std_logic);--频率输出
END div_clk;
ARCHITECTURE a OF div_clk IS
SIGNAL fre_N : integer range 0 to 100000;
SIGNAL clk_tmp: std_logic;
BEGIN
div_out <= clk_tmp;
process(clk_in)
begin
if falling_edge(clk_in) then
if fre_N >= 99999 then--大于等于99999
fre_N <= 0;--则fre_N归零
clk_tmp <= not clk_tmp;--clk_tmp求反else
fre_N <= fre_N + 1;--fre_N加1
end if;
end if;
end process;
END a;
【电路图】
六、实验连线
◎输入接口:
1.代表清零,调时,调分信号RESET,SETHOUR,SETMIN的管脚分别已经连接按键开关。
2.代表计数时钟信号CLK和扫描时钟信号CKDSP的管脚分别已经同1HZ时钟源和32HZ (或更高)时钟源相连。
3.Reset键为低电平复位,已经接上。
◎输出接口:
1.代表扫描显示的驱动信号管脚SCAN2,SCAN1,SCAN0已经接到实验箱上的SCAN0~SCAN2,A…G接八位数码管显示模块的A~G。
2.代表花样LED灯显示的信号管脚LAMP0…LAMP2已经同3个LED灯相连。代表到时LED 灯闪烁提示的ENHOUR接LED灯。
SETHOUR、SETMIN分别对应CPU板上的PB0、PB1(有些CPU板对应的标识是SW1、
SW2)
RESET对应CPU板上的RESET。CLKDSP对应CPU板上的50MHz固定晶振输入。LAMP对应IO9-IO11。CLK,对应IO3。
功能选择位M[3..0]状态为0010,左端8个数码管,低8位为7位段加小数点选取位,高8位为8个数码管com端选取,即如果要选取数码管0,则发送总线值为:1111 1110 1111 1111,如要选取数码管1,则发送总线值为:1111 1101 1111 1111,此时所选数码管7段和
DP位将全部亮。
底板上ADJ_CLK为4位拨码开关SW17--SW20来控制输出40M分频后的可调时钟
具体对应如下:
SW20 SW19 SW18 SW17 ADJ_CLK
1 1 1 1 1Hz
0 1 1 1 5Hz
1 0 1 1 10Hz
0 0 1 1 25Hz
1 1 0 1 50Hz
0 1 0 1 500Hz
1 0 0 1 1KHz
0 0 0 1 2.5KHz
1 1 1 0 10KHz
0 1 1 0 20KHz
1 0 1 0 50KHz
0 0 1 0 200KHz
1 1 0 0 500KHz
0 1 0 0 2MHz
1 0 0 0 5MHz
0 0 0 0 20MHz
接线:用导线连接IO3与ADJ_CLK,调整SW17-SW20,使输出频率为1Hz;
IO5接到蜂鸣器的BUZZER控制端口。
按下PB0、PB1(有些CPU板对应的标识是SW1、SW2)可以调整时钟,分钟。