EDA课设:12/24小时数字钟设计

1 篇文章 0 订阅
1 篇文章 0 订阅

设计要求:

1.设计一个12/24小时制数字钟。
2.按下时调整键,“时”迅速增加,并按24/12小时制规律循环。
3.按下分调整键,“分”迅速增加,并按60分制规律循环。
4.按下秒清零键,“秒”清零。
5.整点报时,从59分55秒开始报时,每隔一秒报时一次。
6.具有12/24小时显示切换的功能。
7.增加万年历功能,输入2000~2100年任意一天日期,输出为周几。
8.具有按键切换功能,在日期,周几,计时三种显示模式中切换。

模块设计

分频模块

分频产生2k,1k,50,10,2,1等频率的信号,占空比尽量都为50%,为此,设计任意整数进制占空比50%的分频模块。
代码如下:

module fenpin(clk,N,clk_out);
input clk;
output clk_out;
input[15:0] N;
reg[15:0] count1,count2;
reg clkA,clkB;
assign clk_re = ~clk;
assign clk_out = clkA | clkB;
always@(posedge clk)
  if(N%2==1)
	 begin 
		if(count1<N-1)
			begin
				count1<=count1+1'b1;
			if(count1==(N-1)/2)
				begin
					clkA<=~clkA;
				end
			end
		 else 
			begin
				clkA<=~clkA;
				count1<=1'b0;
			end
	  end
	else
		begin
			if(count1<N/2-1)
				begin	
					count1<=count1+1'b1;
				end
			 else
				 begin
					clkA<=~clkA;
					count1<=1'b0;
				 end
		 end
		 
always@(posedge clk_re)
	if(N%2==1)
		begin
			if(count2<(N-1))
				begin
					count2<=count2+1'b1;
					if(count2==(N-1)/2)
						begin
							clkB<=~clkB;
						end
				end
			else
				clkB=1'b0;
			end
endmodule
		

调用时只要将N改为对应的分频系数即可。
对应代码如下:

module clock_fenpin(clk_50M,clk_2k,clk_1k,clk_50,clk_10,clk_2,clk_1);
input clk_50M;
output clk_2k,clk_1k,clk_50,clk_10,clk_2,clk_1;
fenpin(clk_50M,25000,clk_2k);
fenpin(clk_2k,2,clk_1k);
fenpin(clk_1k,20,clk_50);
fenpin(clk_50,5,clk_10);
fenpin(clk_50,25,clk_2);
fenpin(clk_2,2,clk_1);
endmodule

时间计数模块

由一个12/24计数器和两个60进制计数器组成,要实现时分的迅速增加和秒的清零,可以由一个二选一的数选器控制计数器的计数时钟,具体实现如下:
带清零的60进制计数:

