实际要求:
设计二0.01秒~1小时的秒表设计
1、设计一个能显示0.01秒~1小时的秒表。
2、具有启动/停止按键和清零按键。
3、利用GW48-PK2中提提供的3MHz信号做为时钟信号。
4、计数结果在GW48-PK2中提供的数码管中显示。
功能实现:
基本功能:
1、设计一个能显示0.01秒~1小时的秒表。
2、具有启动/停止按键和清零按键。
3、利用GW48-PK2中提提供的3MHz信号做为时钟信号。
4、计数结果在GW48-PK2中提供的数码管中显示。
提高功能:
5.计时时间在0.01秒~24小时范围内
6.增加了一个功能按键,可以在单道和双道模式之间切换
7.可以双道计时,
8.在双道模式显示时,可以切换两道的计时结果
程序思路:
本程序的输入为三个按键,分别为功能按键(SW1)、启动停止按键(SW2)
和清零按键(SW3);输出为八位数码管的时间显示,分别显示小时、分钟、秒
和百分秒。
本程序有两个模式:单道模式(mode0)和双道模式(mode1)。
单道模式(mode0):按SW2按键时,启动秒表计时,以后每按一次秒表就
在启动和停止之间切换,同时数码管会显示计时器中的数值;当按下SW3键时,
计数器和显示都清零,并且停止计数。
双道模式(mode1):在单道模式(mode0)下按一次SW1键就切换到双道
模式(mode1)。在双道模式(mode1)下,第一次按SW2按键时,启动秒表计
时;第二次按SW2按键时,其中一道结束计时,并把此时的时间按存储起来,
同时秒表还在继续计时;第三次按SW2按键时,秒表停止计时,并把此时的时
间存储起来,表示另一道结束;以后每按一次SW2按键数码管输出显示就在两
道计时结果之间切换;按下SW3键时计数器清零,数码管显示清零;此时按下
SW1键可以切换到单道模式(mode0)。
本程序将各个功能单元用不同的模块写出来,一共有个模块,分别是顶层模
块、分频模块、模式转换模块、按键处理模块、时间计数主模块(包括小时计时
模块、分钟计时模块、秒计时模块和百分秒计时模块)、单双道时间数据选择模
块、时间显示数据选择模块和模式输出显示模块。
各个模块的详细功能已在程序中注释。
程序实现:
//顶层模块
//用于连接各个底层模块
modulestopwatch_mode2(clk_3M,SW1,SW2,SW3,
disp_ms_l,disp_ms_h,
disp_c_l,disp_c_h,
disp_min_l,disp_min_h,
disp_hour_l,disp_hour_h,
mode_out);
inputclk_3M;//系统时钟
inputSW1,SW2,SW3;//按键
outputmode_out;//模式输出,用于模式显示
output[3:0]disp_ms_l,disp_ms_h;//输出至数码管显示
output[3:0]disp_c_l,disp_c_h;
output[3:0]disp_min_l,disp_min_h;
output[3:0]disp_hour_l,disp_hour_h;
wireclk_3M;
wireSW1,SW2,SW3;
wireclk_100;
wiretime_EN;
wiremode;
wire[3:0]ms_l,ms_h,c_l,c_h,min_l,min_h,hour_l,hour_h;
wire[3:0]ms_l_0,ms_h_0,c_l_0,c_h_0,min_l_0,min_h_0,hour_l_0,hour_h_0;
wire[3:0]ms_l_1,ms_h_1,c_l_1,c_h_1,min_l_1,min_h_1,hour_l_1,hour_h_1;
wire[3:0]disp_ms_l,disp_ms_h,disp_c_l,disp_c_h,
disp_min_l,disp_min_h,disp_hour_l,disp_hour_h;
wireflag_ds;
wireflag_st0;
wireflag_st1;
//分频模块,把3MHZ的时钟分频为100HZ用于计数器计数
f_divm1(.clk_3M(clk_3M),
.clr(SW3),
.clk_100(clk_100));
//模式转换模块
maincontrolm2(.SW1(SW1),.mode(mode));
//按键处理模块
SW_ctrlm3(.mode(mode),
.clr(SW3),.SW_2(SW2),.flag_st(time_EN),
.flag_ds(flag_ds),.flag_st0(flag_st0),.flag_st1(flag_st1));
//时间计数主模块
time_counter_mainm4(.clk_100(clk_100),.clr(SW3),.time_EN(time_EN),
.ms_l(ms_l),.ms_h(ms_h),.c_l(c_l),.c_h(c_h),
.min_l(min_l),.min_h(min_h),.hour_l(hour_l),.hour_h(hour_h));
//单双道时间数据选择模块
doublem5(.mode(mode),.flag_st0(flag_st0),.flag_st1(flag_st1),
.ms_l(ms_l),.ms_h(ms_h),.c_l(c_l),.c_h(c_h),
.min_l(min_l),.min_h(min_h),.hour_l(hour_l),.hour_h(hour_h),
.ms_l_0(ms_l_0),.ms_h_0(ms_h_0),.c_l_0(c_l_0),.c_h_0(c_h_0),
.min_l_0(min_l_0),.min_h_0(min_h_0),.hour_l_0(hour_l_0),.hour_h_0(hour_h_0),
.ms_l_1(ms_l_1),.ms_h_1(ms_h_1),.c_l_1(c_l_1),.c_h_1(c_h_1),
.min_l_1(min_l_1),.min_h_1(min_h_1),.hour_l_1(hour_l_1),.hour_h_1(hour_h_1));
//时间显示数据选择模块
disp_muxm6(.mode(mode),.flag_ds(flag_ds),.ms_l_0(ms_l_0),.ms_h_0(ms_h_0),
.c_l_0(c_l_0),.c_h_0(c_h_0),.min_l_0(min_l_0),
.min_h_0(min_h_0),.hour_l_0(hour_l_0),.hour_h_0(hour_h_0),
.ms_l_1(ms_l_1),.ms_h_1(ms_h_1),.c_l_1(c_l_1),.c_h_1(c_h_1),
.min_l_1(min_l_1),.min_h_1(min_h_1),.hour_l_1(hour_l_1),.hour_h_1(hour_h_1),
.disp_ms_l(disp_ms_l),.disp_ms_h(disp_ms_h),.disp_c_l(disp_c_l),
.disp_c_h(disp_c_h),.disp_min_l(disp_min_l),
.disp_min_h(disp_min_h),.disp_hour_l(disp_hour_l),.disp_hour_h(disp_hour_h));
//模式输出显示模块
mode_outputm7(.mode(mode),.mode_out(mode_out));
endmodule
//********************************************************************
//分频模块
//用计数器实现分频
//把3MHZ的时钟分频为100HZ用于计数器计数输入
modulef_div(clk_3M,clr,clk_100);
inputclk_3M;
inputclr;
outputclk_100;
regclk_100;
reg[14:0]cnt_div;
always@(podgeclk_3M)begin
if(clr)begin
clk_100<=1'b0;
cnt_div<=14'b0;
end
elif(cnt_div==15000)begin
clk_100<=1'b0;
cnt_div<=cnt_div+15'b00_0000_0000_0001;
end
elif(cnt_div==30000)begin
clk_100<=1'b1;
cnt_div<=15'b0;
end
elbegin
cnt_div<=cnt_div+15'b00_0000_0000_0001;
end
end
endmodule
//********************************************************************
//模式转换模块
//本程序一共有两个模式,分别是单道计时和双道计时
//每按一次SW1键就切换一次模式
modulemaincontrol(SW1,mode);
inputSW1;
outputmode;
regmode;
always@(podgeSW1)
begin
if(mode==1'b1)
mode<=1'b0;
el
mode<=1'b1;
end
endmodule
//********************************************************************
//按键处理模块
//接收按键,输出标志位
//通过标志位实现双道时的开始计时、停止计时和双道计时结果的显示
moduleSW_ctrl(mode,clr,SW_2,flag_st,flag_ds,flag_st0,flag_st1);
inputmode;
inputSW_2;
inputclr;
outputflag_st;//flag_st=1,start;flag_st=0,stop;
outputflag_ds;//flag_clr=1,clear;flag_clr=0,noaction;
outputflag_st0,flag_st1;//单双道停止控制标志位
regflag_st,flag_ds;
reg[1:0]flag_one;//双道模式时用于记忆SW2按键的次数
regflag_st0,flag_st1;
always@(podgeSW_2orpodgeclr)
begin
if(clr)
begin
flag_st<=1'b0;flag_st0<=1'b0;flag_st1<=1'b0;
flag_one<=2'b0;flag_ds<=1'b0;
end
elca(mode)
1'b0:
begin
flag_st<=~flag_st;flag_ds<=1'b0;
end
1'b1:
begin
ca(flag_one)
2'b00:
begin
flag_st<=1'b1;flag_one<=flag_one+2'b01;
flag_ds<=1'b0;
end
2'b01:
begin
flag_st1<=1'b1;//1daostop
flag_one<=flag_one+2'b01;flag_ds<=1'b0;
end
2'b10:
begin
flag_st0<=1'b1;//0daostop
flag_one<=flag_one+2'b01;flag_ds<=1'b0;
end
2'b11:
begin
flag_one<=flag_one;flag_ds<=~flag_ds;
end
endca
if(flag_st0||flag_st1)flag_st<=1'b0;
end
default:
begin
flag_st<=1'b0;flag_ds<=1'b0;
end
endca
end
endmodule
//********************************************************************
//时间计数主模块
//用于计时,可以通过time_EN控制启停
//底层四个计时模块为串行方式相连,百分秒、秒和分钟计时单个子模块各有一
//个EO计数溢出标志,当本模块记满时会输出一个正脉冲给下一个模块使
//下一个模块计数加一,其他以此类推
module
time_counter_main(clk_100,clr,time_EN,ms_l,ms_h,c_l,c_h,min_l,min_h,hour_l,
hour_h);
inputclk_100;
inputclr;
inputtime_EN;
output[3:0]ms_l,ms_h;
output[3:0]c_l,c_h;
output[3:0]min_l,min_h;
output[3:0]hour_l,hour_h;
wirems_EO;
wirec_EO;
wiremin_EO;
ms_counteri1(.clk(clk_100),.clr(clr),.EN(time_EN),.EO(ms_EO),
.ms_l(ms_l),.ms_h(ms_h));
c_counteri2(.clk(ms_EO),.clr(clr),.EN(time_EN),.EO(c_EO),
.c_l(c_l),.c_h(c_h));
min_counteri3(.clk(c_EO),.clr(clr),.EN(time_EN),.EO(min_EO),
.min_l(min_l),.min_h(min_h));
hour_counteri4(.clk(min_EO),.clr(clr),.EN(time_EN),
.hour_l(hour_l),.hour_h(hour_h));
endmodule
//********************************************************************
//百分秒计时模块
modulems_counter(EN,clk,clr,ms_h,ms_l,EO);
inputclk,clr,EN;
output[3:0]ms_h;
output[3:0]ms_l;
outputEO;
reg[3:0]ms_h;
reg[3:0]ms_l;
regEO;
always@(podgeclkorpodgeclr)
begin
if(clr)
begin
ms_h<=4'b0;ms_l<=4'b0;EO<=1'b0;
end
el
begin
if(EN==1'b1)
begin
if(ms_l<4'b1001)
begin
ms_l<=ms_l+4'b0001;
end
el
begin
EO<=1'b0;ms_l<=4'b0;
if(ms_h<4'b1001)
ms_h<=ms_h+4'b1;
el
begin
ms_h<=4'b0;EO<=1'b1;
end
end
end
end
end
endmodule
//********************************************************************
//秒计时模块
modulec_counter(EN,clk,clr,c_h,c_l,EO);
inputclk,clr,EN;
output[3:0]c_h;
output[3:0]c_l;
outputEO;
reg[3:0]c_h;
reg[3:0]c_l;
regEO;
always@(podgeclkorpodgeclr)
begin
if(clr)
begin
c_h<=4'b0;c_l<=4'b0;EO<=1'b0;
end
el
begin
if(EN==1'b1)
begin
if(c_l<4'b1001)
begin
c_l<=c_l+4'b0001;
end
el
begin
EO<=1'b0;c_l<=4'b0;
if(c_h<4'b0101)
c_h<=c_h+4'b1;
el
begin
c_h<=4'b0;EO<=1'b1;
end
end
end
end
end
endmodule
//********************************************************************
//分钟计时模块
modulemin_counter(EN,clk,clr,min_h,min_l,EO);
inputclk,clr,EN;
output[3:0]min_h;
output[3:0]min_l;
outputEO;
reg[3:0]min_h;
reg[3:0]min_l;
regEO;
always@(podgeclkorpodgeclr)
begin
if(clr)
begin
min_h<=4'b0;min_l<=4'b0;EO<=1'b0;
end
el
begin
if(EN==1'b1)
begin
if(min_l<4'b1001)
begin
min_l<=min_l+4'b0001;
end
el
begin
EO<=1'b0;min_l<=4'b0;
if(min_h<4'b0101)
min_h<=min_h+4'b1;
el
begin
min_h<=4'b0;EO<=1'b1;
end
end
end
end
end
endmodule
//********************************************************************
//小时计时模块
modulehour_counter(EN,clk,clr,hour_h,hour_l);
inputclk,clr,EN;
output[3:0]hour_h;
output[3:0]hour_l;
reg[3:0]hour_h;
reg[3:0]hour_l;
always@(podgeclkorpodgeclr)
begin
if(clr)
begin
hour_h<=4'b0;hour_l<=4'b0;
end
el
begin
if(EN==1'b1)
begin
if((hour_l<4'b1001)&&(hour_h<4'b0010))
hour_l<=hour_l+4'b0001;
elif((hour_l<4'b0011)&&(hour_h==4'b0010))
hour_l<=hour_l+4'b0001;
el
begin
hour_l<=4'b0;
if(hour_h<4'b0010)
hour_h<=hour_h+4'b0001;
el
begin
hour_h<=4'b0;
end
end
end
end
end
endmodule
//********************************************************************
//单双道时间数据选择模块
//输入为计时主模块的输出,输出为单双道时间的数据
//根据mode,flag_st0,flag_st1输入来判断单双道计时存储
moduledouble(mode,flag_st0,flag_st1,ms_l,ms_h,c_l,c_h,
min_l,min_h,hour_l,hour_h,ms_l_0,ms_h_0,c_l_0,c_h_0,
min_l_0,min_h_0,hour_l_0,hour_h_0,
ms_l_1,ms_h_1,c_l_1,c_h_1,
min_l_1,min_h_1,hour_l_1,hour_h_1);
input[3:0]ms_l,ms_h;
input[3:0]c_l,c_h;
input[3:0]min_l,min_h;
input[3:0]hour_l,hour_h;
inputflag_st0,flag_st1;
inputmode;
output[3:0]ms_l_0,ms_h_0;
output[3:0]c_l_0,c_h_0;
output[3:0]min_l_0,min_h_0;
output[3:0]hour_l_0,hour_h_0;
output[3:0]ms_l_1,ms_h_1;
output[3:0]c_l_1,c_h_1;
output[3:0]min_l_1,min_h_1;
output[3:0]hour_l_1,hour_h_1;
reg[3:0]ms_l_0,ms_h_0;//0daoflag_ds=0;
reg[3:0]c_l_0,c_h_0;
reg[3:0]min_l_0,min_h_0;
reg[3:0]hour_l_0,hour_h_0;
reg[3:0]ms_l_1,ms_h_1;//1daoflag_ds=1;
reg[3:0]c_l_1,c_h_1;
reg[3:0]min_l_1,min_h_1;
reg[3:0]hour_l_1,hour_h_1;
always@(*)
begin
ca(mode)
1'b0:
begin
ms_l_0<=ms_l;ms_h_0<=ms_h;
c_l_0<=c_l;c_h_0<=c_h;
min_l_0<=min_l;min_h_0<=min_h;
hour_l_0<=hour_l;hour_h_0<=hour_h;
ms_l_1<=4'b0;ms_h_1<=4'b0;
c_l_1<=4'b0;c_h_1<=4'b0;
min_l_1<=4'b0;min_h_1<=4'b0;
hour_l_1<=4'b0;hour_h_1<=4'b0;
end
1'b1:
begin
ca({flag_st0,flag_st1})
2'b00:
begin
ms_l_0<=ms_l;ms_h_0<=ms_h;
c_l_0<=c_l;c_h_0<=c_h;
min_l_0<=min_l;min_h_0<=min_h;
hour_l_0<=hour_l;hour_h_0<=hour_h;
ms_l_1<=ms_l;ms_h_1<=ms_h;
c_l_1<=c_l;c_h_1<=c_h;
min_l_1<=min_l;min_h_1<=min_h;
hour_l_1<=hour_l;hour_h_1<=hour_h;
end
2'b01:
begin
ms_l_0<=ms_l;ms_h_0<=ms_h;
c_l_0<=c_l;c_h_0<=c_h;
min_l_0<=min_l;min_h_0<=min_h;
hour_l_0<=hour_l;hour_h_0<=hour_h;
ms_l_1<=ms_l_1;ms_h_1<=ms_h_1;
c_l_1<=c_l_1;c_h_1<=c_h_1;
min_l_1<=min_l_1;min_h_1<=min_h_1;
hour_l_1<=hour_l_1;hour_h_1<=hour_h_1;
end
2'b10:
begin
ms_l_0<=ms_l_0;ms_h_0<=ms_h_0;
c_l_0<=c_l_0;c_h_0<=c_h_0;
min_l_0<=min_l_0;min_h_0<=min_h_0;
hour_l_0<=hour_l_0;hour_h_0<=hour_h_0;
ms_l_1<=ms_l;ms_h_1<=ms_h;
c_l_1<=c_l;c_h_1<=c_h;
min_l_1<=min_l;min_h_1<=min_h;
hour_l_1<=hour_l;hour_h_1<=hour_h;
end
2'b11:
begin
ms_l_0<=ms_l_0;ms_h_0<=ms_h_0;
c_l_0<=c_l_0;c_h_0<=c_h_0;
min_l_0<=min_l_0;min_h_0<=min_h_0;
hour_l_0<=hour_l_0;hour_h_0<=hour_h_0;
ms_l_1<=ms_l_1;ms_h_1<=ms_h_1;
c_l_1<=c_l_1;c_h_1<=c_h_1;
min_l_1<=min_l_1;min_h_1<=min_h_1;
hour_l_1<=hour_l_1;hour_h_1<=hour_h_1;
end
endca
end
endca
end
endmodule
//********************************************************************
//时间显示数据选择模块
//选择输出显示的数据,主要用于双道切换模式
//根据SW_ctrl模块的输出标志flag_ds来判断是单道计时输出还是双道计时输出
//flag_ds=0时,是单道输出
//flag_ds=1时,是双道中的另一个道输出
moduledisp_mux(mode,flag_ds,ms_l_0,ms_h_0,c_l_0,c_h_0,//mode0
min_l_0,min_h_0,hour_l_0,hour_h_0,
ms_l_1,ms_h_1,c_l_1,c_h_1,//mode1(sdao)
min_l_1,min_h_1,hour_l_1,hour_h_1,
disp_ms_l,disp_ms_h,disp_c_l,disp_c_h,
disp_min_l,disp_min_h,disp_hour_l,disp_hour_h);
inputflag_ds;
inputmode;
input[3:0]ms_l_0,ms_h_0;
input[3:0]c_l_0,c_h_0;
input[3:0]min_l_0,min_h_0;
input[3:0]hour_l_0,hour_h_0;
input[3:0]ms_l_1,ms_h_1;
input[3:0]c_l_1,c_h_1;
input[3:0]min_l_1,min_h_1;
input[3:0]hour_l_1,hour_h_1;
output[3:0]disp_ms_l,disp_ms_h;
output[3:0]disp_c_l,disp_c_h;
output[3:0]disp_min_l,disp_min_h;
output[3:0]disp_hour_l,disp_hour_h;
reg[3:0]ms_ll,ms_hh;
reg[3:0]c_ll,c_hh;
reg[3:0]min_ll,min_hh;
reg[3:0]hour_ll,hour_hh;
assigndisp_ms_l=ms_ll;
assigndisp_ms_h=ms_hh;
assigndisp_c_l=c_ll;
assigndisp_c_h=c_hh;
assigndisp_min_l=min_ll;
assigndisp_min_h=min_hh;
assigndisp_hour_l=hour_ll;
assigndisp_hour_h=hour_hh;
always@(*)
begin
ca(mode)
1'b0:
begin
ms_ll=ms_l_0;ms_hh=ms_h_0;
c_ll=c_l_0;c_hh=c_h_0;
min_ll=min_l_0;min_hh=min_h_0;
hour_ll=hour_l_0;hour_hh=hour_h_0;
end
1'b1:
begin
if(flag_ds==1'b1)
begin
ms_ll=ms_l_1;ms_hh=ms_h_1;
c_ll=c_l_1;c_hh=c_h_1;
min_ll=min_l_1;min_hh=min_h_1;
hour_ll=hour_l_1;hour_hh=hour_h_1;
end
el
begin
ms_ll=ms_l_0;ms_hh=ms_h_0;
c_ll=c_l_0;c_hh=c_h_0;
min_ll=min_l_0;min_hh=min_h_0;
hour_ll=hour_l_0;hour_hh=hour_h_0;
end
end
endca
end
endmodule
//********************************************************************
//模式输出显示模块
//用于显示当前的模式状态,输出连接到LED灯,灯灭为单道模式(mode0)
//灯亮为双道模式(mode1)
modulemode_output(mode,mode_out);
inputmode;
outputmode_out;
assignmode_out=mode;
endmodule
本文发布于:2022-12-29 02:15:08,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/50478.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |