找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4378|回复: 2
打印 上一主题 下一主题
收起左侧

EDA多功能数字钟(源代码)

[复制链接]
跳转到指定楼层
楼主
ID:51024 发表于 2014-7-30 14:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
                       
这个实验先自己做了一次,功能可以全部实现,由于ModelSim不熟悉仿真出现问题向苏豪学长求助时学长说我的代码太丑,思路不清晰,排版杂乱,要我重新写一遍。因而今天又做了一次。这里附上两次源代码(两次的代码都在板子上跑过了,都可以实现所有功能)。算我自己留个纪念,也供需要的人参考。(有任何问题或建议欢迎留言。)
实验任务及要求

基本功能:

1,准确计时,以数字形式(十进制)显示时、分、秒的时间

2,校正时间:时、分  快校 与 慢校 (1Hz与手动)

3,复位:00:00:00

选做:

1,任意闹钟

2,小时为12/24进制可切换

3,报整点数(几点钟LED闪烁几下)

实验条件

DE0开发板,Quartus II 13.1.0 Altera-Modelsim

第一次实验时代码:

moduledemultiply(CP,MainCLK);//50MHz分频出1Hz

input MainCLK;

output CP;

regCP;

reg[24:0]counter;

initial

begin counter=0;CP=0;end

always @(posedge MainCLK)

begin

   if(counter==24999999)   

          begin CP=~CP;counter=0;end

    elsecounter=counter+1;

end

endmodule


moduleshow(OUT,IN,CP);//译码显示模块

output [7:0]OUT;

input [3:0]IN;

input CP;

reg [7:0]OUT;

always @(posedgeCP)

case (IN)

   0:OUT=8'b11000000;

   1:OUT=8'b11111001;

   2:OUT=8'b10100100;

   3:OUT=8'b10110000;

   4:OUT=8'b10011001;

   5:OUT=8'b10010010;

   6:OUT=8'b10000010;

   7:OUT=8'b11111000;

   8:OUT=8'b10000000;

   9:OUT=8'b10010000;

    default:OUT=8'b10001001;

endcase

endmodule


//秒/分控制(60进制,快慢校正,Ck=2'b10为减,Ck=2'b01为加)

module SecOrMinControl(Q,nCR,EN,ENQ,CP,Ck);

output [7:0]Q;

input nCR,EN,CP,ENQ;

input [1:0]Ck;

reg[7:0]Q;

always @(posedge CP)

begin

if(~nCR) Q<=8'b00000000;

else if(~EN) Q<=Q;

else

