电子线路设计课程设计实验报告-多功能数字钟设计.doc
华中科技大学电子线路设计实验报告多功能数字钟设计姓名 学号 班级 一、实验目标:1、掌握可编程逻辑器件的应用开发技术设计输入、编译、仿真和器件编程;2、熟悉EDA软件使用;3、掌握Verilog HDL设计方法; 4、分模块、分层次数字系统设计二、实验任务及要求1、基本功能¨ 准确计时,以数字形式(十二进制)显示时、分、秒的时间¨ 校正时间:时、分 快校与慢校(1Hz与手动)¨ 复位:00:00:00¨ 仿广播电台正点报时 (四高一低) 2、扩展功能: (1)任意闹钟;(2)小时为12/24进制可切换(3)报正点数(几点响几声)三、实验条件:DE0 实验板结构与使用方法 quartus软件的使用 FPGA的使用四、电路设计过程:1、需求分析开发背景:数字钟是采用数字电路实现对.时,分,秒.数字显示的计时装置,广泛用于个人家庭,车站, 码头办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表, 钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,所有这些,都是以钟表数字化为基础的。因此,研究数字钟及扩大其应用,有着非常现实的意义。2、 实验原理:用层次化设计的方法以Verilog语言编程实现以下功能:(1)、具有“时”、“分”、“秒”计时功能;时为24进制,分和秒都为60进制。(2)、具有校时和清零功能,能够用4Hz脉冲对“小时”和“分”进行调整,并可进行秒清零;实际电路中使用快校时。(3)、具有整点报时功能。在59分51秒、53秒、55秒、57秒发出低音512Hz信号,在59分59秒发出一次高音1024Hz信号,音响持续1秒钟,在1024Hz音响结束时刻为整点。在实际电路中使用灯实现四低使用用,高音另一个灯显示。(4)、具有一键设定闹铃及正常计时与闹铃时间的显示转换。闹时时间为一分钟。3、模块设计分析整体电路分为两块,主体电路和扩展电路分别实现基本功能和扩展的功能。(1)、主体电路设计: (2)时分秒计数器需求分析:分和秒计数器都是模M=60的计数器 其计数规律为0001585900 时计数器:若采用24小时制:计数器为24进制,其计数规律为 0001022300.若采用12小时制:计数器为12进制,其计数规律为 01021201.24小时制:当数字钟运行到23时59分59秒时,秒的个位计数器再输入一个秒脉冲时,数字钟应自动显示为00时00分00秒。12小时制:当数字钟运行到12时59分59秒时,秒的个位计数器再输入一个秒脉冲时,数字钟应自动显示为01时00分00秒。4、逻辑分析:主体电路由两个60进制计数器、一个24进制计数器、两个二选一数据选择器、分频器,7端译码显示器共7个模块组成。分频器将系统内置的50MHz的信号分成4Hz的信号输出CP,是数字能稳定的在数码管上显示。3个计数器共用一个时钟信号CP,为同步8421BCD码输出的计数器。具体实现如下图:秒译码显示分译码显示时译码显示60进制计数器选择器60进制计数器选择器24进制计数器 1 1 EN MCoM EN SCo EN 校时控制Adj_Hour 校分控制Adj_Min (adjust_Time) (adjust_Time)图中连个选择器分别用于选择分计数器和是计数器的使能控制信号。对时间进行校正时,先选择校时模式,在adjust_Time=1时,在控制端(Adj_Hour、Adj_Min)的作用下,使能信号接高电平,此时每来一个时钟信号,计数器加1,从而实现对小时和分钟的校正。正常计时时,使能信号来自每一位的低位计数器的输出,即秒计数器到59秒时,产生一个输出信号(Sco=1)使分计数器加1,分秒计数器同时计到最大值时,产生输出信号(Mco=1)使小时计数器加1。实现上述功能的Verilog的程序如下:整个程序2分为两个层次4个模块,底层由3个模块组成,即六进制计数模块、十进制计数模块、和24进制计数模块、顶层有一个模块,他调用底层的3个模块完成数字钟的计时功能,其中,底层的六进制模块,和十进制模块分别被调用两次,构成60进制的秒计数器和分计数器。5、各模块接口规定输入量需求说明输出量需求说明CP工作时钟out_HourH时钟十位EN使能端1时计数out_HourL时钟个位nCR清零端即复位端out_MinH分钟十位Alarm_on闹钟开关out_MinL分钟个位Display_A切换闹钟SEC秒频率Adjust_Time调整时钟D四低Adj_Min自动调整分钟G一高Adj_Hour自动调整时钟A闹钟Sel12/24进制切换Voice正点报时6、程序分析:(1)、六进制计数模块nCR为复位端口,当nCR 为0是,输出为0,EN为使能端,只有当EN为1时,计数器才在CP的作用下加1。module counter6(Q,nCR,EN,CP);input CP,nCR,EN;output3:0 Q;reg 3:0 Q;always(posedge CP or negedge nCR)begin if(nCR) Q<=4'b0000;else if(EN) Q<=Q;else if(Q=4'b0101) Q<=4'b0000;else Q<=Q+1'b1;endendmodule仿真波形如下:(2)、十进制模块和六进制的思想一样module counter10(Q,nCR,EN,CP);input CP,nCR,EN;output3:0 Q;reg 3:0 Q;always(posedge CP or negedge nCR)begin if(nCR) Q<=4'b0000;else if(EN) Q<=Q;else if(Q=4'b1001) Q<=4'b0000;else Q<=Q+1'b1;endendmodule仿真波形如下:(3)、24进制模块 由于扩展功能里有12和24模式的切换,所以设置一模式控制端口Sel,当Sel=1时为12进制模式,当Sel=0时为24进制模式。12和24进制的思想是一样的。以24进制为例,在nCR和EN有效时,当时钟高位大于2或分钟高位大于9或者时钟大于等于23时,时钟高位HourH置0,低位HourL置1;如果(HourH=2)和(HourL<3)成立则高位不变,低位加1;其余的如果HourL=9;高位加1,低位置0;剩下的情况高位不变,低位加1。module counter24(HourH,HourL,nCR,EN,CP,Sel);input CP,nCR,EN,Sel;output3:0 HourH,HourL;reg 3:0 HourH,HourL;always(posedge CP or negedge nCR)beginif(nCR) HourH,HourL<=8'h00 ; 复位else if(EN) HourH,HourL<=HourH,HourL; 使能else if(Sel=1) 模式选择begin 12进制if(HourH>1)|(HourL>9)|(HourH=1)&&(HourL>=2) begin HourH<=4'b0000;HourL<=4'b0001;endelse if(HourH=1)&&(HourL<2)begin HourH<=HourH; HourL<=HourL+1'b1; endelse if(HourL=9)begin HourH<=HourH+1'b1; HourL<=4'b0000; endelsebegin HourH<=HourH; HourL<=HourL+1'b1; end endelse begin 24 进制if(HourH>2)|(HourL>9)|(HourH=2)&&(HourL>=3) HourH,HourL<=4'b0000;else if(HourH=2)&&(HourL<3)begin HourH<=HourH; HourL<=HourL+1'b1; endelse if(HourL=9)begin HourH<=HourH+1'b1; HourL<=4'b0000; endelsebegin HourH<=HourH; HourL<=HourL+1'b1; endendendendmodule仿真波形如下:(4)、分频成1Hz模块由于系统供给时钟为50MHz时钟,为保证系统计数结果清晰可辨,可设计分频模块clk1hz(clk,CP),先将系统50MHz时钟clk(50MHz)分频为1Hz时钟。由于50M可以使用32位二进制来表示,定义clk为输入的50MHz时钟module fenpin(clk,CP); input clk; output CP; reg CP; initial begin CP<=1'b0;clk1<=32'd0; end reg31:0 clk1; /可以通过调节25000000的数值来调节输出的频率大小 always (posedge clk) if(clk1=32'd25000000) begin clk1<=32'd0; CP<=CP; end else clk1<=clk1+1'b1;endmodule 由于这个仿真的时钟频率大,没有在波形里显示:(5)、整点报时和仿电台报时模块将时分秒输入,因为没有使用蜂鸣器,所用的报时均用LED灯来显示,四声低音时在51秒、53秒、57秒、59秒、D亮;0时G亮;根据输入的Hour的数值使整点报时的灯Voice亮Hour下,9点闪烁9下。整点报时时控制灯闪烁的频率和秒的频率一样,为了实现闪烁必需有两倍的Hour数值的脉冲,设置变量N来实现计数,每次在00分00秒时,将两倍的Hour数值赋给n,每来一个脉冲就减1,直至n=0时,正好有2*Hour个脉冲,灯Voice可闪烁相应的次数。module baoshi(Second,Minute,Hour,D,G,Voice,CP);input 7:0 Second,Minute,Hour;input CP;output D,G;output Voice;reg D,G;reg 7:0 n;reg Voice;initialbegin n=8'h0;Voice=0; endalwaysbeginif(Minute=8'h59)&&(Second7:4=4'h5)&&(Second3:0=4'h0)|(Second3:0=4'h2)|(Second3:0=4'h4)|(Second3:0=4'h6)D<=1'b1;else if(Minute=8'h59)&&(Second7:4=4'h5)&&Second3:0=4'h8) G<=1'b1;else begin G<=1'b0;D<=1'b0;end endalways(posedge CP)beginif(Minute=8'h00)&&(Second=8'h00) n<=Hour+Hour; if(Minute=8'h00)&&(n>8'd0) begin Voice<=Voice;n<=n-1'b1; endelse Voice<=0; endendmodule仿真波形如下:仿电台报时:整点报时:(6)、闹钟设置模块 设置一个控制端来控制闹钟的显示和闹钟的设置Display_A,当Display_A=1时,进入闹钟模式,此时数码管上显示的为闹钟的时间,为方便闹钟的设置依然使用Adj_Min,Adj_Hour控制端。因为闹钟同样要满足分钟的60进制和时钟24 进制,所以在alarm_Set模块中调用底层的counter10,counter6,counter24,模块来实现闹钟的设置。并将所设置的闹钟时间保存在A_Hour,A_Minute中表示闹钟的时间。并将其作为输出,以便后续的使用。module alarm_Set(Adj_Min,Adj_Hour,CP,nCR,Display_A,A_Hour,A_Minute);input CP,nCR,Adj_Min,Adj_Hour,Display_A;output 7:0 A_Hour,A_Minute;/ 在闹钟的控制端Display_A&&Adj_Min同时为1时闹钟计时counter10 A1(A_Minute3:0,nCR,(Display_A&&Adj_Min),CP);counter6 A2(A_Minute7:4,nCR,(Display_A&&Adj_Min&&A_Minute3:0=4'h9),CP);counter24 A3(A_Hour7:4,A_Hour3:0,nCR,(Adj_Hour&&Display_A),CP,Sel);endmodule(7)、闹铃模块同时将时分钟和闹钟的时分输入进行比较,如果二者对应相等且闹铃设置alarm_On为0(默认下闹铃为开状态),则闹钟提示灯A持续亮一分钟。一分钟的时间有秒钟频率来控制。 module alarm (Hour,Minute,A_Hour,A_Minute,Second,A,CP,alarm_On);input 7:0 Hour,Minute,A_Hour,A_Minute,Second;input CP,alarm_On;output A;reg A;always (posedge CP)if (Hour=A_Hour) && (A_Minute=Minute)&&(alarm_On=0)begin if(Second<=8'h59) A<=1'b1;else A<=1'b0;endelse A<=1'b0;endmodule(8)、显示模块 由于要切换时钟和闹钟模式,所以由闹钟的控制端口来决定显示的模式,当Disply_A为1时,即为闹钟模式,显示闹钟时间;Disply_A为0时,即为时钟模式,显示时钟时间。程序中Q1为时钟信息,Q2为闹钟的信息。module display(Q1,Q2,Display_A,OUT); input3:0 Q1,Q2; input Display_A; output6:0 OUT; reg6:0 OUT; wire 3:0 Q; assign Q=(Display_A=1) ? Q23:0 : Q13:0 ; /闹钟和时钟的选择 always (Q)case(Q3:0) 4'd0: OUT<=7'b0000_001; 4'd1: OUT<=7'b1001_111; 4'd2: OUT<=7'b0010_010; 4'd3: OUT<=7'b0000_110; 4'd4: OUT<=7'b1001_100; 4'd5: OUT<=7'b0100_100; 4'd6: OUT<=7'b1100_000; 4'd7: OUT<=7'b0001_111; 4'd8: OUT<=7'b0000_000; 4'd9: OUT<=7'b0001_100; default: OUT<=7'b0000_001; endcaseendmodule (9)、顶层模块调用所有的底层模块module clock_top(out_MinL,out_MinH,out_HourL,out_HourH,clk,nCR,EN,Adj_Min,Adj_Hour,adjust_Time,SEC,D,G,A,Sel,Voice,alarm_On,Display_A);input clk,nCR,EN,Adj_Min,Adj_Hour,Sel,Display_A,adjust_Time,alarm_On;output 6:0 out_MinL,out_MinH,out_HourL,out_HourH;output SEC;output D,G,Voice,A;wire 7:0 Hour,Second,Minute,A_Hour,A_Minute;wire MinL_EN,MinH_EN,Hour_EN;wire 6:0 out_MinL,out_MinH,out_HourL,out_HourH;wire D,G,Sel,A;fenpin U0(CP,clk);counter10 U1(Second3:0,nCR,EN,CP); /秒钟的60进制counter6 U2(Second7:4,nCR,(Second3:0=4'h9),CP);assign SEC=Second0; 秒钟以LED来显示 /分钟低位的使能端,满足条件才计数assign MinL_EN=(Adj_Min=1)&&(adjust_Time=1) | (Second=8'h59); /分钟高位的使能端,满足条件才计数assign MinH_EN=(Adj_Min&&(adjust_Time=1)&&(Minute3:0=4'h9)|(Minute3:0=4'h9)&&(Second=8'h59)&&(Adj_Min=0);counter10 U3(Minute3:0,nCR,MinL_EN,CP); /分钟的60进制counter6 U4(Minute7:4,nCR,MinH_EN,CP);assignHour_EN=(Adj_Hour=1)&&(adjust_Time=1)|(Minute=8'h59)&&(Second=8'h59); counter24 U5(Hour7:4,Hour3:0,nCR,Hour_EN,CP,Sel); /时钟的24进制baoshi U11(Second7:0,Minute7:0,Hour7:0,D,G,Voice,CP);alarm_Set U12(Adj_Min,Adj_Hour,CP,nCR,Display_A,A_Hour,A_Minute);alarm U13(Hour,Minute,A_Hour,A_Minute,Second,A,CP,alarm_On);/显示模块的调用display U6(Minute3:0,A_Minute3:0,Display_A,out_MinL);display U7(Minute7:4,A_Minute7:4,Display_A,out_MinH);display U8(Hour3:0,A_Hour3:0,Display_A,out_HourL);display U9(Hour7:4,A_Hour7:4,Display_A,out_HourH);endmodule为各个输入输出接口分配引脚,如下,使其在实验板上的数码管上显示结果。整个实验通过验收。五、调试过程1、调试步骤如果程序编译出错,可以根据错误提示找出错误,这类错误比较容易解决。比如某一行少一个“;”之类的。如果编译通过,再进行仿真,通过仿真波形来判断程序是否出现了逻辑性的错误,这些需要仔细的研究仿真波形,才能看出错误的所在。仿真后,确定仿真波形和程序没有问题,再进行引脚的分配,引脚分配后,编译,再烧写到DE0板上,如果出现错误,返回引脚分配,找出错误所在。在DE0实验板上运行程序时,碰到一些功能与设计不符,或者产生了竞争冒险等问题的时候,应该对程序进行查错和对时序的优化,通过不断的改进和优化程序,最终得到的程序才符合要求。2、调试中碰到的问题及解决方法(1)、用Quartus自带的波形仿真器时,必须在仿真前,将自己编写的波形文件设置为顶层文件,不然的话,仿真结果将是高阻态。(2)、在编写代码时,对于一些比较不常用的verilog语法不是很熟练。犯了一些语法错误,比如在写Disply模块时,未把Q设置成4位的二进制数,只是简单的说明了一下wire Q结果在显示时,一直出现0,1跳变,无法正常显示计数。但在编译时,并没有报错。在反复检查程序时才发现,应该把Q定义为4位的。更改之后出现了正确的显示。六、实验小结:通过这次设计,既复习了以前所学的知识,也进一步加深了对EDA的了解,掌握了EDA设计的基本流程(即设计输入编译调试仿真下载),领会了自顶而下结构化设计的优点,并具备了初步的EDA程序设计能力。让我对它有了更加浓厚的兴趣。特别是当每一个子模块编写调试成功时,心里特别的开心。这个程序最难的地方在于顶层模块的设计,因为顶层模块需要将各个子模块按照电路原理有机地结合起来,这需要扎实的理论功底,而这正是我所欠缺的。相比而言,子模块的设计就容易多了,因为Verilog语言和C语言有很多相似之处,只要明白了实验原理,就不难完成,水平的高下只体现在程序的简洁与否。Verilog源程序的编写很容易出现错误,这就需要耐心的调试。因为很多情况下,一长串的错误往往是由一个不经意的小错误引起的。当程序屡调屡错的时候,最好和其他同学沟通交流一下,他们不经意的一句话,就可能给我启发,使问题迎刃而解。在波形仿真时,也遇到了一点困难,想要的结果不能在波形上得到正确的显示。还有的仿真图根本就不出波形,怎么调节都不管用,后来直接就连上了实验板,结果却在实验板上很好的显示了,我自己都感到很纳闷。现在还不知道为什么。 总的来说,这次设计的数字钟还是比较成功的,有点小小的成就感,终于觉得平时所学的知识有了实用的价值,达到了理论与实际相结合的目的,不仅学到了不少知识,而且锻炼了自己的能力,使自己对以后的路有了更加清楚的认识,同时,对未来有了更多的信心。