这篇文章通过VHDL代码实现数字钟的功能,绑定引脚就可以看到实际的效果。
//右下角坐标,如何改变时间尺度
module CLOCK1(
input clk , //50Mhz系统时钟
input add, //按下加一
input sub, //按下减一
input en, //确认
input out,
input [7:0] key,
input [3:0] type,
input countmode,
input rem_button,
input backcountkey,
input i_know_botton,
output reg [7:0] sel,//数码管位选(选择当前要显示的数码管)
output reg [7:0] seg//数码管段选(当前要显示的内容)
);
reg [31:0] cnt_clock;
reg [15:0] cnt_second=0; //秒计数
reg [15:0] cnt_minute=0; //分计数
reg [15:0] cnt_hour=0; //时计数
reg [15:0] second=0; //秒计数
reg [15:0] minute=0; //分计数
reg [15:0] hour=0; //时计数
reg [15:0] day=28; //天计数
reg [15:0] month=9; //月计数
reg [15:0] year=2021; //月计数
reg [31:0] divider_cnt;//25000-1
reg clk_1K;
reg [3:0] data_tmp;//数据缓存
reg [2:0] clk_1s;
reg[31:0] display;
reg data0=0;
reg [31:0] setnum=0;
reg [31:0] cnt_clock_half=0;
reg clk_half;
reg [31:0] cnt_n;
//产生一秒时钟信号开始
always@(posedge clk)
begin
if(cnt_clock == 31'd24999999)
begin
cnt_clock <= 15'd0;
end
else
begin
cnt_clock <= cnt_clock + 1'b1;
end
end
always@(posedge clk)
begin
if(cnt_clock == 31'd24999999)
clk_1s <= ~clk_1s;
else
clk_1s <= clk_1s;
end
//产生一秒时钟信号结束
//按键消抖模块开始
reg [3:0] keyval= 0;
parameter DURATION = 24'd50_000;
assign ken_enable = key[0] |key[1]|key[2] |key[3];
//always @(posedge clk) //按键的计数
//begin
// if(ken_enable == 1&&keyval==0)
// begin
// if(cnt_n == DURATION)
// begin
// cnt_n <= cnt_n;
// if(key[0])
// keyval=1;
// else if(key[1])
// keyval=2;
// else if(key[2])
// keyval=3;
// else if(key[3])
// keyval=4;
// end
// else
// cnt_n <= cnt_n + 1'b1;
// end
// else if(ken_enable == 0)
// begin
// cnt_n <= 16'b0;
// keyval=0;
// end
//
//end
//按键消抖模块结束
reg [3:0] keyval2=0;
//时间计算模块开始
//always@(posedge clk_1s)
reg [31:0] cnt1s = 0;
reg flag1s=0;
reg flag_stop=0;
reg last_backcountkey;
reg last_i_know_botton;
reg clock_time_arrflag=0;
always@(posedge clk)
begin
cnt1s=cnt1s+1;
if(cnt1s==49_999_999)
begin
cnt1s=0;
flag1s=1;
end
if(ken_enable == 1&&keyval==0)
begin
if(cnt_n == DURATION)
begin
cnt_n <= cnt_n;
if(key[0])
keyval=1;
else if(key[1])
keyval=2;
else if(key[2])
keyval=3;
else if(key[3])
keyval=4;
end
else
cnt_n <= cnt_n + 1'b1;
end
else if(ken_enable == 0)
begin
cnt_n <= 16'b0;
end
if(flag1s==1) //一秒钟后进入的模块
begin
flag1s=0;
if(type==6&&backcountkey==1)
begin
if(cnt_second==0)
begin
if(cnt_minute==0)
begin
if(cnt_hour>0)
begin
cnt_hour=cnt_hour-1;
cnt_minute=59;
cnt_second=59;
end
end
else
begin
cnt_minute=cnt_minute-1;
cnt_second=59;
end
end
else
cnt_second=cnt_second-1;
if(cnt_second==0&&cnt_minute==0&&cnt_hour==0)
flag_stop=1;
else
flag_stop=0;
end
second=second+1;
if(second==31'd60)
begin
second=0;
minute=minute+1;
end
if(minute==31'd60)
begin
minute=0;
hour=hour+1;
end
if(hour == 31'd24)
begin
hour=0;
day=day+1;
end
if(month == 31'd1) //1月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd2) //2月特殊处理
begin
if(year%4==0&&day==30)
begin
day=1;
month=month+1;
end
if(year%4!=0&&day==29)
begin
day=1;
month=month+1;
end
end
if(month == 31'd3) //3月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd4) //4月
begin
if(day == 31'd31)
begin
day=1;
month=month+1;
end
end
if(month == 31'd5) //5月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd6) //6月
begin
if(day == 31'd31)
begin
day=1;
month=month+1;
end
end
if(month == 31'd7) //7月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd8) //8月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd9) //9月
begin
if(day == 31'd31)
begin
day=1;
month=month+1;
end
end
if(month == 31'd10) //10月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd11) //11月
begin
if(day == 31'd31)
begin
day=1;
month=month+1;
end
end
if(month == 31'd12) //12月
begin
if(day == 31'd32)
begin
day=1;
month=month+1;
end
end
if(month == 31'd13)
begin
month=1;
year=year+1;
end
if(countmode==0&type!=5)
begin
count_dis_num=0;
end
//闹钟模式
if(alarm_s!=0||alarm_minute!=0||alarm_hour!=0)
begin
if(alarm_s==second&&alarm_minute==minute&&alarm_hour==hour)
begin
clock_time_arrflag=1;
end
end
if(i_know_botton!=last_i_know_botton)
begin
clock_time_arrflag=0;
end
last_i_know_botton=i_know_botton;
//闹钟模式
//按键控制加减部分
if(keyval==1)
begin
if(type==1||type==3||type==7||type==8)
begin
if(setnum==2)
setnum <= setnum;
else
setnum <= setnum+1;
end
if(type==5)
begin
if(count_dis_num==49)
count_dis_num <= count_dis_num;
else
count_dis_num <= count_dis_num+1;
end
end
else if(keyval==2)
begin
if(type==1||type==3||type==7||type==8)
begin
if(setnum==0)
setnum <= setnum;
else
setnum <= setnum-1;
end
if(type==5)
begin
if(count_dis_num==0)
count_dis_num <= count_dis_num;
else
count_dis_num <= count_dis_num-1;
end
end
else if(keyval==3)
begin
if(type==1)
begin
if(setnum==0) year=year+1;
if(setnum==1) month=month+1;
if(setnum==2) day=day+1;
end
if(type==3)
begin
if(setnum==0) hour=hour+1;
if(setnum==1) minute=minute+1;
if(setnum==2) second=second+1;
end
if(type==7)
begin
if(setnum==0) cnt_hour=cnt_hour+1;
if(setnum==1) cnt_minute=cnt_minute+1;
if(setnum==2) cnt_second=cnt_second+1;
end
if(type==8)
begin
if(setnum==0) alarm_hour=alarm_hour+1;
if(setnum==1) alarm_minute=alarm_minute+1;
if(setnum==2) alarm_s= alarm_s+1;
end
end
else if(keyval==4)
begin
if(type==1)
begin
if(setnum==0) year=year-1;
if(setnum==1) month=month-1;
if(setnum==2) day=day-1;
end
if(type==3)
begin
if(setnum==0) hour=hour-1;
if(setnum==1) minute=minute-1;
if(setnum==2) second=second-1;
end
if(type==7)
begin
if(setnum==0) cnt_hour=cnt_hour-1;
if(setnum==1) cnt_minute=cnt_minute-1;
if(setnum==2) cnt_second=cnt_second-1;
end
if(type==8)
begin
if(setnum==0) alarm_hour=alarm_hour-1;
if(setnum==1) alarm_minute=alarm_minute-1;
if(setnum==2) alarm_s= alarm_s-1;
end
end
keyval=0;
end
//按键控制加减结束
end
//时间计算模块结束
// 分频计数器计数模块
always@(posedge clk)
if(divider_cnt == 15'd24999)
divider_cnt <= 15'd0;
else
divider_cnt <= divider_cnt + 1'b1;
//1K扫描时钟生成模块
always@(posedge clk)
if(divider_cnt == 15'd24999)
clk_1K <= ~clk_1K;
else
clk_1K <= clk_1K;
//数码管位选模块
always@(posedge clk_1K)
if(sel == 8'b0111_1111)
sel <= 8'b1111_1110;
else sel = (sel << 1) | 8'b0000_0001;
//数码管段选
always@(sel)
case(sel)
8'b1111_1110:data_tmp = display[3:0];
8'b1111_1101:data_tmp = display[7:4];
8'b1111_1011:data_tmp = display[11:8];
8'b1111_0111:data_tmp = display[15:12];
8'b1110_1111:data_tmp = display[19:16];
8'b1101_1111:data_tmp = display[23:20];
8'b1011_1111:data_tmp = display[27:24];
8'b0111_1111:data_tmp = display[31:28];
default:data_tmp = data0;
endcase
always@(data_tmp)
case(data_tmp)
4'h0 : seg = ~8'b0011_1111; //显示"0"
4'h1 : seg = ~8'b0000_0110; //显示"1"
4'h2 : seg = ~8'b0101_1011; //显示"2"
4'h3 : seg = ~8'b0100_1111; //显示"3"
4'h4 : seg = ~8'b0110_0110; //显示"4"
4'h5 : seg = ~8'b0110_1101; //显示"5"
4'h6 : seg = ~8'b0111_1101; //显示"6"
4'h7 : seg = ~8'b0000_0111; //显示"7"
4'h8 : seg = ~8'b0111_1111; //显示"8"
4'h9 : seg = ~8'b0110_1111; //显示"9"
4'h10 : seg = ~8'b0011_1111; //显示"-"
default :seg = ~8'b0000_0000;
endcase
//数码管模块结束
//一秒时钟产生
always@(posedge clk)
begin
if(cnt_clock_half == 31'd24999999)
begin
cnt_clock_half <= 15'd0;
end
else
begin
cnt_clock_half <= cnt_clock_half + 1'b1;
end
end
always@(posedge clk)
begin
if(cnt_clock_half == 15'd24999999)
clk_half <= ~clk_half;
else
clk_half <= clk_half;
end
//一秒时钟结束
//年月日显示模块开始
always@(posedge clk)
begin
//模式0
if(type == 31'd0)
begin
display[31:28]=year/1000;
display[27:24]=year/100%10;
display[23:20]=year/10%10;
display[19:16]=year%10;
display[15:12]=month/10;
display[11:8]=month%10;
display[7:4]=day/10;
display[3:0]=day%10;
end
// display[31:28]=clk_half; //测试 使用
//模式1
if(type==31'd1&&clk_half==1)
begin
display[31:28]=year/1000;
display[27:24]=year/100%10;
display[23:20]=year/10%10;
display[19:16]=year%10;
display[15:12]=month/10;
display[11:8]=month%10;
display[7:4]=day/10;
display[3:0]=day%10;
end
if(type==31'd1&&clk_half==0&&setnum==0)
begin
display[31:28]=15'd11;
display[27:24]=15'd11;
display[23:20]=15'd11;
display[19:16]=15'd11;
display[15:12]=month/10;
display[11:8]=month%10;
display[7:4]=day/10;
display[3:0]=day%10;
end
if(type==31'd1&&clk_half==0&&setnum==1)
begin
display[31:28]=year/1000;
display[27:24]=year/100%10;
display[23:20]=year/10%10;
display[19:16]=year%10;
display[15:12]=15'd11;
display[11:8]=15'd11;
display[7:4]=day/10;
display[3:0]=day%10;
end
if(type==31'd1&&clk_half==0&&setnum==2)
begin
display[31:28]=year/1000;
display[27:24]=year/100%10;
display[23:20]=year/10%10;
display[19:16]=year%10;
display[15:12]=month/10;
display[11:8]=month%10;
display[7:4]=15'd11;
display[3:0]=15'd11;
end
//模式2
if(type == 31'd2&&clock_time_arrflag==0)
begin
display[31:28]=hour/10;
display[27:24]=hour%10;
display[23:20]=31'd10;
display[19:16]=minute/10;
display[15:12]=minute%10;
display[11:8]=31'd10;
display[7:4]=second/10;
display[3:0]=second%10;
end
//模式2
if(type == 31'd2&&clock_time_arrflag==1&&clk_half==0)
begin
display[31:28]= alarm_hour/10;
display[27:24]= alarm_hour%10;
display[23:20]=31'd10;
display[19:16]= alarm_minute/10;
display[15:12]= alarm_minute%10;
display[11:8]=31'd10;
display[7:4]= alarm_s/10;
display[3:0]= alarm_s%10;
end
//模式2
if(type == 31'd2&&clock_time_arrflag==1&&clk_half==1)
begin
display[31:28]=31'd10;
display[27:24]=31'd10;
display[23:20]=31'd10;
display[19:16]=31'd10;
display[15:12]=31'd10;;
display[11:8]=31'd10;
display[7:4]=31'd10;
display[3:0]=31'd10;
end
//模式3
if((type == 31'd3)&&clk_half==1) //模式0显示年月日
begin
display[31:28]=hour/10;
display[27:24]=hour%10;
display[23:20]=31'd10;
display[19:16]=minute/10;
display[15:12]=minute%10;
display[11:8]=31'd10;
display[7:4]=second/10;
display[3:0]=second%10;
end
if((type == 31'd3)&&clk_half==0&&setnum==0) //模式0显示年月日
begin
display[31:28]=15'd11;
display[27:24]=15'd11;
display[23:20]=31'd10;
display[19:16]=minute/10;
display[15:12]=minute%10;
display[11:8]=31'd10;
display[7:4]=second/10;
display[3:0]=second%10;
end
if((type == 31'd3)&&clk_half==0&&setnum==1) //模式0显示年月日
begin
display[31:28]=hour/10;
display[27:24]=hour%10;
display[23:20]=31'd10;
display[19:16]=15'd11;
display[15:12]=15'd11;
display[11:8]=31'd10;
display[7:4]=second/10;
display[3:0]=second%10;
end
if((type == 31'd3)&&clk_half==0&&setnum==2) //模式0显示年月日
begin
display[31:28]=hour/10;
display[27:24]=hour%10;
display[23:20]=31'd10;
display[19:16]=minute/10;
display[15:12]=minute%10;
display[11:8]=31'd10;
display[7:4]=15'd11;
display[3:0]=15'd11;
end
//模式4
if(type == 31'd4) //模式0显示年月日
begin
display[31:28]=timer_minute/10;
display[27:24]=timer_minute%10;
display[23:20]=31'd10;
display[19:16]=timer_s/10;
display[15:12]=timer_s%10;
display[11:8]=31'd10;
display[7:4]=timer_decimal/10;
display[3:0]=timer_decimal/10;
end
//模式5
if(type == 31'd5) //模式0显示年月日
begin
display[31:28]=count_dis_num%10;
display[23:20]=31'd10;
display[19:16]=rem_timer_s[count_dis_num]/10;
display[15:12]=rem_timer_s[count_dis_num]%10;
display[11:8]=31'd10;
display[7:4]=rem_timer_decimal[count_dis_num]/10;
display[3:0]=rem_timer_decimal[count_dis_num]/10;
end
if(type == 31'd6)
begin
display[31:28]=cnt_hour/10;
display[27:24]=cnt_hour%10;
display[23:20]=31'd10;
display[19:16]=cnt_minute/10;
display[15:12]=cnt_minute%10;
display[11:8]=31'd10;
display[7:4]=cnt_second/10;
display[3:0]=cnt_second%10;
end
//模式7
if((type == 31'd7)&&clk_half==1) //模式0显示年月日
begin
display[31:28]=cnt_hour/10;
display[27:24]=cnt_hour%10;
display[23:20]=31'd10;
display[19:16]=cnt_minute/10;
display[15:12]=cnt_minute%10;
display[11:8]=31'd10;
display[7:4]=cnt_second/10;
display[3:0]=cnt_second%10;
end
if((type == 31'd7)&&clk_half==0&&setnum==0) //模式0显示年月日
begin
display[31:28]=15'd11;
display[27:24]=15'd11;
display[23:20]=31'd10;
display[19:16]=cnt_minute/10;
display[15:12]=cnt_minute%10;
display[11:8]=31'd10;
display[7:4]=cnt_second/10;
display[3:0]=cnt_second%10;
end
if((type == 31'd7)&&clk_half==0&&setnum==1) //设置倒计时
begin
display[31:28]=cnt_hour/10;
display[27:24]=cnt_hour%10;
display[23:20]=31'd10;
display[19:16]=15'd11;
display[15:12]=15'd11;
display[11:8]=31'd10;
display[7:4]=cnt_second/10;
display[3:0]=cnt_second%10;
end
if((type == 31'd7)&&clk_half==0&&setnum==2) //模式0显示年月日
begin
display[31:28]=cnt_hour/10;
display[27:24]=cnt_hour%10;
display[23:20]=31'd10;
display[19:16]=cnt_minute/10;
display[15:12]=cnt_minute%10;
display[11:8]=31'd10;
display[7:4]=15'd11;
display[3:0]=15'd11;
end
//模式八
if(type == 31'd8)
begin
display[31:28]=alarm_hour/10;
display[27:24]=alarm_hour%10;
display[23:20]=31'd10;
display[19:16]= alarm_minute/10;
display[15:12]= alarm_minute%10;
display[11:8]=31'd10;
display[7:4]= alarm_s/10;
display[3:0]= alarm_s%10;
end
if((type == 31'd8)&&clk_half==0&&setnum==0) //模式0显示年月日
begin
display[31:28]=15'd11;
display[27:24]=15'd11;
display[23:20]=31'd10;
display[19:16]=alarm_minute/10;
display[15:12]=alarm_minute%10;
display[11:8]=31'd10;
display[7:4]=alarm_s/10;
display[3:0]=alarm_s%10;
end
if((type == 31'd8)&&clk_half==0&&setnum==1) //设置倒计时
begin
display[31:28]=alarm_hour/10;
display[27:24]=alarm_hour%10;
display[23:20]=31'd10;
display[19:16]=15'd11;
display[15:12]=15'd11;
display[11:8]=31'd10;
display[7:4]=alarm_s/10;
display[3:0]=alarm_s%10;
end
if((type == 31'd8)&&clk_half==0&&setnum==2) //模式0显示年月日
begin
display[31:28]=alarm_hour/10;
display[27:24]=alarm_hour%10;
display[23:20]=31'd10;
display[19:16]=alarm_minute/10;
display[15:12]=alarm_minute%10;
display[11:8]=31'd10;
display[7:4]=15'd11;
display[3:0]=15'd11;
end
end
//年月日显示模块结束
//拓展模块秒表开始
reg [31:0] timer_cnt;
reg [31:0] timer_basic;
reg [31:0] timer_decimal;
reg [31:0] timer_s;
reg [31:0] timer_minute;
reg [31:0] timer_hour;
reg [7:0] count_dis_num=0;
reg last_rem_button;
reg [6:0] i;
reg [6:0] rem_timer_number=0;
reg [31:0] rem_timer_decimal [0:50];
reg [31:0] rem_timer_s [0:50];
reg [31:0] rem_timer_minute [0:50];
reg [31:0] rem_timer_hour [0:50];
always@(posedge clk)
begin
if(timer_cnt == 31'd249999)
begin
timer_cnt <= 15'd0;
end
else
begin
timer_cnt <= timer_cnt + 1'b1;
end
end
always@(posedge clk)
begin
if(timer_cnt == 31'd249999)
timer_basic <= ~timer_basic;
else
timer_basic <= timer_basic;
end
always@(posedge timer_basic)
begin
timer_decimal=timer_decimal+1;
if(timer_decimal==31'd100) //百分秒
begin
timer_decimal=0;
timer_s=timer_s+1;
end
if(timer_s==31'd60) //秒
begin
timer_s=0;
timer_minute=timer_minute+1;
end
if(timer_minute==31'd60) //分
begin
timer_minute=0;
timer_hour=timer_hour+1;
end
if(timer_hour==31'd24) //时
begin
timer_hour=0;
end
if(countmode==0&type!=5)
begin
timer_decimal=0;
timer_s=0;
timer_minute=0;
timer_hour=0;
rem_timer_number=0;
end
if(rem_button!=last_rem_button) //计时寄存器记录
begin
rem_timer_decimal[rem_timer_number]=timer_decimal;
rem_timer_s[rem_timer_number]=timer_s;
rem_timer_minute[rem_timer_number]=timer_minute;
rem_timer_hour[rem_timer_number]= timer_hour;
rem_timer_decimal[rem_timer_number+1]=0;
rem_timer_s[rem_timer_number+1]=0;
rem_timer_minute[rem_timer_number+1]=0;
rem_timer_hour[rem_timer_number+1]= 0;
rem_timer_decimal[rem_timer_number+2]=0;
rem_timer_s[rem_timer_number+2]=0;
rem_timer_minute[rem_timer_number+2]=0;
rem_timer_hour[rem_timer_number+2]= 0;
rem_timer_number=rem_timer_number+1;
end
last_rem_button=rem_button;
end
//拓展模块秒表开始
reg [31:0] alarm_cnt;
reg [31:0] alarm_basic;
reg [31:0] alarm_decimal;
reg [31:0] alarm_s;
reg [31:0] alarm_minute;
reg [31:0] alarm_hour;
//拓展模块闹钟开始
//拓展模块闹钟结束
endmodule
代码运行成功,就可以实现了计时(年月日/时分秒)、秒表、倒计时、闹钟的全部功能。