EDA数字时钟VerilogHDL.docx
《EDA数字时钟VerilogHDL.docx》由会员分享,可在线阅读,更多相关《EDA数字时钟VerilogHDL.docx(21页珍藏版)》请在冰点文库上搜索。
![EDA数字时钟VerilogHDL.docx](https://file1.bingdoc.com/fileroot1/2023-4/29/b576b5f7-47f3-41d9-8e45-f888e298a6dd/b576b5f7-47f3-41d9-8e45-f888e298a6dd1.gif)
EDA数字时钟VerilogHDL
EDA课程设计报告
一、实验任务
实验目的
1.深入了解基于EDA工具的复杂时序逻辑电路的设计。
2.理解并熟练利用EDA工具进行综合设计。
3.熟练掌握芯片烧录的流程及步骤。
4.掌握VerilogHDL语言的语法规范及时序电路描述方法。
5.掌握多个数码管动态扫描与键盘扫描的显示原理及设计方法。
实验要求
设计一个带闹钟功能的24小时数字钟,它包括以下几个组成部分:
①显示屏,由4个七段数码管组成,用于显示当前时间(时:
分)或设置的闹钟时间;
②数字键‘0’~‘9’,用于输入新的时间或新的闹钟时间;
③TIME(时间)键,用于确定新的时间设置;
④ALARM(闹钟)键,用于确定新的闹钟时间设置,或显示已设置的闹钟时间;
⑤扬声器,在当前时钟时间与闹钟时间相同时,发出蜂鸣声。
基本要求
(1)计时功能:
这是本计时器设计的基本功能,每隔一秒计时一次,并在显示屏上显示当前时间。
(2)闹钟功能:
如果当前时间与设置的闹钟时间相同,则扬声器发出蜂鸣声。
(3)设置新的计时器时间:
用户用数字键‘0’~‘9’输入新的时间,然后按"TIME"键确认。
发挥部分
(1)设置新的闹钟时间:
用户用数字键“0”~“9”输入新的时间,然后按“ALARM”键确认。
(2)显示所设置的闹钟时间:
在正常计时显示状态下,用户直接按下“ALARM”键,则已设置的闹钟时间将显示在显示屏上。
二、设计思路
硬件部分
本次数字时钟的设计主要在NC-EDA-2000C实验箱上完成,应用的芯片为Altara公司的EP1K10TC100—3芯片。
该芯片具有低内核电压、低功耗的特点。
芯片内门电路高达1万门,内部使用RAM作电路结构,速度高达几百MHZ,其输出可用管脚已全部开放,位于芯片的四周,用户可以根据自己的要求和芯片本身的功能自己任意定义管脚。
同时为了体现实验箱的可扩展性,在芯片的两边各有一个34脚的IDE插口,可以通过数据排线与其它应用模块相连接。
除了主芯片外,主要包括三大部分:
八个数码管组成的显示部分、4×4键盘构成的按键输入部分。
以及其他输入或输出部分,如:
"TIME"键、“ALARM”键、时钟信号、蜂鸣器等。
8位7段数码管:
采用2个进口共阴高红7段数码管组成,其连接管脚位选信号在数码管的左边由连接孔SEL0、SEL1、SEL2与其它模块连接。
数码管显示的设计示意图如下:
八位数码管显示设计示意图
4×4键盘:
4×4键盘主要是通过编程实现0~F的输入,也可以作为一个控制键。
在其上方的连接孔R1、R2、R3、R4控制横向4位;C1、C2、C3、C4纵向4位。
键盘输入设计示意图如下:
4×4键盘输入设计示意图
软件部分
软件主要应用软件quartus,使用VerilogHDL语言来编写程序。
在老师所给的keyscan的基础上加入计时部分、设置部分(时间的设置和闹钟的设置)以及闹铃部分。
a)计时部分
always@(posedgeclkl)//计时过程
begin
hour<=Hour;minute<=Minute;
if(reset)beginhour<=0;minute<=0;second<=0;end
else
if(second==59)
if(minute==59)
if(hour==23)beginsecond<=0;minute<=0;hour<=0;end
elsebeginsecond<=0;minute<=0;hour<=hour+1;end
elsebeginsecond<=0;minute<=minute+1;end
elsesecond<=second+1;
end
其中,clkl为1Hz的时钟信号,当每遇到一个时钟信号的上升沿时,秒钟就加1秒;当加到59时,分钟就加1,秒钟自动回到0重新计时;当分钟加到59时,时钟就加1,然后分钟回到0;当计时到23:
59:
59时,则回到00:
00:
00再进入计时。
reset为清零信号,高电平有效。
b)设置部分
always@(posedgeclkh)
begin
if(w==1)//设置时间
beginHour=num1*10+num2;Minute=num3*10+num4;end
elseif(p==1)//设置闹钟
beginAhour=num1*10+num2;Aminute=num3*10+num4;end
end
将按下的键值存在num1、num2、num3、num4中,再通过w和p即所谓的TIME(时间)键与ALARM(闹钟)键将输入的数值赋给初始时间或闹钟时间。
c)闹铃部分
always@(posedgeclkh)//闹钟响
begin
if((hour==Ahour)&&(minute==Aminute))ds=1;
elseds=0;
end
当设置的闹钟时间(时:
分)与当前的时间(时:
分)相等时,则闹铃发出响声;ds信号可以接在蜂鸣器上或者发光二极管上。
本次设计的完整程序已附在报告的最后。
整体程序编译无误。
程序中涉及的变量名称及其对应的变量意义:
引脚配置图
三、完成情况
在这次实验过程中我们完成了24小时数字时钟的设计。
时钟的显示屏为七段数码管。
显示出的时间格式为小时、分钟、秒钟(如图1)。
时钟含有闹钟,可以在程序中设置闹钟时间,在实际时间和闹钟时间相吻合时蜂鸣器响。
图2中的二极管亮即可说明,在闹钟时间可以输出高电平,该输出接在蜂鸣器上即可使蜂鸣器响。
本次设计的闹钟为响1分钟自动关闭。
图3中二极管熄灭。
图1时间显示
图2闹钟响(体现为发光二极管发光)
图3发光二极管熄灭(本次设计的闹钟为响1分钟自动关闭)
四、总结与收获
在实验设计的过程中,我们首先尝试了树上和老师上课时所讲的例程,在熟悉软件和设计流程后开始了数字时钟的设计。
在设计数字时钟时,我们先分设计出来时钟的自动计数显示,实现了24小时时钟。
之后实验了4*4键盘,实现了键盘输入值的扫描读取。
最后设计了闹钟部分,包括设置闹钟时间和到时间闹铃响。
我们通过本次实验深入了解基于EDA工具的复杂时序逻辑电路的设计,理解并熟练利用quartus进行VerilogHDL语言的设计。
掌握了建立工程项目,编译调试程序,下载程序的流程和步骤。
在应用的过程中掌握了数码管和键盘扫描的原理和方法。
并且对VerilogHDL语言的语法规则和几种常用语句有了更深入的理解。
实验过程中通过合作的方式,小组成员积极讨论,对不同的语句进行了对比,最终确定了本次实验的完整程序。
这次完成的数字时钟只是EDA实验箱中可以实现的众多功能之一,我们也认识到VerilogHDL语言可以实现的设计还有很多,本次实验激发了我们对VerilogHDL语言的兴趣,也让我们认识到课堂的学习是有限的,想更加深入学习VerilogHDL语言,还要在今后的学习中多多自学,勤加练习。
五、完整程序
modulezonghe(clkl,clkh,reset,q,w,p,kr,kc,a,b,c,d,e,f,g,sa,sb,sc,ds);
inputclkl,clkh,reset;//计数时钟脉冲、扫描频率脉冲与复位信号
inputq,w,p;//启动设置的控制信号、设置时间的控制信号及设置闹钟的控制信号
inout[3:
0]kr;//4*4键盘的行输入/输出信号
inout[3:
0]kc;//4*4键盘的列输入/输出信号
outputa,b,c,d,e,f,g,sa,sb,sc,ds;//LED的7个片选信号与3个位选信号
rega,b,c,d,e,f,g,sa,sb,sc,ds;
reg[3:
0]kr,kc;
reg[6:
0]display;
reg[2:
0]dcount,kcount;
reg[3:
0]keyr,keyc;
regkflag1,kflag2;
reg[6:
0]buff7;
reg[3:
0]shiwei1,gewei1,shiwei2,gewei2,shiwei3,gewei3;
reg[5:
0]hour,minute,second,Ahour,Aminute,Hour,Minute;//储存当前时间的时分秒、闹钟的时分及设置的时间的时分
always@(posedgeclkh)//累加两个计数值
begin
dcount<=dcount+1;
kcount<=kcount+1;
end
always@(posedgeclkh)//扫描键盘
begin
if(kcount==0)
begin
kr<=4'b1111;
kc<=4'b0000;
end
elseif(kcount==1)
begin
keyr<=kr;
kr<=4'bZZZZ;
end
elseif(kcount==2)
begin
kr<=4'b0000;
kc<=4'b1111;
end
elseif(kcount==3)
begin
keyc<=kc;
kc<=4'bZZZZ;
end
end
always@(posedgeclkh)//改变键的标志位
begin
if(kcount==4&keyr==4'b1111)
kflag1<=0;
elseif(kcount==4)
kflag1<=1;
kflag2<=kflag1;
end
always@(posedgeclkh)//获取相应按键按下的结果
begin
if(kcount==5)
if(keyr==4'b1110)
case(keyc)
4'b1110:
buff7<=7'b0111111;//在LED上显示0
4'b1101:
buff7<=7'b0000110;//在LED上显示1
4'b1011:
buff7<=7'b1011011;//在LED上显示2
4'b0111:
buff7<=7'b1001111;//在LED上显示3
default:
buff7<=buff7;//无变化
endcase
elseif(keyr==4'b1101)
case(keyc)
4'b1110:
buff7<=7'b1100110;//在LED上显示4
4'b1101:
buff7<=7'b1101101;//在LED上显示5
4'b1011:
buff7<=7'b1111101;//在LED上显示6
4'b0111:
buff7<=7'b0000111;//在LED上显示7
default:
buff7<=buff7;//无变化
endcase
elseif(keyr==4'b1011)
case(keyc)
4'b1110:
buff7<=7'b1111111;//在LED上显示8
4'b1101:
buff7<=7'b1101111;//在LED上显示9
4'b1011:
buff7<=7'b1110111;//在LED上显示a
4'b0111:
buff7<=7'b1111100;//在LED上显示b
default:
buff7<=buff7;//无变化
endcase
elseif(keyr==4'b0111)
case(keyc)
4'b1110:
buff7<=7'b0111001;//在LED上显示c
4'b1101:
buff7<=7'b1011110;//在LED上显示d
4'b1011:
buff7<=7'b1111001;//在LED上显示e
4'b0111:
buff7<=7'b1110001;//在LED上显示f
default:
buff7<=buff7;//无变化
endcase
end
always@(posedgeclkh)//显示过程
begin
sa<=dcount[0];//将dcount赋给LED的三个片选信号
sb<=dcount[1];
sc<=dcount[2];
shiwei1=hour/10;
gewei1=hour%10;
shiwei2=minute/10;
gewei2=minute%10;
shiwei3=second/10;
gewei3=second%10;
if(dcount==3'b111)//判断位选dcount的值,并将此位上的值输出到数码管
case(shiwei1)//在第一数码管上显示时钟的十位
4'b0000:
display<=7'b0111_111;
4'b0001:
display<=7'b0000_110;
4'b0010:
display<=7'b1011_011;
4'b0011:
display<=7'b1001_111;
4'b0100:
display<=7'b1100_110;
4'b0101:
display<=7'b1101_101;
4'b0110:
display<=7'b1111_101;
4'b0111:
display<=7'b0000_111;
4'b1000:
display<=7'b1111_111;
4'b1001:
display<=7'b1101_111;
default:
display<=7'b0000_000;
endcase
if(dcount==3'b000)//在第二个数码管上显示时钟的个位
case(gewei1)
4'b0000:
display<=7'b0111_111;
4'b0001:
display<=7'b0000_110;
4'b0010:
display<=7'b1011_011;
4'b0011:
display<=7'b1001_111;
4'b0100:
display<=7'b1100_110;
4'b0101:
display<=7'b1101_101;
4'b0110:
display<=7'b1111_101;
4'b0111:
display<=7'b0000_111;
4'b1000:
display<=7'b1111_111;
4'b1001:
display<=7'b1101_111;
default:
display<=7'b0000_000;
endcase
if(dcount==3'b001)//在第三个数码管上显示分钟的十位
case(shiwei2)
4'b0000:
display<=7'b0111_111;
4'b0001:
display<=7'b0000_110;
4'b0010:
display<=7'b1011_011;
4'b0011:
display<=7'b1001_111;
4'b0100:
display<=7'b1100_110;
4'b0101:
display<=7'b1101_101;
4'b0110:
display<=7'b1111_101;
4'b0111:
display<=7'b0000_111;
4'b1000:
display<=7'b1111_111;
4'b1001:
display<=7'b1101_111;
default:
display<=7'b0000_000;
endcase
if(dcount==3'b010)//在第四个数码管上显示分钟的个位
case(gewei2)
4'b0000:
display<=7'b0111_111;
4'b0001:
display<=7'b0000_110;
4'b0010:
display<=7'b1011_011;
4'b0011:
display<=7'b1001_111;
4'b0100:
display<=7'b1100_110;
4'b0101:
display<=7'b1101_101;
4'b0110:
display<=7'b1111_101;
4'b0111:
display<=7'b0000_111;
4'b1000:
display<=7'b1111_111;
4'b1001:
display<=7'b1101_111;
default:
display<=7'b0000_000;
endcase
if(dcount==3'b011)//在第五个数码管上显示秒钟的十位
case(shiwei3)
4'b0000:
display<=7'b0111_111;
4'b0001:
display<=7'b0000_110;
4'b0010:
display<=7'b1011_011;
4'b0011:
display<=7'b1001_111;
4'b0100:
display<=7'b1100_110;
4'b0101:
display<=7'b1101_101;
4'b0110:
display<=7'b1111_101;
4'b0111:
display<=7'b0000_111;
4'b1000:
display<=7'b1111_111;
4'b1001:
display<=7'b1101_111;
default:
display<=7'b0000_000;
endcase
if(dcount==3'b100)//在第六个数码管上显示秒钟的个位
case(gewei3)
4'b0000:
display<=7'b0111_111;
4'b0001:
display<=7'b0000_110;
4'b0010:
display<=7'b1011_011;
4'b0011:
display<=7'b1001_111;
4'b0100:
display<=7'b1100_110;
4'b0101:
display<=7'b1101_101;
4'b0110:
display<=7'b1111_101;
4'b0111:
display<=7'b0000_111;
4'b1000:
display<=7'b1111_111;
4'b1001:
display<=7'b1101_111;
default:
display<=7'b0000_000;
endcase
if(dcount==3'b101)display<=7'b1000_000;//在第七个数码管上显示“—”
if(dcount==3'b110)display<=buff7;//在第八个数码管上显示按下的键值
end
always@(posedgeclkh)//将display中存的值赋给LED的七个片选信号
begin
a<=display[0];
b<=display[1];
c<=display[2];
d<=display[3];
e<=display[4];
f<=display[5];
g<=display[6];
end
always@(posedgeclkl)//计时过程clkl的频率为1Hz
begin
hour<=Hour;minute<=Minute;//将设置的时间(时、分)赋给hour和minute
if(reset)
beginhour<=0;minute<=0;second<=0;end//当reset为1时,将时间清零即为00:
00:
00
else//正常计时
if(second==59)
if(minute==59)
if(hour==23)
beginsecond<=0;minute<=0;hour<=0;end
elsebeginsecond<=0;minute<=0;hour<=hour+1;end
elsebeginsecond<=0;minute<=minute+1;end
elsesecond<=second+1;
end
integeri;//记录按键按下的次数
reg[3:
0]num1,num2,num3,num4;//储存按键的键值
always@(posedgeclkh)//储存按下的键值
begin
if(q==1)//启动设置
begin
i=0;
if(keyc!
=4'b1111)i=i+1;//当有键按下时,i自动加1
if(i==1)//将第一个按下的按键值存入num1
begin
case({keyr,keyc})
4'b1110_1110:
num1=0;
4'b1110_1101:
num1=1;
4'b1110_1011:
num1=2;
4'b1110_0111:
num1=3;
4'b1101_1110:
num1=4;
4'b1101_1101:
num1=5;
4'b1101_1011:
num1=6;
4'b1101_0111:
num1=7;
4'b1011_1110:
num1=8;
4'b1011_1101:
num1=9;
default:
num1=num1;
endcase
end
if(i==2)//将第二个按下的按键值存入num2
begin
case({keyr,keyc})
4'b1110_1110:
num2=0;
4'b1110_1101:
num2=1;
4'b1110_1011:
num2=2;
4'b1110_0111:
num2=3;
4'b1101_1110:
num2=4;
4'b1101_1101:
num2=5;
4'b1101_1011:
num2=6;
4'b1101_0111:
num2=7;
4'b1011_1110:
num2=8;
4'b1011_1101:
num2