module counter60_S(clk_1,rst,key_S,cout,dout_H,dout_L);
input clk_1,rst,key_S;
output [3:0] dout_H,dout_L;
reg[7:0] cnt;
output reg cout;
wire rst_tmp;
assign dout_H=cnt[7:4];
assign dout_L=cnt[3:0];
assign rst_tmp=key_S?rst?1:0:0;
always@(posedge clk_1 or negedge rst_tmp)
  begin
    if(!rst_tmp)
      cnt = 0;
    else
      begin
        if(cnt == 'h59)
          begin
            cnt = 0;
            cout=1;
          end
        else
          begin
            cout=0;
            cnt<=cnt+1;
            if(cnt[3:0]=='h9)
              begin
                cnt[3:0]=0;
                cnt[7:4]=cnt[7:4]+1;
              end
          end
      end
  end


endmodule

可以迅速增加的60进制分计数器:

module counter60_M(clk_s,clk_2,rst,key_M,cout,dout_H,dout_L);
input clk_s,clk_2,rst,key_M;
output [3:0] dout_H,dout_L;
reg[7:0] cnt;
output reg cout;
wire clk_tmp;
assign dout_H=cnt[7:4];
assign dout_L=cnt[3:0];
assign clk_tmp=key_M?clk_s:clk_2;
always@(posedge clk_tmp or negedge rst)
  begin
    if(!rst)
      cnt = 0;
    else
      begin
        if(cnt == 'h59)
          begin
            cnt = 0;
            cout=1;
          end
        else
          begin
            cout=0;
            cnt<=cnt+1;
            if(cnt[3:0]=='h9)
              begin
                cnt[3:0]=0;
                cnt[7:4]=cnt[7:4]+1;
              end
          end
      end
  end
endmodule



12进制计数器:

module counter12(clk_m,rst,dout_H,dout_L);
input clk_m,rst;
output [3:0] dout_H,dout_L;
reg[7:0] cnt;
assign dout_H=cnt[7:4];
assign dout_L=cnt[3:0];
always@(posedge clk_m or negedge rst)
  begin
    if(!rst)
      cnt = 0;
    else
      begin
        if(cnt == 'h11)
          begin
            cnt = 0;
          end
        else
          begin
            cnt<=cnt+1;
            if(cnt[3:0]=='h9)
              begin
                cnt[3:0]=0;
                cnt[7:4]=cnt[7:4]+1;
              end
          end
      end
  end
endmodule

24进制计数器:

module counter24(clk_m,rst,dout_H,dout_L);
input clk_m,rst;
output [3:0] dout_H,dout_L;
reg[7:0] cnt;
assign dout_H=cnt[7:4];
assign dout_L=cnt[3:0];
always@(posedge clk_m or negedge rst)
  begin
    if(!rst)
      cnt = 0;
    else
      begin
        if(cnt == 'h23)
          begin
            cnt = 0;
          end
        else
          begin
            cnt<=cnt+1;
            if(cnt[3:0]=='h9)
              begin
                cnt[3:0]=0;
                cnt[7:4]=cnt[7:4]+1;
              end
          end
      end
  end
endmodule

组合成为12/24小时计数器:

module counter12_24(clk_m,rst,sw1,dout_H,dout_L,clk_2,key_H,A_P);
	 input clk_m,rst,sw1,clk_2,key_H;
	 output[3:0] dout_H,dout_L;
	 output[1:0] A_P;
	 wire[3:0] dout12_H,dout12_L,dout24_H,dout24_L; //调用模块时必须有相应的定义,否则结果有问题
	 wire clk;
	 assign clk=key_H?clk_m:clk_2;
	 counter12(clk,rst,dout12_H,dout12_L);
	 counter24(clk,rst,dout24_H,dout24_L);
	 assign dout_H=sw1?dout12_H:dout24_H;
	 assign dout_L=sw1?dout12_L:dout24_L;
	 assign A_P=sw1?(((dout24_H==1)&&(dout24_L>2))||(dout24_H==2))?2'b01:2'b10:2'b00;
endmodule

A_P用来显示上午或者下午。

万年历模块

代码如下:

module calendar(clk_50M,clk,rst,key_y,key_m,key_d,year_3,year_2,year_1,year_0,month_H,month_L,day_H,day_L,week);
input clk,rst,key_d,key_m,key_y,clk_50M;
output[3:0] year_3,year_2,year_1,year_0,month_H,month_L,day_H,day_L;
reg[15:0] year;
reg[7:0] month,day;
output [3:0] week;
wire[7:0] week_W;
wire[7:0] year_H,year_L,month_M,day_D;
reg clk_year,clk_month;
reg[7:0] data;
reg clk_y1,clk_y2,clk_y3;
initial
  begin
    clk_y1=0;
    clk_y2=0;
    clk_y3=0;
  end  //初始化很重要,尤其是后面要用边沿触发时
initial
  begin
    year='h2000;
    month=1;
    day=1;
  end
always@(negedge (clk^key_d) or negedge rst)
  begin
    if(!rst)
      day=1;
    else if(!key_d)
      begin
        if(day==data)
          day=1;
        else
          day=day+1;
        if(day[3:0]==4'ha)
          begin
            day[3:0]=0;
            day[7:4]=day[7:4]+1;
          end
      end
    else
      begin
        if(day==data)
          day=1;
        else
          day=day+1;
        if(day[3:0]==4'ha)
          begin
            day[3:0]=0;
            day[7:4]=day[7:4]+1;
          end
        if((day==data)&&(clk))
          clk_month=1;
        else
          clk_month=0;
      end
  end

always @(negedge (clk_month^key_m) or negedge rst)
  begin
    if (!rst)
      month=1;
    else
      begin
        if(month=='h12)
          month=1;
        else
          month=month+1;
        if(month[3:0]=='ha)
          begin
            month[3:0]=0;
            month[7:4]=month[7:4]+1;
          end
        if(month=='h12)
          clk_year=1;
        else
          clk_year=0;
      end
  end

always @(posedge clk_50M)
  begin
    case(month)
      'h01:
        data='h31;
      'h02:
        begin
          case(year)
            16'h2004:
              data='h29;
            16'h2008:
              data='h29;
            16'h2012:
              data='h29;
            16'h2016:
              data='h29;
            16'h2020:
              data='h29;
            16'h2024:
              data='h29;
            16'h2028:
              data='h29;
            16'h2032:
              data='h29;
            16'h2036:
              data='h29;
            16'h2040:
              data='h28;
            16'h2044:
              data='h29;
            16'h2048:
              data='h29;
            16'h2052:
              data='h29;
            16'h2056:
              data='h29;
            16'h2060:
              data='h29;
            16'h2064:
              data='h29;
            16'h2068:
              data='h29;
            16'h2072:
              data='h29;
            16'h2076:
              data='h29;
            16'h2080:
              data='h28;
            16'h2084:
              data='h29;
            16'h2088:
              data='h29;
            16'h2092:
              data='h29;
            16'h2096:
              data='h29;
            16'h2104:
              data='h29;
            default:
              data='h28;
          endcase
        end
      'h03:
        data='h31;
      'h04:
        data='h30;
      'h05:
        data='h31;
      'h06:
        data='h30;
      'h07:
        data='h31;
      'h08:
        data='h31;
      'h09:
        data='h30;
      'h10:
        data='h31;
      'h11:
        data='h30;
      'h12:
        data='h31;
      default:
        data='h30;
    endcase
  end

always@(posedge (clk_year^key_y) or negedge rst)
  begin
    if(!rst)
      year[3:0]=0;
    else
      begin
        if(year[3:0]==9)
          year[3:0]=0;
        else
          year[3:0]=year[3:0]+1;
        if(year[3:0]==9)
          clk_y1=1;
        else
          clk_y1=0;
      end
  end

always@(negedge clk_y1 or negedge rst)
  begin
    if(!rst)
      year[7:4]=0;
    else
      begin
        if(year[7:4]==9)
          year[7:4]=0;
        else
          year[7:4]=year[7:4]+1;
        if(year[7:4]==9)
          clk_y2=1;
        else
          clk_y2=0;
      end
  end

always@(negedge clk_y2 or negedge rst)
  begin
    if(!rst)
      year[11:8]=0;
    else
      begin
        if(year[11:8]==9)
          year[11:8]=0;
        else
          year[11:8]=year[11:8]+1;
        if(year[11:8]==9)
          clk_y3=1;
        else
          clk_y3=0;
      end
  end

always@(negedge clk_y3 or negedge rst)
  begin
    if(!rst)
      year[15:12]=2;
    else
      begin
        if(year[15:12]==9)
          year[15:12]=0;
        else
          year[15:12]=year[15:12]+1;
      end
  end

assign year_H=year[15:12]*10+year[11:8];
assign year_L=year[7:4]*10+year[3:0];
assign month_M=month[7:4]*10+month[3:0];
assign day_D=day[7:4]*10+day[3:0];
assign week_W=(month=='h1)?((year_H/4)-2*year_H+year_L-1+(year_L-1)/4+35+day_D)%7:(month_M=='h2)?((year_H/4)-2*year_H+year_L-1+(year_L-1)/4+38+day_D)%7:((year_H/4)-2*year_H+year_L+year_L/4+(13*(month_M+1))/5+day_D-1)%7;
assign week=(week_W==0)?7:week_W;
assign year_3=year[15:12];
assign year_2=year[11:8];
assign year_1=year[7:4];
assign year_0=year[3:0];
assign month_H=month[7:4];
assign month_L=month[3:0];
assign day_H=day[7:4];
assign day_L=day[3:0];
endmodule

显示模块

硬件开发板为xx大学的LB0板,别的板子根据硬件结构自己调整,代码如下:

module display(data,clk_1k,sel,hex,sw2,A_P,key_state);
input[31:0] data;
input clk_1k,sw2;
input[1:0] key_state;
output reg[2:0] sel;
output reg[7:0] hex;
reg[3:0] seg;
input[1:0] A_P;
reg[3:0] A_P_tmp;
parameter N=3;
reg[N-1:0] regN;
wire[3:0] data_0,data_1,data_2,data_3,data_4,data_5,data_6,data_7;
assign data_0=data[3:0];
assign data_1=data[7:4];
assign data_2=data[11:8];
assign data_3=data[15:12];
assign data_4=data[19:16];
assign data_5=data[23:20];
assign data_6=data[27:24];
assign data_7=data[31:28];
always@(posedge clk_1k)
case(A_P)
	2'b00:A_P_tmp<=4'hF;
	2'b10:A_P_tmp<=4'hA;
	2'b01:A_P_tmp<=4'hD;
endcase

always@(posedge clk_1k)
 begin
	regN<=regN+1;
	sel<=regN;
 end
	
always@*
	case(regN)
	3'b000: seg=data_1;
	3'b001: seg=data_6;
	3'b010: seg=((A_P_tmp==4'h0) && (key_state!=2'b01))?data_7:(key_state==2'b01)?data_7:A_P_tmp;
	3'b011: seg=data_4;
	3'b100: seg=data_5;
	3'b101: seg=data_2;
	3'b110: seg=data_3;
	3'b111: seg=data_0;
	default:begin seg=4'b0000;end
   endcase
	
always@*
	case(seg)
			4'h0:hex = 8'h3f;
			4'h1:hex = 8'h06;
			4'h2:hex = 8'h5b;
			4'h3:hex = 8'h4f;
			4'h4:hex = 8'h66;
			4'h5:hex = 8'h6d;
			4'h6:hex = 8'h7c;
			4'h7:hex = 8'h07;
			4'h8:hex = 8'h7f;
			4'h9:hex = 8'h67;
			4'hA:hex = 8'h77;
			4'hB:hex = 8'h00;
			4'hC:hex = 8'h00;
			4'hD:hex = 8'h5E;
			4'hE:hex = 8'h00;
			4'hF:hex = 8'h00;
			default:hex=8'h3f;
	
	endcase
endmodule


按键去抖动模块

module keySkew(clk,keyin,keyout);
input keyin,clk;
output keyout;
reg key_tmp1,key_tmp2;
reg keyout_tmp;
assign keyout=keyout_tmp;
always@(posedge clk)begin 
    key_tmp1<=keyin;
    key_tmp2<=key_tmp1;
    keyout_tmp<=~(~key_tmp1 && key_tmp2);
end
endmodule

四个按键:

module key4(key1,key2,key3,key4,key_clk,key_o1,key_o2,key_o3,key_o4);
input key1,key2,key3,key4,key_clk;
output key_o1,key_o2,key_o3,key_o4;
keySkew(key_clk,key1,key_o1);
keySkew(key_clk,key2,key_o2); //对应端口一定不能错
keySkew(key_clk,key3,key_o3);
keySkew(key_clk,key4,key_o4);
endmodule

顶层调用

module clock_top(clk_50M,sw0,sw1,sw2,key1_in,key2_in,key3_in,key4_in,sound,sel,hex);
	 input clk_50M,sw0,sw1,sw2,key1_in,key2_in,key3_in,key4_in;
	 output sound;
	 output[2:0] sel;
	 output[7:0] hex;
	 
	 wire clk_2k,clk_1k,clk_50,clk_10,clk_2,clk_1,key1,key2,key3,rst,key_year,key_month,key_day,key_hour,key_minute,key_second;
	 wire cout,cout_S,cout_M;
	 wire[1:0] A_P;
	 wire[3:0] doutS_H,doutS_L,doutM_H,doutM_L,doutH_H,doutH_L,year_3,year_2,year_1,year_0,month_H,month_L,day_H,day_L,week;
		
	 reg[1:0] key_state;
	 reg key1_state,key2_state;
	 
	 parameter zero=4'hf;
always@(negedge key4)
	 key_state<=key_state+1;
always@(negedge key1)
	 key1_state<=key1_state+1;
always@(negedge key2)
	 key2_state<=key2_state+1;
	
	
	 key4(key1_in,key2_in,key3_in,key4_in,clk_50,key1,key2,key3,key4);
	 keySkew(clk_50,sw1,sw1_out);
	 keySkew(clk_50,sw2,sw2_out);
	 assign key_year=(sw1_out)?key1_state:1;
	 assign key_month=(sw1_out)?key2_state:1;
	 assign key_day=(sw1_out)?key3:1;
	 assign key_hour=(sw2_out)?key1_state:1;
	 assign key_minute=(sw2_out)?key2_state:1;
	 assign key_second=(sw2_out)?key3:1;

	 
	 clock_fenpin(clk_50M,clk_2k,clk_1k,clk_50,clk_10,clk_2,clk_1);
counter60_S(clk_1,1,key_second,cout_S,doutS_H,doutS_L);
	 counter60_M(cout_S,clk_2,1,key_minute,cout_M,doutM_H,doutM_L);
	 counter12_24(cout_M,1,sw0,doutH_H,doutH_L,clk_2,key_hour,A_P);
	 calendar(clk_50M,cout,1,key_year,key_month,key_day,year_3,year_2,year_1,year_0,month_H,month_L,day_H,day_L,week);
    wire [31:0]Number_Sig,Number_Sig_Clo,Number_Sig_Cal,Number_Sig_week;
	 assign Number_Sig_Clo={zero,doutH_H,doutH_L,doutM_H,doutM_L,doutS_H,doutS_L};
	 assign Number_Sig_Cal={year_3,year_2,year_1,year_0,month_H,month_L,day_H,day_L};
	 assign Number_Sig_week={week};
	 assign Number_Sig=(key_state==2'b01)?Number_Sig_Cal:(key_state==2'b10)?Number_Sig_week:Number_Sig_Clo;
	 display(Number_Sig,clk_1k,sel,hex,sw2,A_P,key_state);
	 assign cout=((A_P==2'b00)&&(doutH_H==4'h2)&&(doutH_L==4'h3)&&(doutM_H==4'h5)&&(doutM_L==4'h9)&&(doutS_H==4'h5)&&(doutS_L==4'h9))?1:((A_P==2'b01)&&(doutH_H==4'h1)&&(doutH_L==4'h1)&&(doutM_H==4'h5)&&(doutM_L==4'h9)&&(doutS_H==4'h5)&&(doutS_L==4'h9))?1:0;
	 assign sound=(({doutM_H,doutM_L}=='h59)&&(({doutS_H,doutS_L}=='h55)||({doutS_H,doutS_L}=='h57)||({doutS_H,doutS_L}=='h59)))?clk_1k:(({doutM_H,doutM_L}=='h00)&&({doutS_H,doutS_L}=='h00))?clk_2k:1;
endmodule
  • 15
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值