数字钟verilogWord文档格式.docx
《数字钟verilogWord文档格式.docx》由会员分享,可在线阅读,更多相关《数字钟verilogWord文档格式.docx(23页珍藏版)》请在冰豆网上搜索。
从仿真图中可以看到,在rst为高电平时分频过程开始,f500HZ、f200HZ和f1HZ也与预期的输出结果一样。
3.3秒表模块
秒表模块实现秒表功能,在实现的过程中,通过改变自动工作模式下的时钟频率来实现秒表的功能。
即按动start键闹钟开始工作,再次按动start键,闹钟便停止工作。
由于秒表模块比较简单,流程图在此省略。
根据分析,在verilogHDL实现过程中,clk作为时钟正常工作时候的频率,f500hz为秒表工作时候的频率,仿真结果如下图7所示。
图7秒表仿真模块
由图中可以看出,根据start高低电平的变化,时钟在正常工作与秒表之间相互转换。
3.4闹钟模块
闹钟模块实现的是闹钟的设置及闹钟所设定的时间到之后的响铃提示。
闹钟模块的设置主要思想是由控制键来设置数字钟的闹钟响的时间,经过与当前数字钟实时时间的比较,来决定闹钟提醒的时间。
设计框图如下图8所示。
图8闹钟模块设计框图
在verilogHDL实现的过程中,由SW1、SW2两个调整键来实现,其中SW1为移位控制键,即按SW1一次,将移位一次,闪烁显示当前设置为数字,SW2为当前位的闹钟数字设置,每按SW2一次,当前数字设置位数字增加1,每一位上数字变化范围由当前位循环上限决定,不会超出范围。
EN为设置使能端,为1有效。
Hour1、hour0、minute1和minute0分别为当前时间每个位上显示的数字,hour_set1、hour_set0、minute_set1和minute_set0为与当前时间所对应的每一位上设置的时间显示,f200hz为闹钟设置过程中显示闪烁的频率。
Con_alarm为闹钟响铃的控制键,其值为1时,表示闹钟已设置,并且在闹钟响的时候,如果设置其值为0,则闹钟关闭。
Alarm为闹钟响铃提示输出,即设定时间到时alarm值为1,否则为0。
Alarmclock_disp_select为闹钟设置中位选信号,为4位reg型变量,其值采用独热编码,为1000、0100、0010和0001分别表示设置过程中hour1、hour0、minute1和minute0四个位。
其仿真结果如下图9所示。
图9闹钟模块仿真示意图
由于设置波形输入的时候如果调整过多,将不容易看出仿真结果的正确与否,所以图中输入比较简单,以便可以更好地分析仿真结果。
由图中可以看出,经过SW1的两次调整,位选信号alarmclock_disp_select的值为0010,表示此时的设置位为hour_set0位,SW2键将其值设置为0001,其他位均为0000,然后在与当前时钟时间相等的情况下,并且在con_alarm值为1的时候闹钟响,即alarm值输出为1,在当前时间与闹钟时间仍然相等的情况下,将闹钟控制键con_alarm值设置为0,闹钟停止,即alarm值为0。
很好的完成了闹钟的功能。
3.5时间设置模块
时间设置模块实现的功能为通过按键调节可以对当前时间进行手动控制。
其主要是在时间设置使能端有效地情况下通过SW1和SW2两个按键对数字钟的小时和分钟数进行调节。
Disp_drive为设置中的显示控制,即通过SW1对位的调整,Disp_drive随之变化。
SW2为对每一位上的数字在其范围内进行加1调节,其调节过程与闹钟模块相同。
Disp_drive取值000、001、010和011分别对应hour1、hour0、minute1和minute0的设置。
Quartus下仿真结果如图10所示。
图10时间设置模块仿真效果
图中,hour_set0、hour_set1、minute_set0和minute_set1为设置后的时间。
可以看到,当前给的hour0为0010,hour1的值0001,在SW1经过一次高电平之后,disp_drive的值变为001,对hour0进行设置,加1之后hour_set0变为0001,SW1再按一下,变为0010,在SW2两次高电平之后,SW1的值变为1,此时对分的高位进行加1设置,依此类推。
3.6报时模块
整点报时模块的主要功能为仿中央人民广播电台整点报时信号,即从59分50秒起每隔2秒发出一次低音“嘟”信号,将其定义为500HZ的低频信号,到达整点(00分00秒时),发一次高音“哒”信号,其响声为高频1kHZ信号。
由于整点报时程序比较简单,所以框图省略。
为了程序简化又与其他模块有较好的兼容性,用minute、second分别表示minute1、minute0和second1,second0经过位拼接之后的分和秒的当前显示时间。
F1khz为到达整点之后的高音频率,f500hz为59分50秒、52秒、54秒、56秒和58秒时的低音频率,radio则为到达时间时的报时输出。
仿真图如下图11所示。
图11整点报时模块仿真效果图
从图中可以看出,从59分50秒开始,输出的radio开始以f500hz的频率报时,当到达00分00秒时,输出信号频率为f1khz,到达00分01秒的时候之后便变为0,符合设计要求。
3.7控制显示模块
控制显示模块在整个数字钟的设计中起着非常重要的作用。
它的作用是将时间等数据用数码管显示的控制和数据传输模块,包括数据的传输以及BCD码译码等。
通过几个控制使能端将其不同功能时的时间在数码管上显示出来。
本模块中端口定义比较多,下面是其所对应的功能。
Time_EN:
时间自动模式工作使能信号;
Timeset_EN:
时间设置使能信号;
Stopwatch_EN:
秒表使能信号;
Alarmclock_EN:
闹钟设置使能信号;
Radio_EN:
整点报时使能信号;
Time_disp_select:
时间显示位选信号;
Alarmclock_disp_select:
闹钟设置的显示位选信号;
Disp_select:
显示位选信号输出;
Disp_data:
经过译码之后显示的数据。
程序设计中,各使能端信号为1表示执行该功能,以时间自动工作模式使能信号有效为例说明,当Time_EN为1时,首先将时间显示位选信号isp_select的值赋给显示位选信号disp_select输出,定义time_disp_select的状态一共有6个,分别为100000、010000、001000、000100、000010和000001,其在各状态下分别依次表示将hour0、hour1、minute0、minute1、second0和second1的值赋给data,用case语句来实现,其实现语句如下:
if((Time_EN==1'
b1)
begin
disp_select<
=time_disp_select;
case(time_disp_select)
6'
b100000:
Data<
=hour1;
b010000:
=hour0;
b001000:
=minute1;
b000100:
=minute0;
b000010:
=second1;
b000001:
=second0;
default:
=4'
b0;
endcase
在quartusⅡ下仿真图12如下:
图12控制显示模块当前时间使能端有效时译码的显示
从图中可以看出,在第一个时钟周期内,时间显示位选信号time_disp_select的值为000000,此时应执行case语句的default,Data的值为0;
在第二个时钟周期内,time_disp_select的值为000001,此时对应其最后一种状态,将second0的值赋给Data,即Data的值为0110,从图中看,仿真结果正确,disp_data表示的是将当前数据译码显示之后七段数码管的显示,所以在第一个周期内值为1111110,表示值为0,与Data所表示的数对应。
依次类推,可将Data的值全部表示出来。
显示译码数据段主要程序如下:
case(Data)
4'
b0000:
disp_data<
=7'
b1111110;
b0001:
b0110000;
b0010:
b1101101;
b0011:
b1111001;
b0100:
b0110011;
b0101:
b1011011;
b0110:
b1011111;
b0111:
b1110000;
b1000:
b1111111;
b1001:
b1111011;
显示译码程序说明了0到9十个数在7段数码管中所对应的值,在case语句里面最重要的是一定不能忘了default,否则仿真会发生所不希望看到的
结果。
下图13为闹钟设置使能有效时仿真结果。
图13控制显示模块当闹钟设置使能信号有效时译码显示
从图中可以看出,当只有闹钟使能信号alarmclock_EN有效时,其七段数码管显示结果,与数字钟自动工作使能端的区别为闹钟设置使能端有效时只需对hour0、hour1、minute0和minute1进行设置,所以闹钟设置显示位选信号alarmclock_disp_select的状态只有4个,由于其同样需要将值赋给disp_select,为了统一期间,其值也设为6位,其4个状态分别为100000、010000、001000和000100。
其他与自动工作模式相同。
3.8顶层模块
将以上设计的各个模块组合起来,就可以得到多功能数字钟的整体仿真结果。
其主要作用是将各个模块衔接起来,图14为时钟正常工作模式下Quartus仿真结果。
图14整体仿真结果
4总结
4.1本次作业遇到的问题
在做本次作业中,遇到的问题主要有以下几个方面:
(1)软件的安装与学习。
在软件的安装过程中,首先通过自己从网上下载软件安装,第一次安装的时候未经破解,导致安装的软件虽然装上了,但是打不开,无法使用。
软件的学习过程中,首先经过上课讲解,自己从网上下视频的学习,运行了几个书上的小程序,对软件进行了熟悉。
(2)由于VerilogHDL这门语言对自己来说属于一个从未接触过的东西,所以学习起来比较困难。
本次作业选择的题目为多功能数字钟,前面是资料的搜集与设计思路的理清,再有了一定的基础之后,开始对整个大的模块进行分模块分析设计。
(3)在作业的过程中,遇到了许多的问题,首先发现自己对软件的运用上存在的一些问题,如刚开始的时候没有生成功能网表,导致最后运行出错;
还有没有选功能仿真的时候,波形出现了一些毛刺和延时。
(4)以为自己上课听懂了阻塞与非阻塞赋值的区别,结果的程序的书写上还是出现的问题,比如在秒表模块中,用的电平触发,刚开始的时候时候用的阻塞赋值,发现仿真波形有延时,以为是阻塞赋值的问题,将阻塞赋值改为了非阻塞赋值,延时问题还是没有解决,才发现进行的是时序仿真。
这是由于自己当时还是没有深刻的理解两者之间的区别,才造成的误解,给解决问题带来了一定的困扰。
(5)仿真过程中不够细心,比如在整点报时模块,波形输入的时候,将minute与second的值设置反了,造成找了一下午的问题,radio就是不报时,后来发现问题的时候,觉着特别不可思议,还把程序改了半天。
(6)在控制显示模块,波形文件仿真的过程中,由于其输入输出接口比较多,为了看得更清楚期间,在数字钟正常工作模式下显示的过程中,将闹钟设置使能端去掉了,结果在仿真的过程中data跟disp_data就是没有值,后来发现原因是在将闹钟使能端去掉之后,不确定闹钟使能端是否有效。
造成没有显示结果,后来把闹钟使能段加上之后并将其置为0,仿真结果正确。
作业过程中,遇到的小问题不计其数,在多方努力之下,问题基本解决,这里就不一一列举。
总结出的宝贵经验就是要多看书,学会自己解决问题,一般的问题在看书找资料之后基本都能解决;
还有就是一定要细心,这样可以避免很多不必要的麻烦。
4.2建议和总结
首先非常感谢老师在每周末还那么辛苦的给我们上课,真的使我学到了很多的东西,在此对老师致以深深的谢意!
对老师的建议就是可以在刚开始上课的时候就可以给同学布置一些小的作业,然后可以让同学慢慢接触一下软件,学一点浅显的编程,这样在最后写大作业的时候就不会感觉无从下手,以便起到一个循序渐进的作用。
附件
1.小时计数器模块
modulehour_counter(EN,clk,hour_data1,hour_data0,zox);
inputclk,EN;
//时钟与使能端
output[3:
0]hour_data1,hour_data0;
//小时的高位和低位
outputzox;
//上下午指示模块
reg[3:
regzox;
always@(posedgeclk)
begin
if(EN==1'
begin
if(hour_data0<
b0011)
hour_data0<
=hour_data0+4'
b1;
else
begin
zox<
=1'
if(hour_data1<
b0001)
hour_data1<
=hour_data1+4'
else
begin
hour_data1<
zox<
end
end
end
end
endmodule
2.分秒计数器模块
moduleminute_counter(EN,clk,minute_data1,minute_data0,EO);
0]minute_data1,minute_data0;
分高位、低位
outputEO;
//进位输出端
regEO;
always@(posedgeclk)//上升沿触发
b1)//使能端为1有效
if(minute_data0<
b1001)
minute_data0<
=minute_data0+4'
EO<
if(minute_data1<
b0101)
minute_data1<
=minute_data1+4'
minute_data1<
EO<
3.分频模块
modulefdiv(clk,rst,f500hz,f200hz,f1hz);
inputclk,rst;
//1KHz输入
outputf500hz,f200hz,f1hz;
//分频出500HZ、200HZ、1HZ输出
regf500hz,f200hz,f1hz;
integerCNT1=0,CNT2=0;
//两个常数变量,分频技术用
always@(posedgeclk)//2分频
if(!
rst)f500hz=0;
elsef500hz=~f500hz;
always@(posedgeclk)//5分频
if(!
rst)
f200hz<
=0;
CNT2<
end
else
if(CNT2==4)
CNT2<
=0;
f200hz<
=~f200hz;
elseCNT2<
=CNT2+1;
end
always@(posedgef200hz)//将200HZ信号200分频为1HZ
if(!
f1hz<
CNT1<
if(CNT1==199)
CNT1<
f1hz<
=~f1hz;
elseCNT1<
=CNT1+1;
end
4.秒表模块
modulestopwatch(clk,f500hz,start,F_out);
inputclk,f500hz,start;
//start为控制秒表信号
outputF_out;
//输出,秒表工作方式
regF_out;
always@(startorclkorf500hz)
case(start)
1'
b0:
F_out=clk;
1'
b1:
F_out=f500hz;
default:
F_out=1'
endcase
5.闹钟模块
modulealarmclock(clk_200hz,EN,SW1,SW2,
hour1,hour0,hour_set1,hour_set0,minute1,minute0,minute_set1,minute_set0,alarm,control_alarm,alarmclock_disp_select);
inputEN,SW1,SW2,clk_200hz;
//SW1、SW2为闹钟设置键
input[3:
0]hour1,hour0,minute1,minute0;
//显示当前时间
inputcontrol_alarm;
//闹钟控制键
outputalarm;
//闹钟响铃输出
0]alarmclock_disp_select;
//闹钟设置位选信号
0]hour_set1,hour_set0,minute_set1,minute_set0;
reg[3:
regalarm;
0]hour_set1,hour_set0;
//存放设置的小时
0]minute_set1,minute_set0;
//存放设置的分
reg[2:
0]disp_drive;
//设置闹钟时间时,数码管显示的动态位选择
//闹钟一直工作(设置的闹钟时间与当前时间比较)
always
if((hour_set1==hour1)&
&
(hour_set0==hour0)&
(minute_set1
==minute1)&
(minute_set0==minute0)&
(control_alarm==1))
alarm<
//相等,闹钟响
elseif(control_alarm==0)
//不相等,输出1
//闹钟设置中,按SW1一次,将移位一次,显示当前设置位
always@(posedgeSW1)
if(EN==1'
if(disp_drive!
=3'
b101)
disp_drive<
=disp_drive+3'
disp_drive<
b000;
//当前位的闹钟数字设置,按SW2一次,数字增加1
always@(posedgeSW2)
case(disp_drive)
3'
b000:
begin//000时,设置小时的高位
if(hour_set1<
b0010)
hour_set1<
=hour_set1+4'
3'