用VHDL语言设计的数字电子钟
《电子设计自动化(EDA)技术》课程实训报告
1、课程设计内容与要求 (3)
1.1 设计内容 (3)
1.2 具体内容 (3)
2、系统设计 (3)
2.1 设计思路 (3)
2.2 系统原理 (4)
3、系统的实现 (6)
3.1 秒计数器模块及代码 (6)
3.2 分钟计数器模块及代码 (7)
3.3 小时计数器模块及代码 (8)
3.4 数码管位选择信号模块及代码 (9)
3.5 多路选择器模块及代码 (9)
3.6 七段译码器模块及代码 (10)
3.7 整点报时模块及代码 (10)
3.8 自动电子钟源代码 (10)
4、系统的仿真 (14)
4.1 VHDL的工作环境 (14)
4.2程序的编译和波形的仿真 (15)
4.3引脚的设置 (18)
4.4 全程编译及配置文件下载 (19)
5、硬件验证说明 (20)
6、总结 (21)
7、参考书目 (21)
数字电子钟设计
王海峰
重庆三峡学院应用技术学院电子信息工程(仪器仪表)2008级重庆万州404000
摘要:基于VHDL的自动电子钟,芯片采用ALTERA公司的ACEX1K 系列的EP1K10TC100-3,本文在简要介绍了EDA技术特点的基础上,用EDA技术作开发手段,运用VHDL语言,采用了自顶向下的设计方法,实现计时24小时的电子时钟的设计,并利用Quartus II 软件集成开发环境进行编译、综合、波形仿真、定义管脚,并下载到FPGA器件中,经实际电路测试,该系统性能实现。
关键词:VHDL EDA 数字电子钟 FPGA
1、课程设计内容与要求
1.1 设计内容
数字电子钟
1.2 具体内容
1.用24小时制进行时间显示;
2.能够显示小时、分钟、秒;
3.通电后从“00 00 00”开始显示。
4. 随时可复位,可暂停工作;
5. 整点报时。
2、系统设计
2.1 设计思路
数字电子钟端口说明
1.clk信号为实验板上的标准的1Hz脉冲。
2.en信号为使能端,en信号为低电平,此时所有的显示器均不显示,en为高电平时,所有的显示器均从0开始递增的工作。
3. clr信号为高电平清零信号。
4.Scanclk信号为数码管的位选择时钟信号。
5.led<7:0>信号是来驱动数码管显示的。
6.sel<2:0>为位选择控制信号,决定哪一个数码管显示数字。
7. speaker为报时用的扬声器端口输出信号。
2.2系统原理
自动电子钟将采用模块化的设计,模块分别是数码管位选择信号、秒计数器、分计数器、时计数器、多路选择器、7段译码器。用VHDL编写程序实现自动电子钟,其系统原理模块如下:
实际设计实现原理图如下:
数字电子钟原理图
1.进程P1描述60s计数器,输出秒个位的BCD码。
2.进程P2描述60min计数器,根据秒计数器的输出值,输出分十位和分个位的BCD 码。
3.进程P3描述23h计数器,根据秒计数器和分计数器的输出值,输出小时十位和个位的BCD码。
4.进程P4和P5根据进程产生数码管的位选择信号,从小时、分钟和秒中,选择一个BCD码给7段译码器。
5. 进程P6作为报时装置,当整点时就输出高电平,由Speaker发出声音。
3、系统的实现
3.1 秒计数器模块及代码
秒是这次电子钟设计的最底层模块.其核心是一个60进制计数器,以外来时钟信号作为其触发时钟信号,当外来信号进入clk时钟信号端,其内部的60进制计数器便开始工作,对信号源进行计数.计数结果由led<7:0>输出至数码管显示秒钟时间.当计数到60时,其值置零,并向外输出一个进位信号sj,这个进位信号便为下个分钟模块的输入时钟信号。
p1:process(clk,en,clr) --60秒计数器
VARIABLE s11:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE s21:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF clr='1' THEN
s11:=(OTHERS=>'0');
s21:=(OTHERS=>'0');
ELSIF clk'EVENT AND clk='1' THEN
IF EN='1' THEN
IF s21<9 THEN
s21:=s21+1;
ELSE
s21:=(OTHERS=>'0');
IF s11<5 THEN
s11:=s11+1;
ELSE
s11:=(OTHERS=>'0');
END IF;
END IF;
END IF;
END IF;
IF (s11=5 AND s21=9) THEN
sj<='1';
ELSE
sj<='0';
END IF;
s1<=s11;
s2<=s21;
end process p1;
3.2 分钟计数器模块及代码
分钟模块核心也是一个60进制计数器,其功能的实现是将秒模块的进位信号进行计数,计数结果由led<7:0>输至数码管显示,当计数至60是数值置零,并向外输出进位信号mj。
p2:process(sj,en,clr) --60分计数器
VARIABLE m11:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE m21:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF clr='1' THEN
m11:=(OTHERS=>'0');
m21:=(OTHERS=>'0');
ELSIF sj'EVENT AND sj='1' THEN
IF EN='1' THEN
IF m21<9 THEN
m21:=m21+1;
ELSE
m21:=(OTHERS=>'0');
IF m11<5 THEN
m11:=m11+1;
ELSE
m11:=(OTHERS=>'0');
END IF;
END IF;
END IF;
END IF;
IF (m11=5 AND m21=9) THEN
mj<='1';
ELSE
mj<='0';
END IF;
m1<=m11;
m2<=m21;
end process p2;
3.3 小时计数器模块及代码
小时模块核心也是一个60进制计数器,其功能的实现是将分钟模块的进位信号进行计数,计数结果由led<7:0>输至数码管显示,当计数至60是数值置零。
p3:process(mj,en,clr) --24小时计数器
VARIABLE h11:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE h21:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF clr='1' THEN
h11:=(OTHERS=>'0');
h21:=(OTHERS=>'0');
ELSIF mj'EVENT AND mj='1' THEN
IF EN='1' THEN
IF h21<3 THEN
h21:=h21+1;
ELSE
h21:=(OTHERS=>'0');
IF h11<2 THEN
h11:=h11+1;
ELSE
h11:=(OTHERS=>'0');
END IF;
END IF;
END IF;
END IF;
h1<=h11;
h2<=h21;
end process p3;
3.4 数码管位选择信号模块及代码
数码管位选择信号核心在于结合多路选择器从小时、分钟和秒中,选择一个BCD码给7段译码器。
P4:process(scanclk) --动态扫描时钟
begin
if rising_edge(scanclk) then
if dispcnt="101" then
dispcnt<="000";
else
dispcnt<=dispcnt+'1';
end if; end if;
end process P4;
3.5 多路选择器模块及代码
多路选择器核心在于结合数码管为选择信号从小时、分钟和秒中,选择一个BCD码给7段译码器。
P5:process(dispcnt) --选择对应位的BCD码
begin
if dispcnt="000" then
sel<="000";data<=h1;
elsif dispcnt="001"then
sel<="001";data<=h2;
elsif dispcnt="010"then
sel<="010";data<=m1;
elsif dispcnt="011"then
sel<="011";data<=m2;
elsif dispcnt="100"then
sel<="100";data<=s1;
elsif dispcnt="101"then
sel<="101";data<=s2;
end if;
end process P5;
3.6 七段译码器模块及代码
对多路选择器输出的信号进行译码,驱动7段数码管的显示。
--a,b,c,d,e,f,g,dp
with data select --7段译码器
led<= "11111100" when "0000", --0
"01100000" when "0001", --1
"11011010" when "0010", --2
"11110010" when "0011", --3
"01100110" when "0100", --4
"10110110" when "0101", --5
"00111110" when "0110", --6
"11100000" when "0111", --7
"11111110" when "1000", --8
"11100110" when "1001", --9
"00000000" when others;
3.7 整点报时模块及代码
当分位和秒位时钟同时为零时,进行整点报时,输出高电平信号驱动speaker发出声音。
P6:process(m1,m2,s1,s2) --整点报时
begin
if((m1="0000")and(m2="0000")and(s1="0000")and(s2="0000")) then
speaker<='1';
else
speaker<='0';
end if;
end process p6;
3.8 自动电子钟源代码
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity shizhong is
port(clk,en,scanclk,clr:in std_logic;
sel:out std_logic_vector(2 downto 0);
speaker:out std_logic;
led: out std_logic_vector( 7 downto 0));
end shizhong;
architecture szdzz of shizhong is
signal h2,h1,m2,m1,s2,s1:std_logic_vector(3 downto 0); signal sj,mj:std_logic;
signal data:std_logic_vector(3 downto 0);
signal dispcnt: std_logic_vector(2 downto 0);
begin
p1:process(clk,en,clr) --60秒计数器 VARIABLE s11:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE s21:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF clr='1' THEN
s11:=(OTHERS=>'0');
s21:=(OTHERS=>'0');
ELSIF clk'EVENT AND clk='1' THEN
IF EN='1' THEN
IF s21<9 THEN
s21:=s21+1;
ELSE
s21:=(OTHERS=>'0');
IF s11<5 THEN
s11:=s11+1;
ELSE
s11:=(OTHERS=>'0');
END IF;
END IF;
END IF;
END IF;
IF (s11=5 AND s21=9) THEN
sj<='1';
ELSE
sj<='0';
END IF;
s1<=s11;
s2<=s21;
end process p1;
p2:process(sj,en,clr) --60分计数器 VARIABLE m11:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE m21:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF clr='1' THEN
m11:=(OTHERS=>'0');
m21:=(OTHERS=>'0');
ELSIF sj'EVENT AND sj='1' THEN
IF EN='1' THEN
IF m21<9 THEN
m21:=m21+1;
ELSE
m21:=(OTHERS=>'0');
IF m11<5 THEN
m11:=m11+1;
ELSE
m11:=(OTHERS=>'0');
END IF;
END IF;
END IF;
END IF;
IF (m11=5 AND m21=9) THEN
mj<='1';
ELSE
mj<='0';
END IF;
m1<=m11;
m2<=m21;
end process p2;
p3:process(mj,en,clr) --24小时计数器 VARIABLE h11:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE h21:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF clr='1' THEN
h11:=(OTHERS=>'0');
h21:=(OTHERS=>'0');
ELSIF mj'EVENT AND mj='1' THEN
IF EN='1' THEN
IF h21<3 THEN
h21:=h21+1;
ELSE
h21:=(OTHERS=>'0');
IF h11<2 THEN
h11:=h11+1;
ELSE
h11:=(OTHERS=>'0');
END IF;
END IF;
END IF;
END IF;
h1<=h11;
h2<=h21;
end process p3;
P6:process(m1,m2,s1,s2) --整点报时
begin
if((m1="0000")and(m2="0000")and(s1="0000")and(s2="0000")) then speaker<='1';
else
speaker<='0';
end if;
end process p6;
p4:process(scanclk) --动态扫描时钟
begin
if rising_edge(scanclk)then
if dispcnt="101"then
dispcnt<="000";
else
dispcnt<=dispcnt+'1';
end if;
end if;
end process p4;
P5:process(dispcnt) --选择对应位的BCD码
begin
if dispcnt="000" then
sel<="000";data<=h1;
elsif dispcnt="001"then
sel<="001";data<=h2;
elsif dispcnt="010"then
sel<="010";data<=m1;
elsif dispcnt="011"then
sel<="011";data<=m2;
elsif dispcnt="100"then
sel<="100";data<=s1;
elsif dispcnt="101"then
sel<="101";data<=s2;
end if;
end process P5;
--a,b,c,d,e,f,g,dp
with data select --7段译码器
led<= "11111100" when "0000", --0
"01100000" when "0001", --1
"11011010" when "0010", --2
"11110010" when "0011", --3
"01100110" when "0100", --4
"10110110" when "0101", --5
"00111110" when "0110", --6
"11100000" when "0111", --7
"11111110" when "1000", --8
"11100110" when "1001", --9
"00000000" when others;
end szdzz;
4、系统的仿真
4.1 VHDL的工作环境
在菜单栏中选择File New New Quartus Project。芯片的选择:
4.2程序的编译和波形的仿真
芯片的选择一定要与实验室或者自己购买的芯片一致。项目创建完之后,接着就新建一个VHDL语言的文件,创建方法和项目的创建大同小异,File New VHDL
File。然后将自己的程序写入:
程序输入完之后,就进行语法编写,语法编译是检查程序的正确性,若有错误,程序自动指出。
在命令栏中选择Start Analysis & synthesis按钮,编译后成功后如下(警告可以忽略):
接下来就是波形的仿真,首先还是要新建一个波形文件,方法是File Vector WaveForm File,然后把程序中的输入输出端导入到这个波形中:
导入完后,就是设置输入端的初始值:
最后就是波形的编译,编译之前,一定要先进行网表的生成:
网表生成后才能波形的仿真,结果如下:
方法是在菜单栏中选择Assignment Editor
然后在Category中选择Pin
然后逐个的进行设置:
4.4 全程编译及配置文件下载
在菜单栏中点击Start Comiplation进行全程编译
最后一步就是程序的下载(配置文件的下载),点击菜单栏中的Programmer图标
图中所示,点击Start,程序的所有相关配置文件就下载到FPGA中。
5、硬件验证说明
程序下载到FPGA中,接好相应的引脚线之后,使能端置‘0’时,数码管全显示0,,
当使能端置‘1’时,数码管均从0开始递增的工作。