数字时钟
程序员文章站
2022-03-26 17:22:50
...
//时钟调校及正常计时模块
myclock.v文件
module myclock(RSTn,CLK,FLAG,UP,DN,Y,Mon,D,H,M,S,MS);
input RSTn,CLK,UP,DN;
output [7:0] H,M,S;
output [7:0] Mon,D;
output [15:0] Y;
output [7:0] MS;
input[2:0] FLAG;
reg [5:0] m_H,m_M,m_S;
reg [5:0] m_Mon,m_D;
reg [6:0] m_MS;
reg [15:0] m_Y;
assign H=m_H;
assign M=m_M;
assign S=m_S;
assign MS=m_MS;
assign Y=m_Y;
assign Mon=m_Mon;
assign D=m_D;
always @(posedge CLK)
if(~RSTn) //复位状态
begin
m_H<=8'b00000000;
m_M<=8'b00000000;
m_S<=8'b00000000;
m_MS<=8'b00000000;
m_Y<=16'h07e3;//16'h07e3;
m_Mon<=8'b00000001;
m_D<=8'b00000001;
end
else if(FLAG==3'b001) //001调时状态
begin
if(UP)
begin
m_H <= m_H + 1'b1;
if(m_H==8'd23)
m_H<=8'd0;
end
else if(DN)
begin
m_H<=m_H-1'b1;
if(m_H==8'd0)
m_H<=8'd23;
end
end
else if(FLAG==3'b010) //010调分状态
begin
if(UP)
begin
m_M<=m_M+1'b1;
if(m_M==8'd59)
m_M<=8'd0;
end
else if(DN)
begin
m_M<=m_M-1'b1;
if(m_M==8'd0)
m_M<=8'd59;
end
end
else if(FLAG==3'b011) //011调秒状态
begin
if(UP)
begin
m_S<=m_S+1'b1;
if(m_S==8'd59)
m_S<=8'd0;
end
else if(DN)
begin
m_S<=m_S-1'b1;
if(m_S==8'd0)
m_S<=8'd59;
end
end
else if(FLAG==3'b000)
begin
m_MS<=m_MS+1'b1; //000正常计时状态
if(m_MS==8'd100)
begin
m_MS<=8'd0;
m_S<=m_S+1'b1;
end
if(m_S==8'd60)
begin
m_S<=8'd0;
m_M<=m_M+8'd1;
end
if(m_M==8'd60)
begin
m_M<=8'd0;
m_H<=m_H+1'b1;
end
if(m_H==8'd24)
begin
m_H<=8'd0;
m_D<=m_D+1'b1;
end
if((m_Mon==8'd1)||(m_Mon==8'd3)||(m_Mon==8'd5)||(m_Mon==8'd7)||(m_Mon==8'd8)||(m_Mon==8'd10)||(m_Mon==8'd12))//big month
begin
if(m_D==8'd31)
begin
m_D<=8'd1;
m_Mon<=m_Mon+1'b1;
end
end
if((m_Mon==8'd4)||(m_Mon==8'd6)||(m_Mon==8'd9)||(m_Mon==8'd11))//small month
begin
if(m_D==8'd30)
begin
m_D<=8'd1;
m_Mon<=m_Mon+1'b1;
end
end
if(m_Mon==2) //run month
begin
if((m_Y%4==0)&&(m_Y%100!=0)||(m_Y%400==0))//year of RUN has 29days
begin
if(m_D==8'd29)
begin
m_D<=8'd1;
m_Mon<=m_Mon+1'b1;
end
end
else
begin
if(m_D==8'd28)//normal year has 28days
begin
m_D<=8'd1;
m_Mon<=m_Mon+1'b1;
end
end
end
if(m_Mon==8'd12)
begin
m_Mon<=8'd1;
m_Y<=m_Y+1'b1;
end
end
else if(FLAG==3'b100) //100adjust years
begin
if(UP)
begin
m_Y <= m_Y + 1'b1;
end
else if(DN)
begin
m_Y<=m_Y-1'b1;
end
end
else if(FLAG==3'b101)//101adjust month
begin
if(UP)
begin
m_Mon<=m_Mon + 1'b1;
if(m_Mon==8'd12)
m_Mon<=8'd1;
end
else if(DN)
begin
m_Mon<=m_Mon-1'b1;
if(m_Mon==8'd1)
m_Mon<=8'd12;
end
end
else if(FLAG==3'b110) //110adjust day
begin
if(UP)
begin
m_D<=m_D+1'b1;
if(m_D==8'd31)
m_D<=1;
end
else if(DN)
begin
m_D<=m_D-1'b1;
if(m_D==8'd1)
m_D<=8'd31;
end
end
Endmodule
//闹钟定时模块
myalarm.v文件
module myalarm(reset,CLK,con,UP,DN,yue,ri,shi,fen);
input reset,CLK,UP,DN;
input[2:0] con;
output [7:0] yue,ri,shi,fen;
reg [5:0] n_yue,n_ri,n_shi,n_fen;
assign yue=n_yue;
assign ri=n_ri;
assign shi=n_shi;
assign fen=n_fen;
always @(posedge CLK)
if(~reset) //复位状态
begin
n_yue<=8'b00000000;
n_ri<=8'b00000000;
n_shi<=8'b00000000;
n_fen<=8'b00000000;
end
else if(con==3'b100)
begin
if(UP)
begin
n_yue <= n_yue + 1'b1;
if(n_yue==8'd12)
n_yue<=8'd1;
end
else if(DN)
begin
n_yue<=n_yue-1'b1;
if(n_yue==8'd1)
n_yue<=8'd12;
end
end
else if(con==3'b101)
begin
if(UP)
begin
n_ri <= n_ri + 1'b1;
if(n_ri==8'd31)
n_ri<=8'd1;
end
else if(DN)
begin
n_ri<=n_ri-1'b1;
if(n_ri==8'd1)
n_ri<=8'd31;
end
end
else if(con==3'b110)
begin
if(UP)
begin
n_shi <= n_shi + 1'b1;
if(n_shi==8'd23)
n_shi<=8'd0;
end
else if(DN)
begin
n_shi<=n_shi-1'b1;
if(n_shi==8'd0)
n_shi<=8'd23;
end
end
else if(con==3'b111)
begin
if(UP)
begin
n_fen <= n_fen + 1'b1;
if(n_fen==8'd59)
n_fen<=8'd0;
end
else if(DN)
begin
n_fen<=n_fen-1'b1;
if(n_fen==8'd0)
n_fen<=8'd59;
end
end
endmodule
//分频模块
CP.v文件
module CP(iCP,clk_out);
parameter Count=25000000;
input iCP;
output reg clk_out;
reg [24:0] X=1;
[email protected](posedge iCP)
begin
if(X==Count)
begin
X<=1;
clk_out<=~clk_out;
end
else
X<=X+1'b1;
end
endmodule
//分频选择模块
clkgen.v文件
module clkgen(flag,clk_100hz,clk_2hz,clkout);
input[2:0] flag; //若flag=0则clkout=100Hz,否则clkout=2Hz
input clk_100hz,clk_2hz;
output clkout;
assign clkout=(flag==3'b000)?clk_100hz:clk_2hz;
endmodule
//到时报警模块
alarm.v文件
module alarm(clk,yue,ri,shi,fen,Mon,D,H,M,signal);
input clk;
input [7:0] yue,ri,shi,fen; //设定的时间
input [7:0] Mon,D,H,M; //正常的时间
output [7:0] signal;
reg [7:0] signal;
[email protected](posedge clk)
begin
if((yue == Mon)&&(ri==D)&&(shi==H)&&(fen==M))
signal<=8'b11111111;
else
signal<=8'b00000000;
end
endmodule
//总天数模块
countday.v文件
module countday(Y,Mon,D,nday);
input [15:0] Y;
input [7:0] Mon;
input [7:0] D;
output [7:0] nday;
reg [7:0] u_nday;
assign nday=u_nday;
[email protected](Y,D,Mon)
if((Y%4==0)&&(Y%100!=0)||(Y%400==0))
begin
case(Mon)
8'd1:u_nday = 8'd0+D;
8'd2:u_nday = 8'd31+D;
8'd3:u_nday = 8'd31+8'd29+D;
8'd4:u_nday = 8'd31+8'd29+8'd31+D;
8'd5:u_nday = 8'd31+8'd29+8'd31+8'd30+D;
8'd6:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+D;
8'd7:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+8'd30+D;
8'd8:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+8'd30+8'd31+D;
8'd9:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+D;
8'd10:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+8'd30+D;
8'd11:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+8'd30+8'd31+D;
8'd12:u_nday = 8'd31+8'd29+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+8'd30+8'd31+8'd30+D;
endcase
end
else
begin
case(Mon)
8'd1:u_nday = 8'd0+D;
8'd2:u_nday = 8'd31+D;
8'd3:u_nday = 8'd31+8'd28+D;
8'd4:u_nday = 8'd31+8'd28+8'd31+D;
8'd5:u_nday = 8'd31+8'd28+8'd31+8'd30+D;
8'd6:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+D;
8'd7:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+8'd30+D;
8'd8:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+8'd30+8'd31+D;
8'd9:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+D;
8'd10:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+8'd30+D;
8'd11:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+8'd30+8'd31+D;
8'd12:u_nday = 8'd31+8'd28+8'd31+8'd30+8'd31+8'd30+8'd31+8'd31+8'd30+8'd31+8'd30+D;
endcase
end
endmodule
//计算当天是星期几
computeweek.v文件
module computeweek(nday,Y,W);
input [7:0] nday;
input [15:0] Y;
output [7:0] W;
reg [7:0] m_W;
assign W = m_W;
[email protected](nday,Y)
m_W = ((Y-1 + (Y-1)/4 - (Y-1)/100 + (Y-1)/400 + nday)%7==0)? 7:(Y-1 + (Y-1)/4 - (Y-1)/100 + (Y-1)/400 + nday)%7;
endmodule
//计算当天是一年中的第几周
countweek.v
module countweek(nday,nweek);
input [7:0] nday;
output [7:0] nweek;
reg [7:0] u_nweek;
assign nweek=u_nweek;
[email protected](nday)
u_nweek =(nday)/7+((nday%7==0)?0:1);
endmodule
//计算当天是本学期中的第几周
termweek.v文件
module termweek(Y,Mon,nday,mweek);
input [15:0] Y;
input [7:0] nday,Mon;
output [7:0] mweek;
reg [7:0] u_mweek;
assign mweek=u_mweek;
[email protected](Y,nday)
if(Mon>=3&&Mon<=7)
begin
if((Y%4==0)&&(Y%100!=0)||(Y%400==0))
begin
u_mweek =(nday-60)/7+(((nday-60)%7==0)?0:1);
end
else
begin
u_mweek =(nday-59)/7+(((nday-59)%7==0)?0:1);
end
end
else if(Mon>=9&&Mon<=12)
begin
if((Y%4==0)&&(Y%100!=0)||(Y%400==0))
begin
u_mweek =(nday-244)/7+(((nday-244)%7==0)?0:1);
end
else
begin
u_mweek =(nday-243)/7+(((nday-243)%7==0)?0:1);
end
end
else
u_mweek=0;
endmodule
//转换为BCD码
disp_dec.v文件
module disp_dec(show,Y,Mon,D,W,H,M,S,MS,yue,ri,shi,fen,nweek,mweek,dispout);
input[7:0] Mon,D,W,H,M,S,MS;
input[7:0] yue,ri,shi,fen;
input[15:0] Y;
input [7:0] nweek,mweek; //八位二进制输入数据
input [1:0]show;
output[63:0] dispout; //2位十进制的七段段码显示数据
reg[31:0] dec;
[email protected](Y,Mon,D,W,H,M,S,MS,yue,ri,shi,fen,nweek,mweek)
if(show==2'b10) //display RUN/wek/nweek/mweek
begin
if((Y%4==0)&&(Y%100!=0)||(Y%400==0))
begin
dec[31:28]=0;
dec[27:24]=1;
end
else
begin
dec[31:28]=0;
dec[27:24]=0;
end
dec[23:20]=W/4'd10;
dec[19:16]=W%4'd10;
dec[15:12]=nweek/4'd10;
dec[11:8]=nweek%4'd10;
dec[7:4]=mweek/4'd10;
dec[3:0]=mweek%4'd10;
end
else if(show==2'b01)//display date
begin
dec[31:28]=(Y[15:0]/1000)%10;
dec[27:24]=(Y[15:0]/100)%10;
dec[23:20]=(Y[15:0]/10)%10;
dec[19:16]=(Y[15:0]/1)%10;
dec[15:12]=Mon/4'd10;
dec[11:8]=Mon%4'd10;
dec[7:4]=D/4'd10;
dec[3:0]=D%4'd10 ;
end
else if(show==2'b00)//display time
begin
dec[31:28]=H/4'd10;
dec[27:24]=H%4'd10;
dec[23:20]=M/4'd10;
dec[19:16]=M%4'd10;
dec[15:12]=S/4'd10;
dec[11:8]=S%4'd10;
dec[7:4]=MS/4'd10;
dec[3:0]=MS%4'd10;
end
else //display alarm
begin
dec[31:28]=yue/4'd10;
dec[27:24]=yue%4'd10;
dec[23:20]=ri/4'd10;
dec[19:16]=ri%4'd10;
dec[15:12]=shi/4'd10;
dec[11:8]=shi%4'd10;
dec[7:4]=fen/4'd10;
dec[3:0]=fen%4'd10;
end
dual_hex u1(1'b0,dec,dispout); //调用2位共阳极七段显示模块
endmodule
//七段显示模块
dual_hex.v文件
module dual_hex(iflag,datain,dispout);
input iflag; //共阴或共阳输出选择
input[31:0] datain; //2位的十进制或十六进制数据
output[63:0] dispout; //2个七段段码数据
seg_decoder u1(iflag,datain[31:28],dispout[63:56]);
seg_decoder u2(iflag,datain[27:24],dispout[55:48]);
seg_decoder u3(iflag,datain[23:20],dispout[47:40]);
seg_decoder u4(iflag,datain[19:16],dispout[39:32]);
seg_decoder u5(iflag,datain[15:12],dispout[31:24]);
seg_decoder u6(iflag,datain[11:8],dispout[23:16]);
seg_decoder u7(iflag,datain[7:4],dispout[15:8]);
seg_decoder u8(iflag,datain[3:0],dispout[7:0]);
endmodule
//
seg_decoder.v文件
module seg_decoder(iflag,iA,oY);
input iflag; //共阴或共阳输出选择
input[3:0] iA; //4位二进制数据
output reg[7:0] oY; //七段段码显示数据
always @(iflag,iA)
begin
case(iA) //共阴级七段输出
4'b0000:oY=8'h3f;
4'b0001:oY=8'h06;
4'b0010:oY=8'h5b;
4'b0011:oY=8'h4f;
4'b0100:oY=8'h66;
4'b0101:oY=8'h6d;
4'b0110:oY=8'h7d;
4'b0111:oY=8'h27;
4'b1000:oY=8'h7f;
4'b1001:oY=8'h6f;
4'b1010:oY=8'h77;
4'b1011:oY=8'h7c;
4'b1100:oY=8'h58;
4'b1101:oY=8'h5e;
4'b1110:oY=8'h79;
4'b1111:oY=8'h71;
endcase
if(!iflag)
oY=~oY; //共阳极七段输出
end
endmodule
//顶层模块
module clock(iCLK_50,RSTn,reset,FLAG,con,UP,DN,Show,dispout,Mode_show,Mode_falg,
Mode_con,adjust,restart,H,M,S,Y,Mon,D,W,yue,ri,shi,fen,nweek,mweek,nday,signal,alarm_reset);
input iCLK_50;
input RSTn,reset,UP,DN;
input [1:0]Show;
input [2:0] FLAG;
input [2:0] con;
output [1:0] Mode_show;
output [2:0] Mode_falg;
output [2:0] Mode_con;
output [1:0] adjust;
output restart;
output alarm_reset;
output [63:0] dispout;
output [7:0] H,M,S;
output [7:0] Mon,D,W;
output [15:0] Y;
output [7:0] nweek;
output [7:0] mweek;
output [7:0] nday;
output [7:0] yue,ri,shi,fen;
output [7:0] signal;
wire [7:0] Mon,D,W,H,M,S,MS;
wire [15:0] Y;
wire clk_100hz,clk_2hz;
wire clk;
wire clk_n;
wire [7:0] nweek,mweek,nday;
assign Mode_show=Show;
assign Mode_falg=FLAG;
assign Mode_con=con;
assign adjust={UP,DN};
assign restart=RSTn;
assign alarm_reset=reset;
CP #(25000000) nclk2(iCLK_50,clk_2hz);//0.5s
CP #(250000) nclk100(iCLK_50,clk_100hz);//0.01s
clkgen u0(FLAG,clk_100hz,clk_2hz,clk);
myalarm u3(reset,clk_2hz,con,UP,DN,yue,ri,shi,fen);
alarm u4(clk,yue,ri,shi,fen,Mon,D,H,M,signal);
myclock u1(RSTn,clk,FLAG,UP,DN,Y,Mon,D,H,M,S,MS);
countday u5(Y,Mon,D,nday);
countweek u6(nday,nweek);
computeweek u8(nday,Y,W);
termweek u7(Y,Mon,nday,mweek);
disp_dec(Show,Y,Mon,D,W,H,M,S,MS,yue,ri,shi,fen,nweek,mweek,dispout);
endmodule