桂林电子科技大学职业技术学院
FPGA应用实训报告
数字钟
学院(系): 电子信息工程系
专 业: 电子信息工程技术
学 号: xxxxxxxxxx
学生姓名: xxxxxx
指导教师: xxxxxx
目 录
摘要………………………………………………………………………………1
引言………………………………………………………………………………2
一、设计任务与要求……………………………………………………………3
二、总体设计方案………………………………………………………………3
三、程序设计方案………………………………………………………………3
(1)分频模块实现方案1…………………………………………………3
(2)分频模块实现方案2…………………………………………………4
(3)计时模块实现方案 1…………………………………………………4
(4) 计时模块实现方案 2…………………………………………………4
(5)方案总结………………………………………………………………5
四、系统软件原理………………………………………………………………5
(1)主程序入口即变量定义………………………………………………5
(2)计时模块………………………………………………………………6
五、系统硬件原理………………………………………………………………6
心得体会…………………………………………………………………………8
致谢………………………………………………………………………………9
参考文献…………………………………………………………………………10
附录………………………………………………………………………………11
摘 要
数字钟是人们日常生活中经常使用的计时工具,本次的课程设计是基于Verilog HDL的多功能数字钟,完成时、分、秒的显示功能。设计利用Verilog HDL语言自顶向下的设计理念,突出其作为硬件描述语言的良好的可读性、可移植性以及易于理解等优点。程序下载到FPGA芯片后,可用于实际的数字钟显示中。
此次设计的逻辑结构主要由分频器、计数器和译码显示器三个模块构成。分频模块将50Mhz系统基准时钟分频产生两路时钟信号,一路是1HZ的数字钟计时工作频率,一路是数码管动态显示的扫描频率;计时模块对1HZ的时钟信号进行计时,分为时、分、秒三个部分;与机械式时钟相比具有更高的准确性和直观性,且无机械装置,具有更长的使用寿命,已得到广泛的使用。数字钟的设计方法有许多种,例如,可用中小规模集成电路组成电子钟;也可以利用专用的电子钟芯片配以显示电路及其所需要的外围电路组成电子钟;钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。译码显示模块采用动态扫描的方式完成数码管的显示。最后通过主模块调用三个子模块函数完成整个设计。
【关键词】硬件描述语言 FPGA 数字钟
引 言
现代电子设计技术进入了一个新的阶段。传统的电子设计方法、工具和器件在更大程度上被EDA所取代。EDA技术就是以计算机为工具,设计者在EDA软件平台上,用硬件描述语言HDL完成设计文件,然后由计算机自动地完成逻辑编译、化简、分割、综合、优化、布局、布线和模拟,直至对于特定目标芯片的适配编译、逻辑映像和程序设计下载等工作。EDA技术的出现,极大地提高了电路设计的效率和可操作性,减轻了设计者的劳动强度。Verilog HDL是EDA技术的重要组成部分,Verilog HDL具有极强的描述能力,能支持系统行为级、寄存器传输级、逻辑门级三个不同层次的设计,支持结构、数据流、行为三种描述形式的混合描述。ASIC是专用的系统集成电路而FPGA是特殊的ASIC芯片具有设计开发周期短、设计制造成本低、开发工具先进等优点。
一、设计任务与要求
(1)设计一个数码管实时显示时、分、秒的数字时钟(24小时显示模式)
(2)为了演示方便,应具有分钟、小时快进功能。
(3)到点报时、闹钟时间固定为8:00
(4)同时设置按键调时。
二、总体设计方案
(1)方案一 用数电制作一个数字钟,通过74L74芯片实现数码管计数功能
用与非门结合,用按键来设置实现闹钟和整点报时的功能。
(2)方案二 用fpga来制作一个数字钟,通过编写程序来控制fpga芯片输
出输入来得到数字钟的功能,同时用fpga板来实现该功能。
(3)方案三 用单片机来控制数字钟,通过编写程序来实现时钟计时功能,
通过单片机试验箱来实现该功能,最终达到相应的结果。
总结:
方案一用数电的方式做数字钟,用的芯片多同时之制作麻烦,不适合制做数字钟。方案二制作比较便捷,只需要写程序,制作业是比较方便,也比较实现功能。方案三用单片机虽然也是编写程序,可是和FPGA相比我个人觉得还是比单片机好做一点。综合上述我选择FPGA来制作该程序
三、程序设计方案
(1)分频模块实现方案1
定义变量并且设定一个上限值,每次加计数到该上限值时,输出该计数值的最高位
parameter DIV_SIZE=25;
always@(posedge clock)
counter=counter+1;
assign clkdiv=counter[DIV_SIZE-1];(2)分频模块实现方案2
定义一个变量,使得counter_1hz==20000000,使得输入1hz信号,让counter_1hz自加
always@(posedge clk)
Begin if(counter_1hz==20000000)
begin counter_1hz=0;clk_1hz<=~clk_1hz;end
else counter_1hz=counter_1hz+1;
if(counter>=20000)
begin counter<=0;clk_1khz<=~clk_1khz;end
else begin counter<=counter+1;
end
(3)计时模块实现方案 1
计时分每个信号的高低位进行判断及计时
if(sL==9) begin sL<=0;if(sH==5) begin sH<=0; if(mL==9)begin mL<=0; if(mH==5) begin mH<=0; if(hL==9)
begin hL<=0;hH<=hH+1;end
else if(hL==3&&hH==2)
begin hL<=0;hH<=0; end else hL<=hL+1;end else mH<=mH+1;
end
else mL<=mL+1;
end
else sH<=sH+1;
end
else sL<=sL+1;
end
(4)、计时模块实现方案 2
用信号来判断
if(b==1000)
begin b=0; second_l=second_l+1;
if(second_l==10)begin second_l=0;second_h=second_h+1;end
if(second_h==6)begin second_h=0;miniute_l=miniute_l+1;end
if(miniute_l==10)begin miniute_l=0;miniute_h=miniute_h+1;end
if(miniute_h==6)begin miniute_h=0;hour_l=hour_l+1;end
if(((hour_l==4)&&(hour_h==2))||((hour_l==10)&&(hour_h<=1)))
begin hour_l=0;hour_h=hour_h+1;end
if(hour_h==3)hour_h=0;end else b=b+1;
end
(5)方案总结:采用方案2来实现设计。方案2在思路方面较为通俗易懂,且判断过程简短明了,在最终的显示时出现毛刺干扰现象,其他方案中不便于增加小时和分钟的调节信号,方案最终失败。方案2比较判断复杂,在最终的数码管显示时可能不怎么稳定。方案2我们上课时学的也是这个方案用起来也比较熟悉。综合考虑,使用方案2。
四、系统软件原理
1软件部分有分频模块,按键防抖动,时钟主体,闹铃模块,动态扫描模块等来实现此方案。软件原理框图3-1

