這個實驗先自己做了一次,功能可以全部實現,由于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
不知道為什么新浪博文會把格式打亂,發表出來的排版空格效果跟寫的有點不一樣。。。白白按照蘇豪的要求改了半天。。。
|