case (Ck[1:0])

   2'b01:

   if((Q[3:0]==4'b1001)&&(Q[7:4]!=4'b0101))beginQ[7:4]<=Q[7:4]+1'b1;Q[3:0]<=4'b0000;end

    elseif(Q[7:0]==8'b01011001)Q[7:0]<=8'b00000000;

    else beginQ[7:4]<=Q[7:4];Q[3:0]<=Q[3:0]+1'b1;end

   2'b10:

   if((Q[3:0]==4'b0000)&&(Q[7:4]!=4'b0000))beginQ[7:4]<=Q[7:4]-1'b1;Q[3:0]<=4'b1001;end

    elseif(Q[7:0]==8'b00000000)Q[7:0]<=8'b01011001;

    else beginQ[7:4]<=Q[7:4];Q[3:0]<=Q[3:0]-1'b1;end

    default:   if(~ENQ)Q<=Q;

   else

   begin

   if((Q[3:0]==4'b1001)&&(Q[7:4]!=4'b0101))beginQ[7:4]<=Q[7:4]+1'b1;Q[3:0]<=4'b0000;end

    elseif(Q[7:0]==8'b01011001)Q[7:0]<=8'b00000000;

    else beginQ[7:4]<=Q[7:4];Q[3:0]<=Q[3:0]+1'b1;end

   end

endcase

end


endmodule

//小时控制,快慢校正Ck=2‘b01加,Ck=2'b10减.

//12/24进制选择,Select=1——24进制,0——12进制

moduleHrControl(Q,nCR,EN,ENQ,CP,Ck,Select);

output [4:0]Q;

input nCR,EN,CP,ENQ,Select;

input [1:0]Ck;

reg[4:0]Q;

always @(posedge CP)

begin

if(~nCR) Q<=5'b00000;

else if(~EN) Q<=Q;

else

case (Ck[1:0])

   2'b01:if(Select==1)

if(Q==5'b10111)Q<=5'b00000;

else Q<=Q+1'b1;

elseif(Q>5'b01100)Q<=Q-5'b01100;

elseif(Q==5'b01100)Q<=5'b0001;

else Q<=Q+1'b1;

   2'b10:if(Select==1)

if(Q==5'b00000)Q<=5'b10111;

else Q<=Q-1'b1;

elseif(Q>5'b01100)Q<=Q-5'b01100;

else if((Q==5'b00001)||(Q==5'b00000))Q<=5'b01100;

elseQ<=Q-1'b1;

   default:

    if(~ENQ)Q<=Q;

   else

if(Select==1)

if(Q==5'b10111)Q<=5'b0000000;

else Q<=Q+1'b1;

elseif(Q==5'b01100)Q<=5'b00001;

else Q<=Q+1'b1;

endcase

end

endmodule

//整点报时功能,几点LED亮几次

moduleTellTime(LED,Hr,ENL,EN,MainCLK);

input MainCLK ,ENL, EN;

input [4:0]Hr;

output LED;

regflag;

regLED;

reg[5:0]CntTimes;

reg[25:0]counter_number;

initial beginflag=0;counter_number=0;CntTimes=0;end

always @(posedge MainCLK)

begin

if(~EN) LED<=0;

else

if(ENL)

beginflag<=1;end

if(flag==1)

begin

if(CntTimes>=2'b10*Hr)

  beginLED<=0;flag<=0;CntTimes=0;end

  elseif(counter_number==24999999)

       begincounter_number<=0;LED<=~LED;CntTimes<=CntTimes+1'b1;end

      elsecounter_number<=counter_number+1'b1;

end

end

endmodule


module ALARM_Clock(SetHr,SetMin,SetSec,Alarm,CP,MainCLK,nCR,EN,ENAC,CkSec,CkMin,CkHr,Select,Sec,Min,Hr);

output [4:0]SetHr;

output [7:0]SetSec,SetMin;

output Alarm;

inputCP,EN,Select,nCR,MainCLK,ENAC;

input [1:0]CkMin,CkHr,CkSec;

input [7:0]Sec,Min;

input [4:0]Hr;

regAlarm;

regflag;

reg[3:0]CntTimes;

reg[25:0]counter_number;

wire ENSec;

wire ENSM,ENMH,ENL;

wire [7:0]Sec,Min;

wire [4:0]Hr;

assign ENSM=0;

assign ENMH=0;

assign ENSec=0;

initial beginflag=0;counter_number=0;CntTimes=0;end

SecOrMinControlAlarmSecControl(SetSec,nCR,EN,ENSec,CP,CkSec);

SecOrMinControlAlarmMinControl(SetMin,nCR,EN,ENSM,CP,CkMin);

HrControlAlarmHourControl(SetHr,nCR,EN,ENMH,CP,CkHr,Select);

always @(posedge MainCLK)

if(~EN||~nCR||~ENAC)Alarm<=0;

else

begin

if(Hr==SetHr&&Min==SetMin&&Sec==SetSec)flag<=1;

if(flag==1)

begin

if(CntTimes>=4'b1100)

  beginAlarm<=0;flag<=0;CntTimes=0;end

  elseif(counter_number==49999)

       begincounter_number<=0;Alarm<=~Alarm;CntTimes<=CntTimes+1'b1;end

      elsecounter_number<=counter_number+1'b1;

end

end

endmodule


//顶层模块,其中SHOWAC=1,数码管显示当时时间,=0显示定时设置时间

moduleDigtalClock(Hr0,Hr1,Min0,Min1,Sec0,Sec1,Light,Alarm,nCR,EN,MainCLK,CkSec,CkMin,CkHr,Select,ENAC,SHOWAC);

output [7:0]Min0,Min1,Hr0,Hr1;

output [3:0]Sec0,Sec1;

output Light,Alarm;

inputnCR,EN,MainCLK,Select,ENAC,SHOWAC;

input [1:0]CkSec,CkMin,CkHr;

wire ENSec;

wire ENSM,ENMH,ENL;

wire [7:0]Sec,Min;

wire [4:0]Hr;

wire [7:0]SetSec,SetMin;

wire [4:0]SetHr;

assign ENSec =EN;

assign ENSM=(Sec==8'b01011000);

assign ENMH=(Min==8'b01011001&&Sec==8'b01011000);


assignENL=(Min==8'b00000000&&Sec==8'b00000000);

assign Sec0 =(SHOWAC==0?SetSec:Sec);

assign Sec1 =(SHOWAC==0?SetSec>>4:Sec>>4);


demultiplyOneHzMaker(CP,MainCLK);

SecOrMinControlSecControl(Sec,nCR,EN,ENSec,CP,(ENAC==1?2'b00:CkSec));

SecOrMinControlMinControl(Min,nCR,EN,ENSM,CP,(ENAC==1?2'b00:CkMin));

HrControlHourControl(Hr,nCR,EN,ENMH,CP,(ENAC==1?2'b00:CkHr),(ENAC==1?1'b1:Select));

ALARM_ClockYalling(SetHr,SetMin,SetSec,Alarm,CP,MainCLK,nCR,EN,ENAC,(ENAC==1?CkSec:2'b00),(ENAC==1?CkMin:2'b00),(ENAC==1?CkHr:2'b00),Select,Sec,Min,Hr);

TellTimeShining(Light,Hr,ENL,EN,MainCLK);



showMinSh0(Min0,(SHOWAC==0?SetMin[3:0]:Min[3:0]),CP);

showMinSh1(Min1,(SHOWAC==0?SetMin[7:4]:Min[7:4]),CP);

showHrSh0(Hr0,(SHOWAC==0?SetHr:Hr),CP);

showHrSh1(Hr1,(SHOWAC==0?SetHr/10:Hr/10),CP);

endmodule

第二次的代码:分了多个文件写的,思路差不多,只是省了几个拨码开关


//NewDigitalClock.v

module NewDigitalClock(//顶层模块

input EN,

input nCR,

input CP,

input Sel_Hr,

//Sel_Hr选择小时是12还是24进制,Sel=1,24;Sel==0,12.

input UpOrDown,

//UPOrDown:加校正减校正0——>-,1——>+

input Set_Sel,

//Set_Sel选择设置位:0——>Min,1——>Hr;Set_EN设置校时使能

input Set_EN,//设置时间使能

input Alarm_Clock_EN,//闹钟使能

inputShowAlarm,//1---Alarm,0---Clock.

output [3:0] Sec_L,

output [3:0]Sec_H,

output [6:0] Min_L,

output [6:0] Min_H,

output [6:0]Hr_L,

output [6:0] Hr_H,

output Alarm,

output LED );

wire [7:0] Sec,Min;

wire [4:0] Hr;

wire [7:0] Clock_Min;

wire [4:0] Clock_Hr;

wire EN_Min,EN_Sec, EN_Hr, EN_Main;//分钟,秒钟,时,主使能

wire Hr_UpOrDown,Min_UpOrDown, Sec_UpOrDown;


assign EN_Sec = (EN &&EN_Main);

assign EN_Min = (EN_Sec &&((!Alarm_Clock_EN && Set_EN == 1 && Set_Sel == 0)|| (!(!Alarm_Clock_EN && Set_EN == 1 && Set_Sel ==0) && ( Sec == 8'h59))));

assign EN_Hr = (EN_Sec &&((!Alarm_Clock_EN && Set_EN == 1 && Set_Sel == 1)|| (!(!Alarm_Clock_EN && Set_EN == 1 && Set_Sel ==1) && (Min == 8'h59 && Sec ==8'h59))));



assign Min_UpOrDown = !(Set_EN == 1 &&Set_Sel == 0 && UpOrDown == 0);

assign Hr_UpOrDown = !(Set_EN == 1 &&Set_Sel == 1 && UpOrDown == 0);

assign Sec_UpOrDown = 1;


assign Sec_H = Sec[7:4];

assign Sec_L = Sec[3:0];


OneHzMaker OneHz(

.Q(EN_Main),

.CP(CP));


Counter60 SecTiming(

.Q(Sec),

.nCR(nCR),

.EN(EN_Sec),

.CP(CP),

.UpOrDown(Sec_UpOrDown));

Counter60 MinTiming(

.Q(Min),

.nCR(nCR),

.EN(EN_Min),

.CP(CP),

.UpOrDown(Min_UpOrDown));

Counter12or24 HrTiming(

.Q(Hr),

.nCR(nCR),

.EN(EN_Hr),

.CP(CP),

.Sel(Sel_Hr),//选择小时的进制,1——24,0——12

.UpOrDown(Hr_UpOrDown));


Alarm_Clock AlarmOn(//闹钟

.CP(CP),

.nCR(nCR),

.EN(Alarm_Clock_EN),

.Min(Min),

.Hr(Hr),

.UpOrDown(UpOrDown),

//UpOrDown:加校正减校正0——>-,1——>+

.Set_Sel(Set_Sel),

//Set_Sel选择设置位:0——>Min,1——>Hr;Set_EN设置校时使能

.Set_EN(Set_EN),//设置时间使能

.Sel_Hr(Sel_Hr),

//Sel_Hr选择小时是12还是24进制,Sel=1,24;Sel==0,12.

.Alarm(Alarm),//闹钟输出

.Clock_Min(Clock_Min),//闹钟定时分钟

.Clock_Hr(Clock_Hr));//闹钟定时小时


show Hr_L_show(

.OUT(Hr_L),

.IN(ShowAlarm?Clock_Hr:Hr),

.CP(CP));

show Hr_H_show(

.OUT(Hr_H),

.IN(ShowAlarm?Clock_Hr/10:Hr/10),

.CP(CP));

show Min_L_show(

.OUT(Min_L),

.IN(ShowAlarm?Clock_Min[3:0]:Min[3:0]),

.CP(CP));

show Min_H_show(

.OUT(Min_H),

.IN(ShowAlarm?Clock_Min[7:4]:Min[7:4]),

.CP(CP));

LEDTellTime(//整点报时

.CP(CP),

.EN(EN),

.Hr(Hr),

.Min(Min),

.Sec(Sec),

.LED(LED));


endmodule



//Counter10.v************模10可逆计数

module Counter10(

output reg [3:0] Q,

input nCR,

input EN,

input CP,

input UpOrDown);


initial

Q<= 0;

always @ (posedge CP or negedge nCR )begin

if(~nCR)

Q<= 0;

else

if(~EN)

Q<= Q;

else

if(!UpOrDown)

Q<= ((Q == 0)?9 : Q - 1);

else

Q<= ((Q == 9)?0 : Q + 1);

end

endmodule



//Counter6.v******模6可逆计数

module Counter6(

output reg [3:0]Q,

input nCR,

input EN,

input CP,

input UpOrDown);


initial

Q<= 0;

always @(posedge CP or negedge nCR)begin

if(~nCR)

Q<= 0;

else

if(~EN)

Q<= Q;

else

if(!UpOrDown)

Q<= ((Q == 0)? 5 : Q - 1);

else

Q<=((Q == 5)? 0: Q + 1);

end

endmodule


//Counter60.v*******模60 可逆计数

module Counter60(

output [7:0]Q,

input nCR,

input EN,

input CP,

input UpOrDown);


wire EN_LH;


assign EN_LH = (EN && (UpOrDown? (Q[3:0]== 9) : (Q[3:0] == 0)));


Counter10 Q_L(

.Q(Q[3:0]),

.nCR(nCR),

.EN(EN),

.CP(CP),

.UpOrDown(UpOrDown));


Counter6 Q_H(

.Q(Q[7:4]),

.nCR(nCR),

.EN(EN_LH),

.CP(CP),

.UpOrDown(UpOrDown));


endmodule



//Counter12or24.v*******12/24进制切换,可逆
moduleCounter12or24(
output reg [4:0]Q,
inputnCR,
inputEN,
inputCP,
inputSel, //Sel=1,24;Sel==0,12.
input UpOrDown);


always @(posedge CP or negedgenCR)begin
if( ~nCR)
Q <= 0;
else begin
if(~EN)
Q <= Q;
else begin
if(Sel) begin
if(!UpOrDown)
Q <=((Q == 0)? 23: Q - 1);
else
Q <=((Q == 23)? 0: Q +1);
end
elsebegin
if(Q > 12)
Q <= Q - 12;
elsebegin
if(!UpOrDown)begin
if(Q == 1)
Q <=12;
else
Q <= ((Q == 0)? 11:Q -1);
end
else
Q <= ((Q == 12)? 1:Q +1);
end
end
end
end
end
endmodule


//50MHz计数分频出1Hz*******OneHzMaker.v
module OneHzMaker(
output reg Q,
inputCP);//50MHzCP____1HzQ


reg [25:0] Cnt;


initial begin
Cnt <= 0;
Q <= 0;
end


always @(posedge CP)begin
if(Cnt == 49999998)begin
Q <= 1;
Cnt <= Cnt + 1;
end
else
if(Cnt == 49999999)begin
Q <= 0;
Cnt <= 0;
end
else begin
Cnt <= Cnt + 1;
Q <= 0;
end
end


endmodule



//show.v****数码管显示
module show(
output reg [7:0] OUT,
input [3:0] IN,
input CP);


always @(posedgeCP)
case (IN)
0: OUT =7'b1000000;
1: OUT =7'b1111001;
2: OUT =7'b0100100;
3: OUT =7'b0110000;
4: OUT =7'b0011001;
5: OUT =7'b0010010;
6: OUT =7'b0000010;
7: OUT =7'b1111000;
8: OUT =7'b0000000;
9: OUT =7'b0010000;
default:
OUT = 7'b0001001;
endcase
endmodule




//Alarm_Clock.v*******闹钟模块
moduleAlarm_Clock(
input CP,
input nCR,
inputEN,//0——无闹钟,1——有闹钟
input [7:0] Min,
input [4:0] Hr,
inputUpOrDown,//UpOrDown:加校正减校正0——>-,1——>+
input Set_Sel,
//Set_Sel选择设置位:0——>Min,1——>Hr;Set_EN设置校时使能
inputSet_EN,//设置时间使能
inputSel_Hr,//Sel_Hr选择小时是12还是24进制,Sel=1,24;Sel==0,12.
output  regAlarm,//闹钟输出
output [7:0]Clock_Min,//闹钟定时分钟
output [4:0]Clock_Hr//闹钟定时小时
);


reg [31:0] Times;
reg flag;
wireCPOfAlarmClock;//500Hz
wireEN_Alarm_Clock_Min;
wireEN_Alarm_Clock_Hr;
wire OneHz;


assign EN_Alarm_Clock_Min =(OneHz && EN && Set_EN &&!Set_Sel);
assign EN_Alarm_Clock_Hr =(OneHz && EN && Set_EN &&Set_Sel);


FiveHHzMakerCPForAlarmClockMaker(
.OUT(CPOfAlarmClock),
.CP(CP));
Counter60MinOfAlarm(
.Q(Clock_Min[7:0]),
.nCR(nCR),
.EN(EN_Alarm_Clock_Min),
.CP(CP),
.UpOrDown(UpOrDown));
Counter12or24HrOfAlarm(
.Q(Clock_Hr[4:0]),
.nCR(nCR),
.EN(EN_Alarm_Clock_Hr),
.CP(CP),
.Sel(Sel_Hr),
.UpOrDown(UpOrDown));


OneHzMakerOneHzForAlarmClock(
.Q(OneHz),
.CP(CP));


initial begin
Times = 0;
flag = 0;
end


always @ (posedge CP)begin
if(~EN )
Alarm <= 0;
else begin
if((Min == Clock_Min)&& (Hr == Clock_Hr ) && OneHz )
flag <=1;
if(CPOfAlarmClock &&(flag == 1)) begin
if(Times > 100000000) begin
Times <= 0;
flag <= 0;
Alarm <= 0;
end
else begin
Times <= Times+1;
Alarm <=~Alarm;
end
end
end
end
endmodule


//500Hz****FiveHHzMaker.v
moduleFiveHHzMaker(
output reg OUT,
input CP );
reg [24:0]counter;
initialbegin
counter = 0;
OUT = 0;
end


always @(posedgeCP)begin
if( counter == 49999)begin
OUT <= ~OUT;
counter <= 0;
end
else
counter <= counter +1;
end
endmodule



//LED.v****整点报时
module LED(
input CP,
input EN,
input [4:0] Hr,
input [7:0] Min,
input [7:0] Sec,
output  regLED);
wire OneHz;
reg [5:0] Times ;
reg flag ;


OneHzMakerOneHzForLED(
.Q(OneHz),
.CP(CP));
initialbegin
Times =0;
flag =0;
LED <=0;
end


always @(posedgeCP)begin
if(~EN)
LED <=0;
else begin
if(!Min &&!Sec)
flag <= 1;
if(flag == 1)begin
if(OneHz == 1 && Times>=2*Hr ) begin
Times <= 0;
flag <= 0;
LED <= 0;
end
elsebegin
if(OneHz ==1)begin
LED <= ~LED;
Times <= Times+1;
end
end
end
end
end
endmodule



不知道为什么新浪博文会把格式打乱,发表出来的排版空格效果跟写的有点不一样。。。白白按照苏豪的要求改了半天。。。




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:86421 发表于 2015-10-12 20:43 | 只看该作者
这是高手呀
回复

使用道具 举报

板凳
ID:1051745 发表于 2023-5-11 23:24 来自手机 | 只看该作者
您好 请问您的激励文件是怎么写的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表