欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数字时钟

程序员文章站 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