图3-1
使用此方案首先进行分频得到一个信号,使得信号稳定。进而促使始终主体工作。再通过按键防抖来控制调时和闹钟模块最后用动态扫描来实现软件的所有功能。
1)主程序入口即变量定义
该程序共有两个输入:Clk为1024Hz主时钟信号输入,Key为清零按键和调节始终按键,高电平有效。Display_tab为数码管显示驱动输出,状态机用于循环扫描点亮数码管,扫描频率1024Hz,Spk将报时音讯输出至扬声器。
2)计时模块
second_l,second_h;miniute_l,miniute_h;hour_l,hour_h;分别表示秒,分,小时的高位和低位L组成十六进制计数器。程序利用1Hz时钟作为输入,首先判断是否有清零信号Key(高电平清零),然后系统判断当前状态是否为23:59:59,而后判断分钟与秒为59:59时小时个位是否为9,此后以此类推。
五、系统硬件原理
Verilog HDL的多功能数字钟的设计方案是设计一个具有计时、报时和显示这三部分的主要功能。系统原理框图如图4-1所示。其中计时功能是整个多功能数字钟的核心部分;报时——顾名思
义,也就是在时钟到达整点时的鸣叫功能;显示起到了一个译码功能,使得程序在实验箱上下载时我们能清晰、明了的整个运行过程。这三部分相结合,就基本完成了这样的一个多功能数字钟。

