一、目的:
實(shí)現(xiàn)多功能數(shù)字鐘,具備下列功能:
1、數(shù)字鐘:能計(jì)時(shí),實(shí)現(xiàn)小時(shí)、分鐘、秒的顯示;
2、數(shù)字跑表:精度至0.01秒 比如顯示12.97秒;
3、鬧鐘: 可以設(shè)定鬧鐘,用試驗(yàn)箱上的蜂鳴器作為鬧鈴;
4、調(diào)時(shí):可以對(duì)時(shí)間進(jìn)行設(shè)定;
5、日期設(shè)定:能設(shè)定日期并顯示當(dāng)前日期;
6、除調(diào)時(shí)狀態(tài),其他狀態(tài)均不應(yīng)影響系統(tǒng)計(jì)時(shí)。
二、設(shè)計(jì)方案與設(shè)計(jì)思路:
整體程序通過例化10個(gè)模塊后整合形成多功能數(shù)字時(shí)鐘功能,各模塊名稱以及各模塊的作用分別為:
1、總控制模塊:用于控制調(diào)整時(shí)分秒、年月日以及鬧鐘的模式選擇,以及控制三個(gè)add按鍵調(diào)整的對(duì)象。
2、分頻器模塊:用于分頻得到1Hz計(jì)時(shí)時(shí)鐘。
3、時(shí)分秒調(diào)整模塊:處于計(jì)時(shí)器時(shí)分秒調(diào)整設(shè)置狀態(tài)時(shí),對(duì)應(yīng)控制模塊的三個(gè)add按鍵可以實(shí)現(xiàn)對(duì)計(jì)時(shí)器的時(shí)分秒數(shù)值的設(shè)置,并且有按鍵可以實(shí)現(xiàn)對(duì)時(shí)分秒模塊進(jìn)行設(shè)置數(shù)值的載入。
4、時(shí)分秒變量處理(計(jì)時(shí))模塊:用于計(jì)時(shí),根據(jù)分頻后的時(shí)鐘每隔一秒使秒變量加一,滿六十向分變量進(jìn)一,以此類推實(shí)現(xiàn)分鐘以及小時(shí)的進(jìn)位。
5、年月日調(diào)整模塊:處于日期年月日調(diào)整設(shè)置狀態(tài)時(shí),對(duì)應(yīng)控制模塊的三個(gè)add按鍵可以實(shí)現(xiàn)對(duì)年月日數(shù)值的設(shè)置,并且有按鍵可以實(shí)現(xiàn)對(duì)年月日變量處理模塊進(jìn)行設(shè)置數(shù)值的載入。
6、年月日變量處理(計(jì)日期)模塊:用于計(jì)日期,根據(jù)時(shí)分秒變量處理模塊的小時(shí)值進(jìn)位進(jìn)行自加,小時(shí)滿二十四向日變量進(jìn)一,以此類推實(shí)現(xiàn)日以及年月的進(jìn)位。
7、鬧鐘設(shè)置及使能模塊:用于設(shè)置鬧鐘的時(shí)分秒數(shù)值,處于鬧鐘設(shè)置狀態(tài)時(shí),對(duì)應(yīng)控制模塊的三個(gè)add按鍵實(shí)現(xiàn)對(duì)鬧鐘的時(shí)分秒數(shù)值的設(shè)置,并帶有可關(guān)閉開啟鬧鐘的開關(guān)。
8、數(shù)字跑表模塊:精度至0.01秒,其中包含了100Hz時(shí)鐘分頻模塊,且可通過按鍵進(jìn)行清零操作。
9、數(shù)碼管顯示控制模塊:可以選擇性地控制數(shù)碼管顯示的三個(gè)不同模式的內(nèi)容。
10、可視化數(shù)碼管顯示模塊:使用六個(gè)帶譯碼器的靜態(tài)數(shù)碼管實(shí)現(xiàn)小時(shí)、分鐘、秒或日期年、月、日或鬧鐘時(shí)、分、秒的顯示以及數(shù)字跑表精度至0.01秒的跑秒顯示。以上模塊例化后可得RTL原理圖如下:
三、各模塊代碼及仿真結(jié)果:
//總控制模塊
module kongzhi(
input add2,
input add1,
input add0,
input k5,
input k6,
input k7,//控制三個(gè)add按鍵調(diào)整的對(duì)象
output reg sec_add,
output reg min_add,
output reg hour_add,
output reg day_add,
output reg mon_add,
output reg year_add,
output reg sec_beemp_add,
output reg min_beemp_add,
output reg hour_beemp_add
);
always @(*)
begin
case ({k5,k6,k7})
3:{year_add,mon_add,day_add}={add2,add1,add0};//選擇的是調(diào)日期模式,add三個(gè)按鍵可增加年月日
4:{hour_beemp_add,min_beemp_add,sec_beemp_add}={add2,add1,add0};//選擇的是調(diào)鬧鐘模式,add三個(gè)按鍵可增加鬧鐘值的時(shí)分秒
default:{hour_add,min_add,sec_add}={add2,add1,add0};//選擇的是調(diào)時(shí)模式,add三個(gè)按鍵可增加計(jì)時(shí)器的時(shí)分秒
endcase
end
endmodule
上圖為總控制模塊不分頻的仿真結(jié)果: 使K5 K6 K7分別為0 0 1,選擇輸出調(diào)時(shí)數(shù)值的結(jié)果,即:{hour_add,min_add,sec_add}={add2,add1,add0};可見輸入隨機(jī)信號(hào)給三個(gè)add時(shí),各add對(duì)應(yīng)的輸出數(shù)組賦值結(jié)果是相匹配的。
//分頻器(1Hz)
module fre_div(
input clk_in,
output reg clk,//輸出的分頻后的時(shí)鐘
output reg clk_disp
);
parameter N=25000000;
integer cnt;
always @(posedge clk_in)
begin //分頻出1Hz時(shí)鐘
if(cnt == N-1)
begin
clk = ~clk; //分頻后的時(shí)鐘取反
clk_disp=clk;
cnt = 0;
end
else
begin //時(shí)鐘更新
cnt = cnt + 1;
end
end
endmodule
上圖為分頻器6分頻結(jié)果。
上圖為50M分頻結(jié)果,由于仿真時(shí)鐘波形不夠顯示50000000次時(shí)鐘波形,所以分頻結(jié)果未顯示出。
//計(jì)數(shù)器時(shí)分秒變量處理模塊
module sfm(
input clk,
input load1, //計(jì)數(shù)器開始工作標(biāo)志(1時(shí)輸出有效)
input [7:0] sec_in,
input [7:0] min_in,
input [7:0] hour_in,
output reg[7:0] sec_out,
output reg[7:0] min_out,
output reg[7:0] hour_out,
output reg clk_day //滿24小時(shí)后加一天的變量存儲(chǔ)
);
reg clk_min,clk_hour;//分鐘和小時(shí)的進(jìn)位標(biāo)志位
//輸出秒的值
always@(posedge load1 or posedge clk)
begin
if(load1)
begin
sec_out=sec_in;//開始輸出
end
else if(sec_out==8'd59)
begin
sec_out=0;
clk_min=1;//分鐘進(jìn)位標(biāo)志位置1
end
else
begin
sec_out=sec_out+1;//秒自加1
clk_min=0;
end
end
//min_out
always@(posedge load1 or posedge clk_min)
begin
if(load1)
begin
min_out=min_in;//開始輸出
end
else if(min_out==8'd59)
begin
min_out=0;
clk_hour=1;
end
else
begin
min_out=min_out+1;
clk_hour=0;
end
end
//hour_out
always@(posedge load1 or posedge clk_hour)
begin
if(load1)
begin
hour_out=hour_in;//開始輸出
end
else if(hour_out==8'd23)
begin
hour_out=0;
clk_day=1;
end
else
begin
hour_out=hour_out+1;
clk_day=0;
end
end
endmodule
上圖為計(jì)數(shù)器時(shí)分秒變量處理模塊計(jì)時(shí)狀態(tài)下6分頻仿真的結(jié)果。
//計(jì)數(shù)器時(shí)分秒設(shè)置模塊
module sfmsz(
input sec_add,
input min_add,
input hour_add,//計(jì)數(shù)器時(shí)分秒增加按鍵
output reg[7:0] sec_out,
output reg[7:0] min_out,
output reg[7:0] hour_out//計(jì)數(shù)器時(shí)分秒設(shè)置后的輸出
);
initial
begin
sec_out='d0;
min_out='d0;
hour_out='d0;
end
//設(shè)置秒
always@(posedge sec_add)//為1時(shí)秒的輸出+1
begin
begin
if(sec_out=='d59)
begin
sec_out=0;
end
else
begin
sec_out=sec_out+1;
end
end
end
//設(shè)置分
always@(posedge min_add)
begin
begin
if(min_out=='d59)
begin
min_out=0;
end
else
begin
min_out=min_out+1;
end
end
end
//設(shè)置小時(shí)
always@(posedge hour_add)
begin
begin
if(hour_out=='d23)
begin
hour_out=0;
end
else
begin
hour_out=hour_out+1;
end
end
end
endmodule
上圖為不分頻情況下仿真設(shè)置小時(shí)變量時(shí)的結(jié)果(分秒變量在相應(yīng)add按鍵按下時(shí)波形與小時(shí)相同,原理一致)。
//年月日變量處理模塊
module nyr(
input clk_day,
input load2,//為1時(shí)開始輸出年月日
input [7:0] day_in,
input [7:0] mon_in,
input [7:0] year_in,
output reg[7:0] day_out,
output reg[7:0] mon_out,
output reg[7:0] year_out
);
reg clk_mon,clk_year;//滿一月或者滿一年的進(jìn)位標(biāo)志位
//輸出日
always@(posedge load2 or posedge clk_day)
begin
if(load2)
begin
day_out=day_in;//開始輸出
end
else if(day_out==8'd30)
begin
day_out=0;
clk_mon=1;
end
else
begin
day_out=day_out+1;
clk_mon=0;
end
end
//輸出月
always@(posedge load2 or posedge
clk_mon)
begin
if(load2)
begin
mon_out=mon_in;//開始輸出
end
else if(mon_out==8'd12)
begin
mon_out=0;
clk_year=1;
end
else
begin
mon_out=mon_out+1;
clk_year=0;
end
end
//輸出年
always@(posedge load2 or posedge
clk_year)
begin
if(load2)
begin
year_out=year_in;//開始輸出
end
else if(year_out==8'd22)
begin
year_out=0;
end
else
begin
year_out=year_out+1;
end
end
endmodule
上圖為年月日變量處理模塊不分頻時(shí)的仿真結(jié)果。
//年月日設(shè)置變量模塊
module nyrsz(
input day_add,
input mon_add,
input year_add,
output reg[7:0] day_out,
output reg[7:0] mon_out,
output reg[7:0] year_out
);
initial
begin
day_out='d0;
mon_out='d0;
year_out='d0;
end
//設(shè)置日
always@(posedge day_add)//為1時(shí)日的輸出+1
begin
begin
if(day_out=='d30)
begin
day_out=0;
end
else
begin
day_out=day_out+1;
end
end
end
//設(shè)置月
always@(posedge mon_add)
begin
begin
if(mon_out=='d12)
begin
mon_out=0;
end
else
begin
mon_out=mon_out+1;
end
end
end
//設(shè)置年
always@(posedge year_add)
begin
begin
if(year_out=='d22)
begin
year_out=0;
end
else
begin
year_out=year_out+1;
end
end
end
endmodule
上圖為年月日變量設(shè)置模塊不分頻時(shí)的仿真結(jié)果。
//鬧鐘時(shí)分秒設(shè)置模塊,到達(dá)設(shè)定值后蜂鳴器響
module sfm_beemp(
input k3,
input [7:0] sec_in,
input [7:0] min_in,
input [7:0] hour_in,//檢測(cè)時(shí)分秒的輸入值
input sec_add,
input min_add,
input hour_add,//設(shè)置鬧鐘時(shí)分秒的增加按鍵
output reg[7:0] sec_out,
output reg[7:0] min_out,
output reg[7:0] hour_out,//設(shè)置的時(shí)分秒的鬧鐘值
output reg beemp//蜂鳴器輸出
);
initial
begin//先設(shè)置鬧鐘值為000
sec_out='d0;
min_out='d0;
hour_out='d0;
end
always@( hour_in or min_in or sec_in or k3 )
begin
if (~k3)//手動(dòng)控制鬧鐘響
beemp=1;
else
begin
if({hour_in,min_in,sec_in}=={hour_out,min_out,sec_out})//檢測(cè)到的時(shí)分秒對(duì)于設(shè)置好的鬧鐘值時(shí)分秒,鬧鐘響
beemp=0;
else
beemp=beemp;
end
end
//設(shè)置鬧鐘值的秒
always@(posedge sec_add)//秒按鍵使能
begin
begin
if(sec_out=='d59)
begin
sec_out=0;
end
else
begin
sec_out=sec_out+1;
end
end
end
//設(shè)置鬧鐘值的分
always@(posedge min_add)
begin
begin
if(min_out=='d59)
begin
min_out=0;
end
else
begin
min_out=min_out+1;
end
end
end
//設(shè)置鬧鐘值的小時(shí)
always@(posedge hour_add)
begin
begin
if(hour_out=='d23)
begin
hour_out=0;
end
else
begin
hour_out=hour_out+1;
end
end
end
endmodule
上圖為鬧鐘時(shí)分秒值設(shè)置模塊設(shè)置鬧鐘為0點(diǎn)0分0秒時(shí),不使能、不分頻的仿真結(jié)果。(三個(gè)add剛開始便滿足0時(shí)0分0秒條件,此時(shí)beemp=0,鬧鐘不響)
上圖為鬧鐘時(shí)分秒值設(shè)置模塊設(shè)置鬧鐘為0點(diǎn)0分0秒時(shí),使能、不分頻的仿真結(jié)果。(三個(gè)add剛開始便滿足0時(shí)0分0秒條件,此時(shí)beemp=1,鬧鐘響)
//數(shù)碼管顯示內(nèi)容的選擇控制模塊
module kongzhi_disp(
input k5,
input k6,
input k7,//控制數(shù)碼管顯示年月日還是計(jì)時(shí)器時(shí)分秒還是鬧鐘值時(shí)分秒
input [7:0] hour,//時(shí)分秒顯示的值
input [7:0] min,
input [7:0] sec,
input [7:0] hour_set,//時(shí)分秒設(shè)置的值
input [7:0] min_set,
input [7:0] sec_set,
input [7:0] year,//年月日顯示的值
input [7:0] mon,
input [7:0] day,
input [7:0] year_set,//年月日設(shè)置的值
input [7:0] mon_set,
input [7:0] day_set,
input [7:0] hour_beemp,//鬧鐘設(shè)置的值
input [7:0] min_beemp,
input [7:0] sec_beemp,
input [7:0] jsg,
input [7:0] jsd,
output reg[7:0] count2,
output reg[7:0] count1,
output reg[7:0] count0
);
always @(*)
case({k5,k6,k7})//不同的值顯示內(nèi)容不一樣
0:{count2,count1,count0}={hour,min,sec};
1:{count2,count1,count0}={hour_set,min_set,sec_set};
2:{count2,count1,count0}={year,mon,day};
3:{count2,count1,count0}={year_set,mon_set,day_set};
4:{count2,count1,count0}={hour_beemp,min_beemp,sec_beemp};
6:{count1,count0}={jsg,jsd};//顯示跑表計(jì)數(shù)高低位
default:{count2,count1,count0}={hour,min,sec};
endcase
endmodule
上圖為數(shù)碼管顯示內(nèi)容的選擇控制模塊不分頻的仿真結(jié)果: 使K5 K6 K7分別為0 1 0,選擇輸出年月日,即:{count2,count1,count0}={year,mon,day};可見輸出數(shù)組賦值結(jié)果是相匹配的。
//數(shù)字秒表及其單獨(dú)的分頻器模塊
module mb(clk_in,count3,count4,load3);
input clk_in,load3;
output reg [6:0]count3;
output reg [6:0]count4;
reg fp;
reg [24:0]TIM;
reg jw;
always @(posedge clk_in)//數(shù)字跑表單獨(dú)分頻
begin
if(TIM==500000)
begin
TIM=0;
fp=~fp;
end
else
begin
TIM=TIM+1;
fp=fp;
end
end
always @(posedge fp or posedge load3)
begin
if(load3)//為1時(shí)數(shù)字跑表值為0
begin
count3=0;
end
else if(count3==8'd59)
begin
count3=0;
jw=1;
end
else
begin
count3=count3+1;
jw=0;
end
end
always @(posedge jw or posedge load3)
begin
if(load3)//為1時(shí)數(shù)字跑表值為0
begin
count4=0;
end
else if(count4==8'd59)
begin
count4=0;
end
else
begin
count4=count4+1;
end
end
endmodule
上圖為數(shù)字跑表級(jí)其分頻模塊在6分頻情況下的仿真結(jié)果。(100Hz分頻仿真時(shí)鐘波形不夠顯示500000次時(shí)鐘波形無法顯示,故采用6分頻實(shí)現(xiàn))
//數(shù)碼管顯示模塊
module disp(
input [7:0] count,//存放顯示字符真值
output reg[3:0] smgL,
output reg[3:0] smgH
);
always@( count )
begin
case( count%10 )//顯示個(gè)位
4'h0 : smgL = 4'h0 ;
4'h1 : smgL = 4'h1 ;
4'h2 : smgL = 4'h2 ;
4'h3 : smgL = 4'h3 ;
4'h4 : smgL = 4'h4 ;
4'h5 : smgL = 4'h5 ;
4'h6 : smgL = 4'h6 ;
4'h7 : smgL = 4'h7 ;
4'h8 : smgL = 4'h8 ;
4'h9 : smgL = 4'h9 ;
default:smgL = 4'h0 ;
endcase
case( count/10)//顯示十位
4'h0 : smgH = 4'h0 ;
4'h1 : smgH = 4'h1 ;
4'h2 : smgH = 4'h2 ;
4'h3 : smgH = 4'h3 ;
4'h4 : smgH = 4'h4 ;
4'h5 : smgH = 4'h5 ;
4'h6 : smgH = 4'h6 ;
4'h7 : smgH = 4'h7 ;
4'h8 : smgH = 4'h8 ;
4'h9 : smgH = 4'h9 ;
default:smgL = 4'h0 ;
endcase
end
endmodule
//數(shù)字跑表單獨(dú)顯示
module dispczw(count,smg1,smg2);
input [6:0] count;
output reg[7:0] smg1,smg2;
always@( count )
begin
case( count%10 )
4'h0 : smg1 = 8'hc0 ;
4'h1 : smg1 = 8'hf9 ;
4'h2 : smg1 = 8'ha4 ;
4'h3 : smg1 = 8'hb0 ;
4'h4 : smg1 = 8'h99 ;
4'h5 : smg1 = 8'h92 ;
4'h6 : smg1 = 8'h82 ;
4'h7 : smg1 = 8'hf8 ;
4'h8 : smg1 = 8'h80 ;
4'h9 : smg1 = 8'h90 ;
endcase
case( count/10)
4'h0 : smg2 = 8'h40 ;
4'h1 : smg2 = 8'h79 ;
4'h2 : smg2 = 8'h24 ;
4'h3 : smg2 = 8'h30 ;
4'h4 : smg2 = 8'h19 ;
4'h5 : smg2 = 8'h12 ;
4'h6 : smg2 = 8'h02 ;
4'h7 : smg2 = 8'h78 ;
4'h8 : smg2 = 8'h00 ;
4'h9 : smg2 = 8'h10 ;
endcase
end
endmodule
上圖為數(shù)碼管顯示模塊在賦給相應(yīng)隨機(jī)真值情況下的仿真結(jié)果。可見數(shù)碼管高低四位與所賦真值相吻合。
//最終頂層例化程序
module FPGACLOCK(clk_in,clk_disp,k5,k6,k7,add2,add1,add0,beemp,load1,load2,load3,kstart_beemp,seg0,seg1,seg2,seg3,seg4,seg5);//頂層程序
input clk_in,add2,add1,add0,kstart_beemp;//時(shí)鐘輸入 設(shè)置時(shí)分秒(年月日,鬧鐘時(shí)分秒)的選擇位 手動(dòng)
input k5,k6,k7;//區(qū)別時(shí)分秒、年月日、鬧鐘設(shè)置的模式位選段
input load1,load2,load3;//三種模式的選擇觸發(fā)按鍵
output clk_disp,beemp;//顯示用的時(shí)鐘和蜂鳴器
output [3:0]seg0;
output [3:0]seg1;//2位數(shù)碼管1
output [3:0]seg2;
output [3:0]seg3;//2位數(shù)碼管2
output [3:0]seg4;
output [3:0]seg5;//2位數(shù)碼管3
//連線型變量,用于模塊間連線傳輸相應(yīng)變量數(shù)據(jù)
wire clk,sec_add,min_add,hour_add,day_add,mon_add,year_add,sec_beemp_add,min_beemp_add,hour_beeemp_add;
wire [7:0]sec_set;
wire [7:0]min_set;
wire [7:0]hour_set;
wire [7:0]day_set;
wire [7:0]mon_set;
wire [7:0]year_set;
wire [7:0]sec;
wire [7:0]min;
wire [7:0]hour;
wire [7:0]day;
wire [7:0]mon;
wire [7:0]year;
wire [7:0]hour_beemp;
wire [7:0]min_beemp;
wire [7:0]sec_beemp;
wire [7:0]count0;
wire [7:0]count1;
wire [7:0]count2;
wire [7:0]count3;
wire [7:0]count4;
fre_div u0 (clk_in,clk,clk_disp);//分頻器例化,敏感參數(shù)列表輸入輸出一一對(duì)應(yīng),下方以此類推
sfm u1 (clk,load1,sec_set,min_set,hour_set,sec,min,hour,clk_day);
sfmsz u2 (sec_add,min_add,hour_add,sec_set,min_set,hour_set);
nyr u3 (clk_day,load2,day_set,mon_set,year_set,day,mon,year);
nyrsz u4 (day_add,mon_add,year_add,day_set,mon_set,year_set);
sfm_beemp u5 (kstart_beemp,sec,min,hour,sec_beemp_add,min_beemp_add,hour_beeemp_add,sec_beemp,min_beemp,hour_beemp,beemp);
kongzhi_disp u6 (k5,k6,k7,hour,min,sec,hour_set,min_set,sec_set,year,mon,day,year_set,mon_set,day_set,hour_beemp,min_beemp,sec_beemp,count4,count3,count2,count1,count0);
kongzhi u7 (add2,add1,add0,k5,k6,k7,sec_add,min_add,hour_add,day_add,mon_add,year_add,sec_beemp_add,min_beemp_add,hour_beeemp_add);
disp u8 (count2,seg4,seg5);
disp u9 (count1,seg2,seg3);
disp u10 (count0,seg0,seg1);
mb u11 (clk_in,count3,count4,load3);
endmodule
上圖為各模塊例化結(jié)果,例化后系統(tǒng)總體仿真可以通過。(下圖以隨機(jī)信號(hào)輸入,觀察同一X軸坐標(biāo)為例,可判斷出不同賦值情況下數(shù)碼管的輸出狀態(tài)):
四、程序下載至FPGA實(shí)驗(yàn)箱的實(shí)際結(jié)果:
1、管腳約束情況:
2、實(shí)物演示效果:
上圖為計(jì)時(shí)器(時(shí)鐘)調(diào)整以及顯示模式工作情況(04時(shí)05分28-31秒)
上圖為日期調(diào)整以及日期顯示模式工作情況(21年12月08日)
上圖為數(shù)字跑表(精確至0.01秒)模式工作情況(00.00秒-04.26秒)
上圖為設(shè)置鬧鐘報(bào)時(shí)時(shí)間(6時(shí)19分05秒時(shí)鬧鈴)
上圖為設(shè)置計(jì)數(shù)器(時(shí)鐘)目前時(shí)間(當(dāng)前時(shí)刻:6時(shí)19分00秒)
上圖左(時(shí)刻:6時(shí)19分03秒)尚未達(dá)到鬧鐘設(shè)置時(shí)間,LED2不亮,鬧鐘不響。文章來源:http://www.zghlxwxcb.cn/news/detail-417014.html
上圖右(時(shí)刻:6時(shí)19分06秒)已經(jīng)達(dá)到鬧鐘設(shè)置時(shí)間,LED2亮,鬧鐘響。文章來源地址http://www.zghlxwxcb.cn/news/detail-417014.html
到了這里,關(guān)于數(shù)字系統(tǒng)設(shè)計(jì)(FPGA)課程設(shè)計(jì): 多功能數(shù)字鐘的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!