FPGA设计多功能数字闹钟.docx
《FPGA设计多功能数字闹钟.docx》由会员分享,可在线阅读,更多相关《FPGA设计多功能数字闹钟.docx(13页珍藏版)》请在冰豆网上搜索。
FPGA设计多功能数字闹钟
设计题目:
设计多功能时钟
姓名:
钱笠
班级:
通信0901
学号:
20096165
指导老师:
龙惠民
设计要求:
(1)可以对小时、分、秒进行计数
(2)可以显示当前的时间(3)可以校对当前的时间(4)可以设置闹钟
设计分析:
本实验是是在Quartus||的环境下进行的一种基于FPGA的数字时钟。
该设计最后通过仿真实现预定功能。
电子时钟的时间显示是通过七段数码管显示的,其内部的时间控制输出是通过各种模块实现的,包括:
功能选择模块、时钟分频模块、校时模块、计时模块、闹钟模块、锁存模块、显示模块共七个部分。
实验原理:
显示时—分—秒、整点报时、小时和分钟可调等基本功能。
整个钟表的工作应该是在1Hz信号的作用下进行,这样每来一个时钟信号,秒增加1秒,当秒从59秒跳转到00秒时,分钟增加1分,同时当分钟从59分跳转到00分时,小时增加1小时,小时的范围为0~23时。
在实验中为了显示的方便,由于分钟和秒钟显示的范围都是从0~59,所以可以用一个3位的二进制码显示十位,用一个四位的二进制码(BCD码)显示个位,对于小时因为他的范围是从0~23,所以可以用一个2位的二进制码显示十位,用一个4位的二进制码(BCD码)显示个位。
实验中由于七段码管是扫描的方式显示,所以虽然时钟需要的是1Hz时钟信号,但是扫描需要一个比较高频率的信号,因此为了得到准确的1Hz信号,必须对输入的系统时钟50Mhz进行分频。
闹钟功能时,通过手动调整对其定时,若设定的时间与计数的时间相等时,发出闹铃声。
二:
单元模块的设计:
1、分频模块
源程序:
modulediv_50(clk,clk_1Hz);
inputclk;
outputclk_1Hz;
regclk_1Hz;
parameterN=999999;
reg[19:
0]Count;
always@(negedgeclk)
begin
if(Count==N)
begin
Count<=0;
clk_1Hz<=~clk_1Hz;
end
else
Count<=Count+1'b1;
end
endmodule
-测频控制器,使得频率计能自动测频
moduletestctl(clkk,cnt_en,rst_cnt,load);
inputclkk;//1HZ
outputcnt_en;
outputrst_cnt;
outputload;
regdiv2clk;
wirecnt_en;
regrst_cnt;
wireload;
always@(posedgeclkk)
div2clk<=~div2clk;
always@(clkkordiv2clk)begin
if(!
clkk&!
div2clk)rst_cnt<=1'b1;
elserst_cnt<=1'b0;
end
assignload=~div2clk;
assigncnt_en=div2clk;
endmodule
(参考FPGA实验5,仿真见实验5中)
2、功能选择模块
当mode0为0时,选择校时模块;当mode0为1时,选择计时和闹铃模块。
源程序:
modulemode(mode0,m);
inputmode0;
output[1:
0]m;
reg[1:
0]m;
always@(mode0)
begin
case(mode0)
1'b0:
m<=2'b00;//选择校时功能
1'b1:
m<=2'b11;//选择计时和闹铃功能
default:
m<=2'b00;
endcase
end
endmodule
仿真波形图
3、60进制计数模块
当秒脉冲clk1_1作为控制信号时,进行计时功能;当手动按键生成的方波信号clk1作为控制信号时,进行校时功能。
当计数满60时进位,并重新开始计数。
modulejishu_60(sel1,clk1,clk1_1,rst,out1,co);
inputclk1,clk1_1,rst;
inputsel1;
output[7:
0]out1;
outputco;
reg[7:
0]out1;
regco;
wireclk0;
/*选择控制信号是秒脉冲信号clk1_1还是手动按键生成的方波信号clk1*/
assignclk0=(sel1==0)?
clk1:
clk1_1;
always@(posedgeclk0ornegedgerst)
if(!
rst)
out1<=8'b0;//清零
else
begin
if(out1==8'h59)
begin
out1<=8'b0;//满60后清零,让其重新计数
co<=1'b1;//进位
end
else
begin
co<=1'b0;
if(out1[3:
0]==4'b1001)
begin
out1[3:
0]<=4'b0000;
out1[7:
4]<=out1[7:
4]+1'b1;//高位计数
end
else
out1[3:
0]<=out1[3:
0]+1'b1;//低位计数
end
end
endmodule
仿真波形图
4、24进制计数模块
当分的进位clk2_2作为控制信号时,进行计时功能;当手动按键生成的方波信号clk2作为控制信号时,进行校时功能。
当计数满24时清零,并重新开始计数。
源程序:
modulejishu_24(sel2,clk2,clk2_2,rst,out2);
inputsel2,rst;
inputclk2,clk2_2;
output[7:
0]out2;
reg[7:
0]out2;
wireclk0;
/*选择控制信号是分进位信号clk2_2还是手动按键生成的方波信号clk2*/
assignclk0=(sel2==0)?
clk2:
clk2_2;
always@(posedgeclk0ornegedgerst)
if(!
rst)
out2<=0;//清零
else
begin
if(out2==8'h23)
out2<=0;
else
begin
if(out2[3:
0]==4'b1001)
begin
out2[3:
0]<=4'b0000;
out2[7:
4]<=out2[7:
4]+1;//时高位计数
end
else
out2[3:
0]<=out2[3:
0]+1;//时低位计数
end
end
endmodule
仿真波形图
5、锁存模块
当sel4为0时,选择clk3信号(手动按键取反产生);否则选择clk4信号(秒脉冲取反产生)。
当控制信号的上升沿时,将计数器的值进行锁存。
源程序:
modulereg3(sel4,clk3,clk4,cq,led);
inputsel4;
inputclk3,clk4;
input[7:
0]cq;
output[7:
0]led;
reg[7:
0]led;
wireclk0;
/*选择控制信号是秒脉冲取反产生的clk4还是手动按键取反生成的方波信号clk3*/
assignclk0=(sel4==0)?
clk3:
clk4;
always@(posedgeclk0)
led<=cq;//锁存
endmodule
仿真波形图
6校时模块
拨动电平开关mode1,选择对时、分、秒进行校时。
当手动进行按键时产生方波信号key1作为校时时计数器的输入信号,使计数器计数,从而达到校时的目的。
源程序
modulecheck(mode1,key1,Q1,Q2);
input[2:
0]mode1;
inputkey1;
output[2:
0]Q1,Q2;
reg[2:
0]Q1,Q2;
always@(mode1orkey1)//当mode1或key1任意一个改变时,触发always模块
begin
case(mode1)
3'b001:
begin//产生秒校时的控制信号
if(key1==1)
Q1[0]<=1;
else
Q1[0]<=0;
end
3'b010:
begin//产生分校时的控制信号
if(key1==1)
Q1[1]<=1;
else
Q1[1]<=0;
end
3'b100:
begin//产生时校时的控制信号
if(key1==1)
Q1[2]<=1;
else
Q1[2]<=0;
end
default:
Q1<=3'b0;
endcase
end
always@(Q1)
Q2<=~Q1;//对Q1取反,产生锁存器的控制信号
endmodule
仿真波形图
7、定时模块
当手动产生的控制信号key2上升沿时,若sel3为0,对时、分清零;否则进行定时。
当mode2为0时,使分定时;当mode2为1时,使时定时。
源程序:
moduleclk(mode2,key2,sel3,min,hour,nclk);
inputmode2,key2,sel3;
output[7:
0]min,hour;
outputnclk;
reg[7:
0]min,hour;
regnclk;
always@(posedgekey2ornegedgesel3)
if(!
sel3)
begin
min<=0;//分清零
hour<=0;//时清零
end
else
begin
case(mode2)
1'b0:
begin
if(min==8'h59)
min<=0;
else
begin
if(min[3:
0]==4'b1001)
begin
min[3:
0]<=4'b0000;
min[7:
4]<=min[7:
4]+1;//定时分的高位
end
else
min[3:
0]<=min[3:
0]+1;//定时分的低位
end
end
1'b1:
begin
if(hour==8'h23)
hour<=0;
else
begin
if(hour[3:
0]==4'b1001)
begin
hour[3:
0]<=4'b0000;
hour[7:
4]<=hour[7:
4]+1;//定时时的高位
end
else
hour[3:
0]<=hour[3:
0]+1;//定时时的低位
end
end
default:
{hour,min}<=16'b0;
endcase
end
always@(key2)
nclk<=~key2;//对key2进行取反
endmodule
仿真波形图
8、闹铃模块
当定时的时间和计数的时间相等时,c为1,否则c为0。
当c为1时,若clk_2H(即500ms的信号)为1时,spkt为高电平;否则spkt为低电平。
设定时间到来时发出声音。
源程序:
modulesonger(clk_2H,A1,A2,B1,B2,spkt);
inputclk_2H;
input[7:
0]A1,A2,B1,B2;
outputspkt;
regspkt;
wirem;
assignc=(A1==B1)&&(A2==B2);//检查设定时间是否到来
always@(c)
if(c==1)
begin
if(clk_2H==1)
spkt<=1'b1;//将1赋值给spkt,扬声器发出声音
else
spkt<=1'b0;//将0赋值给spkt,扬声器不发声音
end
else
spkt<=1'b0;
endmodule
仿真波形图
9、显示模块
当mode3为2'b01时,显示校时和计时的时间;当mode3为2'b10时,显示定时的时间。
源程序:
moduledecl7s(mode3,led1,led2,LD1,LD2);
input[1:
0]mode3;
input[7:
0]led1,led2;
output[6:
0]LD1,LD2;
wire[6:
0]LD1,LD2;
wire[7:
0]a;
parameteri0=4'b0000,i1=4'b0001,i2=4'b0010,i3=4'b0011,i4=4'b0100,
i5=4'b0101,i6=4'b0110,i7=4'b0111,i8=4'b1000,i9=4'b1001;
parametem0=7'b1000000,m1=7'b1111001,m2=7'b0100100,m3=7'b0110000,
m4=7'b0011001,m5=7'b0010010,m6=7'b0000010,m7=7'b1111100,
m8=7'b0000000,m9=7'b0010000;
/*是选择显示校时或计时的时间,还是选择对闹钟进行定时的时间*/
assigna=(mode3==2'b01)?
led1:
(mode3==2'b10)?
led2:
8'b0;
assignLD1=(a[3:
0]==i0)?
m0:
(a[3:
0]==i1)?
m1:
(a[3:
0]==i2)?
m2:
(a[3:
0]==i3)?
m3:
(a[3:
0]==i4)?
m4:
(a[3:
0]==i5)?
m5:
(a[3:
0]==i6)?
m6:
(a[3:
0]==i7)?
m7:
(a[3:
0]==i8)?
m8:
(a[3:
0]==i9)?
m9:
m0;
assignLD2=(a[7:
4]==i0)?
m0:
(a[7:
4]==i1)?
m1:
(a[7:
4]==i2)?
m2:
(a[7:
4]==i3)?
m3:
(a[7:
4]==i4)?
m4:
(a[7:
4]==i5)?
m5:
m0;
endmodule
仿真波形图
实验心得:
这次综合性的实验大部分是在查阅资料和在别人的讲解下完成的,虽然有些方法很不好,不过大部分的原理和应该怎样去编写硬件程序有了很深的认识。
让自己增长了很多知识,希望在以后的学习过程中能够更加深入理解,在每个模块之间的使用和连接是很重要的这次实验最后原理图综合没有通过,存在一些问题,可能是在顶层模块中出现了问题,只有每个模块都能正常工作,在顶层模块调用中才比较好的使用,这次优化方面也没有去考虑,这次实验只是一个起点,以后将不断改进。