图4-1 数字钟原理框图
原理框图功能如下:
①首先输入电源然后进入FPGA芯片,来实现最基本的数字钟计时电路,其计数输出送7段译码电路,由数码管显示。
②PPGA芯片工作使得基准频率分频器可分频出标准的1hz 频率信号,用于秒计数的时钟信号;分频出频率信号用于校时、校分的快速递增信号;分频出 频率信号用于对于按动校时、校分按键的消除抖动。
③然后用按键控制电路模块是一个校时、校分、秒清零的模式控制模块, 频率信号用于键的消除抖动。而模块的输出则是一个边沿整齐的输出信号。
④控制电路模块是一个校时、校分、秒清零的模式控制模块,64Hz 频率信号用于键KEY1、KEY2、KEY3的消除抖动。而模块的输出则是一个边沿整齐的输出信号。
⑤报时电路模块需要通过一个组合电路完成,前五声讯响功能报时电路还需用一个触发器来保证整点报时时间为1 秒。
⑥闹时电路模块也需要音频信号以及来自秒计数器、分计数器和时计数器的输出信号作本电路的输入信号。
心得体会
这次的课程设计结束了,在这次的设计中我学会了很多东西。首先是对Verilog HDL语言的设计思想有了深入理解,将这种自顶向下的设计理念运用于实践中,设计多功能数字钟,突出了Verilog HDL作为硬件描述语言的良好可读性和可移植性,对上学期所学的而理论知识有了深刻的理解。
其次是对Verilog HDL语言的语法熟悉,在这次的课程设计中,我学习到很多Verilog HDL语言的语法知识,比如在两个不同的语句块中不能对同一个变量进行操作,比如在用Verilog HDL语言中编写程序时要注意begin和end语句的匹配问题,在使用Verilog HDL语言时不可以使用中文注释等等。对于这种语言的学习也有了很大的帮助。
最后是设计作品时的设计逻辑和设计思想,在选择不同的系统方案时要综合考虑,选择最优方案。各个模块的实现也要考虑综合情况而制定出最符合实际情况的实现方案,方案间要进行对比、实践,最终确定。
在这次的课程设计中我不仅学习到有关程序编写以及设计方面的逻辑思维,对系统功能的实现也有了较为深入的了解,对各模块的调试等也学习到不少东西,总之,从这次设计中学到很多东西,也巩固了我的理论学习。
致谢
首先要感谢我的老师xxx,老师知识渊博,治学认真而严谨,感谢您从本文研究开始一路指导至本论文的完成,从论文题目的选定到论文写作的指导,经由您悉心的点拨,再经思考后的领悟,常常让我有“山重水复疑无路,柳暗花明又一村”的豁然开朗!由衷感谢您在论文上倾注的大量心血,您宽厚待人的学者风范令我无比感动。 感谢授课老师课上对我们的教导,你们丰富的授课内容拓宽了我的视野,让我能更顺利的完成这篇文章;感谢我的同学们,你们不仅让我感受到友情的力量,也让我感觉到了生活的愉悦,通过课堂讨论学到的思维方式使我受益终生。
最后,我要向我的家人表示深深的谢意。你们的理解、支持、鼓励和鞭策催我更加上进,我竭尽全力的努力,更希望的是能够让你们高兴和满意。你们的情感永远都是我上进的不竭的动力源泉。 这些时光会慢慢的沉淀下来,但无论何时,我想到这段岁月,都如同是看到一枚珍藏已久的夹在书里发黄的书签,永远都是那么璀璨、那么绚烂。
参考文献
【1】夏宇闻. Verilog 数字系统设计教程[第二版].北京航空航天大学出版社,【2】康华光等. 电子技术基础(数字部分)[第五版]高等教育出版社,
【3】罗朝霞等. CPLD/FPGA设计及应用. 北京人民邮电出版社,
【4】亿特科技编著. CPLD/FPGA应用系统设计与产品开发. 北京人民邮电出版 社。
【5】付文红.花汉兵着.EDA技术与实验. 机械工业出版社
【6】崔建明.电工电子EDA仿真技术。 北京高等教育出版社
【7】侯伯亨.Verilog HDL硬件描述语言与数字逻辑电路设计.西安电子科技大学出版
附录
module b(clk,led_out,seg_bit,led_test,alarm_clock,led,
key,key_1,key_2,key_3,key_4);
input clk;
input key,key_1,key_2,key_3,key_4;
reg clk_1hz;
reg clk_1khz;
output reg led_test;
output reg led;
output reg[3:0]seg_bit;
output reg[6:0]led_out;
output reg alarm_clock;
reg[20:0]counter;
reg[30:0]counter_1hz;
reg[7:0]display_tab;
reg[7:0]second_l,second_h;
reg[7:0]miniute_l,miniute_h;
reg[3:0]hour_l,hour_h;
reg[1:0]state;
parameter s0=2'd0,s1=2'd1,s2=2'd2,s3=2'd3;
//定时8:00
parameter timing_miniute_h=0,timing_miniute_l=0,
timing_second_h=0,timing_second_l=0,timing_hour_h=0,timing_hour_l=8;
integer a,b,c,d,e;
integer latch_second_l,latch_second_h,latch_miniute_l,latch_miniute_h,latch_hour_l,latch_hour_h;
initial begin state=0;counter=0;counter_1hz=0;miniute_l=9;miniute_h=5;
second_h=5;second_l=5;hour_h=0;hour_l=7;end //初始化寄存器
//分频模块
always@(posedge clk)
begin
if(counter_1hz==20000000)
begin counter_1hz=0;clk_1hz<=~clk_1hz;end
else counter_1hz=counter_1hz+1;
if(counter>=20000)
begin
counter<=0;clk_1khz<=~clk_1khz;end
else begin counter<=counter+1;end
case(display_tab)
0:led_out=7'b100_0000;
1:led_out=7'b111_1001;
2:led_out=7'b010_0100;
3:led_out=7'b011_0000;
4:led_out=7'b001_1001;
5:led_out=7'b001_0010;
6:led_out=7'b000_0010;
7:led_out=7'b111_1000;
8:led_out=7'b000_0000;
9:led_out=7'b001_0000;
default:led_out=7'bz;
endcase
end
//按键防抖动
always@(posedge clk_1khz)
begin
if(!key_1)a=a+1;if((a==200)&&(!key_1))begin a=0;miniute_h=miniute_h+1;if(miniute_h==6)miniute_h=0;end
if(!key_2)a=a+1;if((a==200)&&(!key_2)) begin a=0;miniute_l=miniute_l+1;if(miniute_l==10)miniute_l=0;end
if(!key_3)a=a+1;if((a==200)&&(!key_3)) begin a=0;hour_l=hour_l+1;
if(((hour_l==4)&&(hour_h==2))||((hour_l==10)&&(hour_h<=1)))hour_l=0;
end
if(!key_4)a=a+1;if((a==200)&&(!key_4)) begin a=0;hour_h=hour_h+1;if(hour_h==3)begin hour_h=0;hour_l=0;end
if(hour_h==2)hour_l=3;
end
//时钟主体
if(b==1000)
begin
b=0;
second_l=second_l+1;
if(second_l==10)begin second_l=0;second_h=second_h+1;end
if(second_h==6)begin second_h=0;miniute_l=miniute_l+1;end
if(miniute_l==10)begin miniute_l=0;miniute_h=miniute_h+1;end
if(miniute_h==6)begin miniute_h=0;hour_l=hour_l+1;end
if(((hour_l==4)&&(hour_h==2))||((hour_l==10)&&(hour_h<=1)))begin hour_l=0;hour_h=hour_h+1;end
if(hour_h==3)hour_h=0;
end
else b=b+1;
end
//闹铃模块
always@(posedge clk_1khz)
begin
if((miniute_h==timing_miniute_h)&&(miniute_l==timing_miniute_l)&&
(hour_h==timing_hour_h)&&(hour_l==timing_hour_l)&&
(second_h==timing_second_h)&&(second_l==timing_second_l))
begin latch_hour_l=hour_l;latch_hour_h=hour_h;
latch_miniute_l=miniute_l;latch_miniute_h=miniute_h;end
if(c==1000) begin c=0;
if((latch_miniute_h==timing_miniute_h)&&(latch_miniute_l==timing_miniute_l)&&
(latch_hour_h==timing_hour_h)&&(latch_hour_l==timing_hour_l))
alarm_clock=~alarm_clock;end
else c=c+1;
if(e==1000) begin e=0; if((miniute_l||miniute_h)==0)led=~led;
if((miniute_l||miniute_h)==1)led=0;end
else e=e+1;
if(!key)d=d+1;if((d==200)&&(!key))begin d=0; latch_miniute_l=latch_miniute_l+1;alarm_clock=0;end
end
//动态扫描模块
always@(posedge clk_1khz)
begin
case(state)
s0:begin seg_bit=4'b0111;
display_tab=miniute_l;
state=s1;led_test=1;end
s1:begin seg_bit=4'b1011;
display_tab=miniute_h;
state=s2;led_test=1;end
s2:begin seg_bit=4'b1101;
display_tab=hour_l;
state=s3;led_test=~clk_1hz;end
s3:begin seg_bit=4'b1110;
display_tab=hour_h;
state=s0;led_test=1;end
default:begin led_out=7'bz;state=0;end
endcase
end
endmodule