基于FPGA的数字电子时钟设计VHDL.docx
- 文档编号:7415349
- 上传时间:2023-05-11
- 格式:DOCX
- 页数:31
- 大小:25.21KB
基于FPGA的数字电子时钟设计VHDL.docx
《基于FPGA的数字电子时钟设计VHDL.docx》由会员分享,可在线阅读,更多相关《基于FPGA的数字电子时钟设计VHDL.docx(31页珍藏版)》请在冰点文库上搜索。
基于FPGA的数字电子时钟设计VHDL
一、题目要求
本次设计的是threestarwatch,它所具有的功能和具体的工作介绍如下:
1、功能
1)具有显示年、月、日、时、分、秒的功能,能准确显示时间
2)能够手动设置时间、闹钟。
3)具有闹钟功能,可以设置闹钟的时间,然后再实际时间与设定时间相等是闹钟响,并有闹钟开关,可控制其是否响,闹钟响时伴有流水灯效果。
4)具有秒表功能,可以累计计时
2、工作介绍
此电子时钟开机后即会进入原始状态(全0),按下s3即会显示初始时间,按下s5一次即会显示时分,再按下s5即会显示秒,再按下s5即会显示闹钟,再按下s5即会显示秒表。
1.设置秒表:
进入秒表界面之后,按下s4后,秒表开始计数,再按下s4后,秒表停止计数。
再按下s4,秒表复位。
2.设置日期、时间:
在相应的显示界面,按下s4后,前两位数码管会跳动,此时为可设置状态,按下s5可调整时间,再按下s4,后两位跳动,此时按下s5进行调整,再按下s4即可确定。
3.设置闹钟:
进入闹钟界面后,调整方法跟设置时间的方法一样。
打开拨盘开关s1,d3灯亮表示闹钟处于开启状态。
到达指定时间之后,闹钟响,流水灯跳动。
关闭拨盘开关s1,d3灯灭表示闹钟处于关闭状态。
二、设计方案
设计一个电子手表,必然要用到计时器,而需要设置时间和闹钟,又需要控制器来控制系统所处的状态。
我们采用外部一个按键来切换系统的状态,用另一个按键来调整时间和启动秒表,再有一个按键来确认操作,并返回显示状态,继续等待命令。
在控制器中,需要接受外部信号,并给出信号给计时器,使其做出相应的动作。
三、模块实现及代码
本设计主要分成分频模块,响铃模块,数码管显示模块,流水灯显示模块,主控模块和消抖模块。
各个模块的分析和代码如下:
1、分频模块
此模块主要通过连接外部50MHz时钟信号来控制计数频率,使其产生不同频率的信号,用来进行显示时间和日期。
只要检测时钟上升沿到来,计数器就加1,直至计到相应的数字,又从0开始计时。
代码如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
--FrequencyDivide
entityclkdivis
port(
clk_50MHz:
instd_logic;
clk_2KHz:
outstd_logic;
clk_100Hz:
outstd_logic;
clk_1Hz:
outstd_logic;
clk_4Hz:
outstd_logic_vector(7downto0);
clk_4Hz2:
outstd_logic;
clk_xHz:
outstd_logic
);
endclkdiv;
architecturebehavofclkdivis
begin
process(clk_50MHz)
VARIABLEtime_flag:
integerRANGE0TO500000;--100HZ
VARIABLEtime_flag1:
integerRANGE0TO50000000;--1HZ
VARIABLEtime_flag2:
integerRANGE0TO25000;--2KHZ
VARIABLEtime_flag3:
integerRANGE0TO12500000;--4HZ
VARIABLEtime_flag4:
integerRANGE0TO5000000;--10HZ
begin
if(rising_edge(clk_50MHz))then
time_flag:
=time_flag+1;
time_flag1:
=time_flag1+1;
time_flag2:
=time_flag2+1;
time_flag3:
=time_flag3+1;
time_flag4:
=time_flag4+1;
iftime_flag=250000THEN
clk_100Hz<='1';
elsiftime_flag=500000THEN
clk_100Hz<='0';
time_flag:
=0;
endif;
iftime_flag1=25000000THEN
clk_1Hz<='1';
elsiftime_flag1=50000000THEN
clk_1Hz<='0';
time_flag1:
=0;
endif;
iftime_flag2=12500THEN
clk_2KHz<='1';
elsiftime_flag2=25000THEN
clk_2KHz<='0';
time_flag2:
=0;
endif;
iftime_flag3=6250000THEN
clk_4Hz<="11111111";
clk_4Hz2<='1';
elsiftime_flag3=12500000THEN
clk_4Hz<="00000000";
clk_4Hz2<='0';
time_flag3:
=0;
endif;
iftime_flag4=1250000THEN
clk_xHz<='1';
elsiftime_flag4=3750000THEN
clk_xHz<='0';
elsiftime_flag4=5000000THEN
time_flag4:
=0;
endif;
endif;
endprocess;
endbehav;
2、响铃模块:
利用不同频率来产生音乐。
这里有两个基本的时钟信号输入,在此基础上进行倍频,产生相应的频率,再进行不同频率之间的排列,使其产生音乐。
代码如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityclk_SoundIS
port(clk_2KHz:
instd_logic;
clk_4Hz:
instd_logic;
alarm_switch:
inbit;
enable:
instd_logic;
zheng_ring:
instd_logic;
beep:
bufferstd_logic;
beep_in:
instd_logic;
ring:
outstd_logic;
light:
outstd_logic_vector(6downto0)
);
endclk_Sound;
architecturebehavofclk_Soundis
constantn:
integer:
=10;
constantm:
integer:
=40;--ring10s
typesongisarray(0tom-1)ofintegerrange0ton;
constantarr:
Song:
=(2,4,7,1,4,8,5,6,7,4,
8,5,6,2,3,2,4,3,6,6,
2,4,2,5,1,1,7,4,4,6,
4,8,5,4,2,2,7,4,2,2
);
signalRering:
std_logic:
='0';
signalRenable:
std_logic:
='0';
--signalTurnOff:
std_logic:
='0';
signaldirection:
bit:
='0';
begin
process(enable,clk_2KHz,Renable,beep_in,alarm_switch)
variabletmpbeep:
std_logic:
='1';
variabletmp:
integerrange0ton:
=0;
variableflag500ms:
integerrange0to800:
=0;
variablei:
integerrange0tom:
=0;
begin
if(beep_in='0')thenbeep<=beep_in;
elsif(rising_edge(clk_2KHz))then
if(zheng_ring='1')then
tmpbeep:
='0';
elsif(enable='0'andRenable='0')then
tmpbeep:
='1';
Rering<='0';
ring<='0';
elsif(alarm_switch='0')then
tmpbeep:
='1';
Rering<='0';
ring<='0';
elsif(Rering='0'orRenable='1')then
if(flag500ms=800)then
flag500ms:
=0;i:
=i+1;
if(i=m)thentmpbeep:
='1';Rering<='1';i:
=0;
endif;
if(enable='1'andi/=m)then
ring<='1';
elsering<='0';
endif;
elseflag500ms:
=flag500ms+1;
if(tmp=arr(i))thentmp:
=0;tmpbeep:
=nottmpbeep;
elsetmp:
=tmp+1;
endif;
endif;
endif;
beep<=tmpbeep;
endif;
endprocess;
process(clk_2KHz,alarm_switch)
variableflag30s:
integerrange0to20000:
=0;
begin
if(rising_edge(clk_2KHz))then
if(alarm_switch='0')thenRenable<='0';
elsif(Rering='1')then
if(flag30s=20000)thenRenable<='1';flag30s:
=20000;
elseflag30s:
=flag30s+1;Renable<='0';
endif;
elseRenable<='0';
endif;
endif;
endprocess;
process(clk_4Hz)
variablelight0:
std_logic_vector(6downto0):
="0000000";
begin
if(rising_edge(clk_4Hz))then
if((enable='1'orRenable='1')andzheng_ring='0')then
if(direction='0')then
if(light0="0000000")then
light0:
="1000000";
else
light0:
='0'&light0(6downto1);
endif;
iflight0="0000000"thendirection<=notdirection;
endif;
else
if(light0="0000000")then
light0:
="0000001";
else
light0:
=light0(5downto0)&'0';
endif;
iflight0="0000000"thendirection<=notdirection;
endif;
endif;
elselight0:
="0000000";
endif;
light<=light0;
endif;
endprocess;
endbehav;
3、数码管显示模块:
由于实验板上将4个8段数码管的端口连在一起,所以每一时刻4个数码管的显示数值应该是一样的,故不能分别显示不同时间。
然而,动态显示通过人眼的余晖效应,以很高的频率来扫描数码管,不断的依次轮流点亮数码管,使得看起来是4个数码管同时显示不同数字。
这主要是通过设置数码管的使能端,同时选择此数码管应该显示的数据,进行动态显示。
此外,我们对数码管显示时的小数点进行控制,使其在显示分和秒之间点亮而其他位不亮。
所以我们设置了一个标志位来对译码电路进行控制,使其点亮或熄灭小数点。
此模块主要将输入的4位向量转换成相应的在8端数码管上显示的向量,使其显示相应的数字。
而且,我们通过从动态显示模块接收到的标志位来控制译码的程序,使得相应的小数点亮或灭。
代码如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitydisplayIS
port(in1,in2,in3,in4:
instd_logic_vector(3downto0);
clk_2kHz:
instd_logic;
seven_seg_output:
outstd_logic_vector(7downto0);
en1,en2,en3,en4:
outstd_logic
);
enddisplay;
architecturebehavofdisplayis
begin
process(clk_2kHz)
variablei:
integerrange0to3:
=0;
variableout_buffer:
std_logic_vector(3downto0):
="0000";
begin
if(rising_edge(clk_2kHz))
then
caseiIS
when0=>
en1<='0';en2<='1';en3<='1';en4<='1';out_buffer:
=in1;i:
=1;
when1=>
en1<='1';en2<='0';en3<='1';en4<='1';out_buffer:
=in2;i:
=2;
when2=>
en1<='1';en2<='1';en3<='0';en4<='1';out_buffer:
=in3;i:
=3;
when3=>
en1<='1';en2<='1';en3<='1';en4<='0';out_buffer:
=in4;i:
=0;
endcase;
if(i=2)then
caseout_bufferis
when"0000"=>seven_seg_output<="00000010";
when"0001"=>seven_seg_output<="10011110";
when"0010"=>seven_seg_output<="00100100";
when"0011"=>seven_seg_output<="00001100";
when"0100"=>seven_seg_output<="10011000";
when"0101"=>seven_seg_output<="01001000";
when"0110"=>seven_seg_output<="01000000";
when"0111"=>seven_seg_output<="00011110";
when"1000"=>seven_seg_output<="00000000";
when"1001"=>seven_seg_output<="00001000";
when"1010"=>seven_seg_output<="10010000";
when"1011"=>seven_seg_output<="00010000";
when"1100"=>seven_seg_output<="11111101";
whenothers=>seven_seg_output<="11111111";
endcase;
else
caseout_bufferis
when"0000"=>seven_seg_output<="00000011";
when"0001"=>seven_seg_output<="10011111";
when"0010"=>seven_seg_output<="00100101";
when"0011"=>seven_seg_output<="00001101";
when"0100"=>seven_seg_output<="10011001";
when"0101"=>seven_seg_output<="01001001";
when"0110"=>seven_seg_output<="01000001";
when"0111"=>seven_seg_output<="00011111";
when"1000"=>seven_seg_output<="00000001";
when"1001"=>seven_seg_output<="00001001";
when"1010"=>seven_seg_output<="10010001";
when"1011"=>seven_seg_output<="00010001";
when"1100"=>seven_seg_output<="11111101";
whenothers=>seven_seg_output<="11111111";
endcase;
endif;
endif;
endprocess;
endbehav;
4、流水灯显示模块:
闹钟响的时候显示。
代码如下:
libraryieee;
useieee.std_logic_1164.all;
entitydisplay_led8is
port(
input_time:
instd_logic_vector(3downto0);
--alarm_switch:
inbit;
--clk_led:
outstd_logic;
seven_seg_output:
outstd_logic_vector(7downto0)
);
enddisplay_led8;
architecturedecode_archofdisplay_led8is
begin
process(input_time)
begin
caseinput_timeis
when"0000"=>seven_seg_output<="00000011";
when"0001"=>seven_seg_output<="10011111";
when"0010"=>seven_seg_output<="00100101";
when"0011"=>seven_seg_output<="00001101";
when"0100"=>seven_seg_output<="10011001";
when"0101"=>seven_seg_output<="01001001";
when"0110"=>seven_seg_output<="01000001";
when"0111"=>seven_seg_output<="00011111";
when"1000"=>seven_seg_output<="00000001";
when"1001"=>seven_seg_output<="00001001";
whenothers=>seven_seg_output<="11111111";
endcase;
--if(alarm_switch='1')thenclk_led<='1';
--elseclk_led<='0';
--endif;
endprocess;
enddecode_arch;
5、主控模块:
此模块用来控制时钟当前工作状态,并对各种工作状态下的操作指令进行接受和处理。
(1)输入信号有:
Clk:
时钟信号;
setsnd:
闹铃开关信号;
setsnd=’1’时,闹铃开;
setsnd=’0’时,闹铃关。
sum:
切换按键1的按下数;
sum=1时,时钟工作在时间显示状态;
sum=2时,时钟工作在时间的时调整状态;
sum=3时,时钟工作在时间的分调整状态;
sum=4时,时钟工作在闹铃的时设定状态;
sum=5时,时钟工作在闹铃的分设定状态;
sum=6时,时钟工作在秒表状态。
Sum1:
启动停止按键2的按下数;
sum=1表示启动,时间开始变化;
sum=2表示停止,时间调整或设定完毕。
Sum2:
确认键3的按下数:
Sum2=1,表示操作完毕,使sum=1,时钟回到时间显示状态,并使sum1=0.
Hour:
时;
Min:
分;
Sec:
秒。
(2)输出信号:
Rst:
复位信号,用来消除秒表的记录,使其变为0;
Showchu:
显示选择信号,用来切换秒表状态和其他状态的显示;
Begincnt:
秒表启动信号;
Load:
时间重置信号,用于将显示时间改变到经调整设置得到的新时间;
Clear:
按键记录清除信号;
Sound:
闹铃信号,达到设定的闹铃时间时,该信号是蜂鸣器鸣叫;
Output1:
经处理后的‘时’;
Output2:
经处理后的‘分’;
Output3:
经处理后的‘秒’;
key3_reset:
复位信号
key2_change:
确定按键
key1_state:
状态按键
clk_100Hz、clk_1Hz、clk_xHz、clk_4Hz、clk_2kHz:
不同频率信号的输入。
alarm_switch:
闹钟的开关
song_switch:
音乐开关
enclock:
闹钟信号
ring:
zheng_ring:
outstd_logic;
beep:
蜂鸣器输出信号
--count:
计数信号
out1,out2,out3,out4:
数码管显示信号输出
代码如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 FPGA 数字 电子 时钟 设计 VHDL