纸上得来终觉浅,绝知此事要编程!
用 EDA 技术设计多功能数字钟
能够实现任意设定闹铃时间,到达闹钟时间时闹钟持续响一分钟
能够对小时进行12/24进制切换,并用LED指示AM和PM
整点报时,从整点零分一秒开始,奇数秒亮LED,偶数秒熄灭,几点钟LED闪烁几下。如果是12小时进制的显示情况下,需要按照24小时进制下面的计数进行报时,零点或者下午12点都需要报时24下,报时完毕LED熄灭
利用ISE软件对其进行仿真,并给出各功能实现关键点的截图和解释
//******************* my_Clock.v ***********************
module my_Clock(
input CLK_50, // 50MHz clock
input nCR, EN, // reset, enable
input Adj_Min, Adj_Hour, // adjust signal of minute and hour
input Set_Alarm, // decide whether to set alarm clock
input Set_Min, Set_Hour, // set signal of alarm clock
output Clock, // alarm control signal
output [5:0] Second_B, // binary code of second
output [3:0] Bit, // position
output [7:0] Seg, // number
input Set_count, // decide 12 counting or 24 counting
output AP, // AM or PM
output Int_time // integral time accounce
);
//============ Parameters =========================
wire [7:0] Hour, Minute, Second; // time
supply1 Vdd; // logical true
wire MinL_EN, MinH_EN, Hour_EN; // enable signal
wire CP_1Hz; // freq 1Hz
wire CP_200Hz; // freq 100Hz
wire [7:0] HEX2, HEX3, HEX4, HEX5;
wire [7:0] C_Hour, C_Minute; // clock time
wire C_MinL_EN, C_MinH_EN;
wire C_Hour_EN;
wire [7:0] B_Hour; // 12 counting
wire [7:0] CB_Hour; // 12 counting for clock time
wire [5:0] Hour_B; // binary code of 12 counting hour
wire [5:0] Hour_24;
//============ Divider50MHz ========================
// divide 50MHz to 1Hz
Divider50MHz U0 (.CLK_50M(CLK_50),
.nCLR(nCR),
.CLK_1Hzout(CP_1Hz));
defparam U0.N = 25,
U0.CLK_Freq = 50000000,
U0.OUT_Freq = 1;
// divide 50MHz to 100Hz
Divider50MHzto100Hz X0 (.CLK_50M(CLK_50),
.nCLR(nCR),
.CLK_200Hzout(CP_200Hz));
defparam X0.N = 25,
X0.CLK_Freq = 50000000,
X0.OUT_Freq = 200;
//========== Hour & Minute & Second counter ========
// Second counter
counter10 S0 (Second[3:0], nCR, EN, CP_1Hz);
counter6 S1 (Second[7:4], nCR, (Second[3:0] == 4'h9), CP_1Hz);
// Change Second to binary code
change_B S2 (Second[7:0], Second_B[5:0]);
// Minute counter
counter10 M0 (Minute[3:0], nCR, MinL_EN, CP_1Hz);
counter6 M1 (Minute[7:4], nCR, MinH_EN, CP_1Hz);
// assign enable signal
assign MinL_EN = Adj_Min?Vdd:(Second == 8'h59); // we can adjust M0 by using Adj_Min
assign MinH_EN = (Adj_Min && (Minute[3:0] == 4'h9)) // the conditions which add 1 to M1
|| ((Minute[3:0] == 4'h9) && (Second == 8'h59));
// Hour counter (24 counting)
counter24 H0(Hour[7:4], Hour[3:0], nCR, Hour_EN, CP_1Hz);
// Hour counter (12 counting)
counter12 P0(B_Hour[7:4], B_Hour[3:0], nCR, Hour_EN, CP_1Hz);
// assign enable signal
assign Hour_EN = Adj_Hour?Vdd:((Minute == 8'h59) && (Second == 8'h59));
// AM or PM
// initial AP = 0;
change_B S3 (Hour[7:0], Hour_B[5:0]); // change hour to be binary code
assign AP = (Hour_B > 5'b01011)?0:1; // AM: AP = 1 PM: AP = 0
//============ Set Alarm clock ======================
// Minute counter
counter10 M2 (C_Minute[3:0], nCR, C_MinL_EN, CP_1Hz);
counter6 M3 (C_Minute[7:4], nCR, C_MinH_EN, CP_1Hz);
// assign enable signal
assign C_MinL_EN = (Set_Min && Set_Alarm);
assign C_MinH_EN = (Set_Min && (C_Minute[3:0] == 4'h9) && Set_Alarm);
// Hour counter (24 counting)
counter24 H1(C_Hour[7:4], C_Hour[3:0], nCR, C_Hour_EN, CP_1Hz);
// Hour counter (12 counting)
counter12 P1(CB_Hour[7:4], CB_Hour[3:0], nCR, C_Hour_EN, CP_1Hz);
// assign enable signal
assign C_Hour_EN = (Set_Alarm && Set_Hour)?Vdd:(Set_Alarm && C_Minute == 8'h59 && Set_Min);
// compare time
Compare_time C1 (CP_1Hz, C_Hour, C_Minute, Hour, Minute, Time_EQ);
// Clock go on!
assign Clock = Time_EQ;
//============ Integral time announce ===============
// change 24
change_24 C2 (Hour_B[5:0], Hour_24[5:0]);
// time announce
Int_Clock I0 (Hour_24[5:0], Minute[7:0], Second_B[5:0], CP_1Hz, T);
// go on!
assign Int_time = T;
//============ appear on the Basys2 =================
// seven-code transition
//SEG7_LUT u1 (HEX0, Second[3:0]);
//SEG7_LUT u2 (HEX1, Second[7:4]);
SEG7_LUT u3 (HEX2, Set_Alarm, Minute[3:0], C_Minute[3:0]);
SEG7_LUT u4 (HEX3, Set_Alarm, Minute[7:4], C_Minute[7:4]);
SEG7_LUT_H u5 (HEX4, Set_Alarm, Set_count, Hour[3:0], C_Hour[3:0], B_Hour[3:0], CB_Hour[3:0]);
SEG7_LUT_H u6 (HEX5, Set_Alarm, Set_count, Hour[7:4], C_Hour[7:4], B_Hour[7:4], CB_Hour[7:4]);
// dynamic scanning
Dynamic_Scan D1(CP_200Hz,HEX2,HEX3,HEX4,HEX5,nCR,Seg,Bit);
endmodule
分频器:50MHz —> 1Hz
module Divider50MHz(CLK_50M, nCLR, CLK_1Hzout);
parameter N = 25; // 位宽
parameter CLK_Freq = 50000000; // 50MHz input
parameter OUT_Freq = 1; // 1Hz output
input nCLR, CLK_50M;
output reg CLK_1Hzout;
initial CLK_1Hzout = 0;
reg [N-1:0] Count_DIV;
initial Count_DIV = 0;
always @(posedge CLK_50M or negedge nCLR)
begin
if (!nCLR)
begin
CLK_1Hzout <= 0;
Count_DIV <= 0;
end
else
begin
if(Count_DIV < (CLK_Freq / (2*OUT_Freq) - 1))
Count_DIV <= Count_DIV + 1'b1;
else
begin
Count_DIV <= 0;
CLK_1Hzout <= ~CLK_1Hzout;
end
end
end
endmodule
分频器: 50MHZ —> 200Hz
module Divider50MHzto100Hz(CLK_50M, nCLR, CLK_200Hzout);
parameter N = 25; // 位宽
parameter CLK_Freq = 50000000; // 50MHz input
parameter OUT_Freq = 200; // 200Hz output
input nCLR, CLK_50M;
output reg CLK_200Hzout;
initial CLK_200Hzout = 0;
reg [N-1:0] Count_DIV;
initial Count_DIV = 0;
always @(posedge CLK_50M or negedge nCLR)
begin
if (!nCLR)
begin
CLK_200Hzout <= 0;
Count_DIV <= 0;
end
else
begin
if(Count_DIV < (CLK_Freq / (2*OUT_Freq) - 1))
Count_DIV <= Count_DIV + 1'b1;
else
begin
Count_DIV <= 0;
CLK_200Hzout <= ~CLK_200Hzout;
end
end
end
endmodule
计数器: 逢十进一
module counter10(Q, nCR, EN, CP);
input CP, nCR, EN;
output reg [3:0] Q;
initial Q = 0;
always @(posedge CP or negedge nCR)
begin
if(~nCR)
Q <= 4'b0000; // nCR = 0, counter asynchronous reset
else if(~EN)
Q <= Q; // EN = 0, stop counting
else if(Q == 4'b1001)
Q <= 4'b0000; // cycle
else
Q <= Q + 4'b0001; // + 1
end
endmodule
计数器:逢六进一
module counter6(Q, nCR, EN, CP);
input CP, nCR, EN;
output reg [3:0] Q;
initial Q = 0;
always @(posedge CP or negedge nCR)
begin
if(~nCR)
Q <= 4'b0000; // nCR = 0, Counter asynchronous reset
else if (~EN)
Q <= Q; // EN = 0, stop counting
else if (Q == 4'b0101)
Q <= 4'b0000; // cycle
else
Q <= Q + 4'b0001;// + 1
end
endmodule
将个位十位描述方法改为二进制
module change_B(
input [7:0] Second,
output reg [5:0] Second_B
);
always @(Second) begin
Second_B = 0;
case(Second[7:4])
4'b0000:
Second_B[3:0] = Second[3:0];
4'b0001:
begin
Second_B[3:0] = Second[3:0];
Second_B = Second_B + 6'b001010;
end
4'b0010:
begin
Second_B[3:0] = Second[3:0];
Second_B = Second_B + 6'b010100;
end
4'b0011:
begin
Second_B[3:0] = Second[3:0];
Second_B = Second_B + 6'b011110;
end
4'b0100:
begin
Second_B[3:0] = Second[3:0];
Second_B = Second_B + 6'b101000;
end
4'b0101:
begin
Second_B[3:0] = Second[3:0];
Second_B = Second_B + 6'b110010;
end
endcase
end
endmodule
计数器:24进制
module counter24(CntH, CntL, nCR, EN, CP);
input CP, nCR, EN;
output reg [3:0] CntH, CntL;
always @(posedge CP or negedge nCR)
begin
if(~nCR)
{CntH, CntL} <= 8'h00; // asynchornous reset
else if(~EN)
{CntH, CntL} <= {CntH, CntL}; // stop counting
else if((CntH > 2)||(CntL >9)||((CntH == 2)&&(CntL >= 3)))
{CntH, CntL} <= 8'h00; // if error or time at 00:00
else if((CntH == 2)&&(CntL < 3))
begin
CntH <= CntH; CntL <= CntL + 1'b1;
end
else if(CntL == 9)
begin
CntH <= CntH + 1'b1; CntL <= 4'b0000;
end
else
begin
CntH <= CntH; CntL <= CntL + 1'b1;
end
end
endmodule
计数器:12进制
module counter12(CntH, CntL, nCR, EN, CP);
input CP, nCR, EN;
output reg [3:0] CntH, CntL;
always @(posedge CP or negedge nCR)
begin
if(~nCR)
{CntH, CntL} <= 8'h00; // asynchornous reset
else if(~EN)
{CntH, CntL} <= {CntH, CntL}; // stop counting
else if((CntH > 1)||(CntL >9)||((CntH == 1)&&(CntL >= 1)))
begin
{CntH, CntL} <= 8'h00; // if error or time at 00:00
end
else if((CntH == 1)&&(CntL < 1))
begin
CntH <= CntH; CntL <= CntL + 1'b1;
end
else if(CntL == 9)
begin
CntH <= CntH + 1'b1; CntL <= 4'b0000;
end
else
begin
CntH <= CntH; CntL <= CntL + 1'b1;
end
end
endmodule
比较闹钟时间和计数时间
module Compare_time(CP, Set_Hour, Set_Minute, Hour, Minute, Time_EQ);
input [7:0] Set_Hour, Set_Minute, Hour, Minute;
input CP;
output reg Time_EQ;
always @(posedge CP)
begin
if((Set_Hour == Hour) && (Set_Minute == Minute))
Time_EQ <= 1;
else
Time_EQ <= 0;
end
endmodule
将0-23改为1-24
module change_24(
input [5:0] Hour,
output reg [5:0] Hour_24
);
always @(Hour) begin
Hour_24 = Hour;
if(Hour == 0)
Hour_24 = 6'b011000;
end
endmodule
整点报时
module Int_Clock(Hour, Minute, Second, CP, Int_time);
input [5:0] Hour;
input [7:0] Minute;
input [5:0] Second;
input CP;
output reg Int_time;
always @(posedge CP)
begin
if((Minute[7:4] == 0) && (Minute[3:0] == 0))
begin
if((Hour[5:0] + Hour[5:0]) <= Second[5:0])
Int_time <= 0;
else
if(Second[0] == 0)
Int_time <= 1;
else
Int_time <= 0;
end
else
Int_time <= 0;
end
endmodule
七段译码器
module SEG7_LUT(oSEG,Set_Alarm, iDIG, C_iDIG);
input Set_Alarm;
input [3:0] C_iDIG; // input Clock time (BCD)
input [3:0] iDIG; // input time (BCD)
output reg [7:0] oSEG; // output (seven code)
always @(Set_Alarm, iDIG, C_iDIG)
begin
if(Set_Alarm == 0)
case(iDIG)
4'b0000:oSEG = 8'b0000_0011;
4'b0001:oSEG = 8'b1001_1111;
4'b0010:oSEG = 8'b0010_0101;
4'b0011:oSEG = 8'b0000_1101;
4'b0100:oSEG = 8'b1001_1001;
4'b0101:oSEG = 8'b0100_1001;
4'b0110:oSEG = 8'b0100_0001;
4'b0111:oSEG = 8'b0001_1011;
4'b1000:oSEG = 8'b0000_0001;
4'b1001:oSEG = 8'b0000_1001;
endcase
else
case(C_iDIG)
4'b0000:oSEG = 8'b0000_0011;
4'b0001:oSEG = 8'b1001_1111;
4'b0010:oSEG = 8'b0010_0101;
4'b0011:oSEG = 8'b0000_1101;
4'b0100:oSEG = 8'b1001_1001;
4'b0101:oSEG = 8'b0100_1001;
4'b0110:oSEG = 8'b0100_0001;
4'b0111:oSEG = 8'b0001_1011;
4'b1000:oSEG = 8'b0000_0001;
4'b1001:oSEG = 8'b0000_1001;
endcase
end
endmodule
动态扫描显示
module Dynamic_Scan(CP, min1, min2, h1, h2, nCR, Seg, Bit);
input [7:0] min1, min2, h1, h2;
input nCR, CP;
output reg [7:0] Seg;
output reg [3:0] Bit;
always @(posedge CP or negedge nCR)
begin
if(~nCR)
begin // asynchronous reset
Bit <= 4'b1111;
Seg <= 8'b11111111;
end
else
begin
case(Bit)
4'b1110:
begin // the light will be on when relavant bit equals to zero!
Bit <= 4'b1101;
Seg <= min1;
end
4'b1101:
begin
Bit <= 4'b1011;
Seg <= min2;
end
4'b1011:
begin
Bit <= 4'b0111;
Seg <= h1;
end
4'b0111:
begin
Bit <= 4'b1110;
Seg <= h2;
end
default:
begin
Bit <= 4'b1110;
Seg <= min1;
end
endcase
end
end
endmodule
ucf 脚本
# input
NET "CLK_50" LOC = B8;
NET "Adj_Min" LOC = G12;
NET "Adj_Hour" LOC = C11;
NET "EN" LOC = P11;
NET "nCR" LOC = L3;
# for alarm clock
NET "Set_Alarm" LOC = N3;
NET "Set_Min" LOC = M4;
NET "Set_Hour" LOC = A7;
NET "Clock" LOC = C6;
# set 12 counting or 24 counting
NET "Set_count" LOC = E2;
NET "AP" LOC = P4;
# integral time announce
NET "Int_time" LOC = G1;
# output
NET "Bit[3]" LOC = M13;
NET "Bit[2]" LOC = J12;
NET "Bit[1]" LOC = F12;
NET "Bit[0]" LOC = K14;
NET "Seg[7]" LOC = L14;
NET "Seg[6]" LOC = H12;
NET "Seg[5]" LOC = N14;
NET "Seg[4]" LOC = N11;
NET "Seg[3]" LOC = P12;
NET "Seg[2]" LOC = L13;
NET "Seg[1]" LOC = M12;
NET "Seg[0]" LOC = N13;
NET "Second_B[5]" LOC = N4;
NET "Second_B[4]" LOC = N5;
NET "Second_B[3]" LOC = P6;
NET "Second_B[2]" LOC = P7;
NET "Second_B[1]" LOC = M11;
NET "Second_B[0]" LOC = M5;
NET "CLK_50" IOSTANDARD = LVCMOS33;
NET "Adj_Min" IOSTANDARD = LVCMOS33;
NET "Adj_Hour" IOSTANDARD = LVCMOS33;
NET "Set_Min" IOSTANDARD = LVCMOS33;
NET "Set_Hour" IOSTANDARD = LVCMOS33;
NET "Set_count" IOSTANDARD = LVCMOS33;
NET "AP" IOSTANDARD = LVCMOS33;
NET "Clock" IOSTANDARD = LVCMOS33;
NET "Int_time" IOSTANDARD = LVCMOS33;
NET "EN" IOSTANDARD = LVCMOS33;
NET "nCR" IOSTANDARD = LVCMOS33;
NET "Bit[3]" IOSTANDARD = LVCMOS33;
NET "Bit[2]" IOSTANDARD = LVCMOS33;
NET "Bit[1]" IOSTANDARD = LVCMOS33;
NET "Bit[0]" IOSTANDARD = LVCMOS33;
NET "Seg[7]" IOSTANDARD = LVCMOS33;
NET "Seg[6]" IOSTANDARD = LVCMOS33;
NET "Seg[5]" IOSTANDARD = LVCMOS33;
NET "Seg[4]" IOSTANDARD = LVCMOS33;
NET "Seg[3]" IOSTANDARD = LVCMOS33;
NET "Seg[2]" IOSTANDARD = LVCMOS33;
NET "Seg[1]" IOSTANDARD = LVCMOS33;
NET "Seg[0]" IOSTANDARD = LVCMOS33;
NET "Second_B[5]" IOSTANDARD = LVCMOS33;
NET "Second_B[4]" IOSTANDARD = LVCMOS33;
NET "Second_B[3]" IOSTANDARD = LVCMOS33;
NET "Second_B[2]" IOSTANDARD = LVCMOS33;
NET "Second_B[1]" IOSTANDARD = LVCMOS33;
NET "Second_B[0]" IOSTANDARD = LVCMOS33;
NET "CLK_50" SLEW = FAST;
固然实验要花费很长时间,然而要想提高能力没有捷径可走,共勉!