您的位置:首页 > 其它

基于BASYS 2开发板的多功能数字钟Verilog程序

2017-04-12 20:18 501 查看

写在最前:

纸上得来终觉浅,绝知此事要编程!

一、实验目的

用 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

4000
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;


三、仿真截图





实验感悟

固然实验要花费很长时间,然而要想提高能力没有捷径可走,共勉!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