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

写在最前:

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

一、实验目的

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

三、仿真截图

基于BASYS 2开发板的多功能数字钟Verilog程序_第1张图片

基于BASYS 2开发板的多功能数字钟Verilog程序_第2张图片

实验感悟

固然实验要花费很长时间,然而要想提高能力没有捷径可走,共勉!

你可能感兴趣的:(编程)