EDA数字钟(三)


前言

再次编写数字钟Verilog程序,使其符合规范,并采用模板化与模块化编程,使程序思路更加清晰。与之前不同,此次编程在Quartus II 13.0中建立项目,在AX530开发板上下载调试,引脚定义与配置需要视情况更改,项目文件将上传到资源中。


一、设计内容

设计功能与之前保持一致:
1.具有“秒”、“分”、“时”计时的功能,小时计数器按24小时制;
2.具有校时功能,能对“分”和“时”进行调整;
3.具有手动输入设置定时闹钟的功能,亮1分钟;
4.可实现时钟复位功能:00:00:00;
5.报整点:几点亮几下。
AX530开发板有六个数码管,没有拨码开关,为与之前保持一致,仅使用其中四个数码管,用按键切换显示内容。

二、模块结构

根据输入和输出划分模块,顶层模块仅实现模块间的连接,状态控制模块控制当前显示内容,计时模块实现计时、校时、秒针输出、整点报时功能,闹钟模块实现定时闹钟的设置与输出,显示模块根据当前工作模式确定显示的内容。

三、代码编写

1、顶层模块Digclk

顶层模块尽量减少逻辑,只用作模块连接,根据输出内容划分模块功能

/***************数字钟顶层模块***************/
module Digclk(
    clk,
    rst_n,
    btn,
    led,
    smg_sig,
    smg_loc
    );

    //输入输出
    input                clk;
    input                rst_n;
    input      [2:0]     btn;
    output     [3:0]     led;
    output     [7:0]     smg_sig;
    output     [5:0]     smg_loc;
    wire       [2:0]     led;
    wire       [7:0]     smg_sig;
    wire       [5:0]     smg_loc;

    /***************状态控制模块***************/
    wire [1:0] mode;
    wire [3:0] set_loc;
    wire set_inc;
    Ctrl U_ctrl(
        .clk(clk),
        .rst_n(rst_n),
        .swc_btn(btn[2]),//切换按键
        .mov_btn(btn[1]),//移位按键
        .inc_btn(btn[0]),//加一按键
        .mode(mode),//工作状态
        .set_loc(set_loc),//位置信号
        .set_inc(set_inc)//加一信号
    );
    /***************计时模块***************/
    wire [23:0] time_data;
    Time U_time(
        .clk(clk),
        .rst_n(rst_n),
        .mode(mode),
        .set_loc(set_loc),
        .set_inc(set_inc),
        .time_data(time_data),
        .sec(led[0]),//秒针LED
        .hour(led[2])//整点报时
    );
    /***************闹钟模块***************/
    wire [15:0] alm_data;
    Alarm U_alarm(
        .clk(clk),
        .rst_n(rst_n),
        .mode(mode),
        .set_loc(set_loc),        
        .set_inc(set_inc),
        .time_data(time_data),
        .alm_data(alm_data),
        .alm(led[1])//定时闹钟
    );
    /***************显示模块***************/
    Display U_display(
        .clk(clk),
        .rst_n(rst_n),
        .mode(mode),
        .time_data(time_data),
        .alm_data(alm_data),
        .set_loc(set_loc),
        .smg_sig(smg_sig),//数码管信号
        .smg_loc(smg_loc)//数码管位置
    );

    endmodule

2、状态控制模块Ctrl

通过消抖模块处理按键信息,输出当前的工作状态与校时操作信号与位置

/***************状态控制模块***************/
module Ctrl(
    clk,
    rst_n,
    swc_btn,//切换按键
    mov_btn,//移位按键
    inc_btn,//加一按键
    mode,//工作状态
    set_loc,//位置信号
    set_inc//加一信号
    );

    //输入输出
    input                clk;
    input                rst_n;
    input                swc_btn;
    input                mov_btn;
    input                inc_btn;
    output     [1:0]     mode;
    output     [3:0]     set_loc;
    output               set_inc;
    reg        [1:0]     mode;
    reg        [3:0]     set_loc;
    wire                 set_inc;

    /***************按键消抖***************/
    wire swc_btn_f;
    wire mov_btn_f;
    wire inc_btn_f;
    Filter U_filter1(
        .clk(clk),
        .rst_n(rst_n),
        .btn(swc_btn),
        .btn_f(swc_btn_f)
    );
    Filter U_filter2(
        .clk(clk),
        .rst_n(rst_n),
        .btn(mov_btn),
        .btn_f(mov_btn_f)
    );
    Filter U_filter3(
        .clk(clk),
        .rst_n(rst_n),
        .btn(inc_btn),
        .btn_f(inc_btn_f)
    );
    /***************工作状态***************/
    wire en_mode;
    wire co_mode;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            mode <= 0;
        end
        else if(en_mode)begin
            if(co_mode)
                mode <= 0;
            else
                mode <= mode + 1;
        end
    end
    assign en_mode = swc_btn_f;       
    assign co_mode = (en_mode) && (mode == 2);   
    /***************位置信号***************/
    reg [3:0] cnt_loc;
    wire en_loc;
    wire co_loc;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_loc <= 0;
        end
        else if(en_loc)begin
            if(co_loc)
                cnt_loc <= 0;
            else
                cnt_loc <= cnt_loc + 1;
        end
    end
    assign en_loc = mov_btn_f || swc_btn_f;       
    assign co_loc = (en_loc) && ((cnt_loc == 4) || swc_btn_f);   

    always@(*)begin
        case(cnt_loc)
            0: set_loc = 4'b0000;
            1: set_loc = 4'b1000;
            2: set_loc = 4'b0100;
            3: set_loc = 4'b0010;
            4: set_loc = 4'b0001;
            default: set_loc = 4'b0000;
        endcase
    end
    /***************加一信号***************/
    assign set_inc = inc_btn_f;

    endmodule

3、按键消抖模块Filter

间隔一段时间采样,将按键的下降沿转化为一个clk的脉冲输出,可作为基本模块使用

/***************按键消抖模块***************/
module Filter(
    clk,
    rst_n,
    btn,
    btn_f
    );

    //参数定义
    parameter  CNT_200MS = 24'd9_999_999;
    parameter  CNT_200NS = 24'd9;
    //输入输出
    input                clk;
    input                rst_n;
    input                btn;
    output               btn_f;
    wire                 btn_f;

    /***************间隔200ms***************/
    reg [23:0] cnt;
    wire en;
    wire co;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 0;
        end
        else if(en)begin
            if(co)
                cnt <= 0;
            else
                cnt <= cnt + 1;
        end
    end
    assign en = 1;       
    assign co = (en) && (cnt == CNT_200MS);   
    /***************buf1***************/
    reg btn_buf1;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            btn_buf1 <= 0;
        end
        else begin
            if(co)
                btn_buf1 <= btn;
        end
    end
    /***************buf2***************/
    reg btn_buf2;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            btn_buf2 <= 0;
        end
        else begin
            btn_buf2 <= btn_buf1;
        end
    end
    /***************输出正脉冲***************/
    assign btn_f = (!btn_buf1) && (btn_buf2);

    endmodule

4、计时模块Time

使用六个计数器进行时分秒的计时,将加一信号接入使能信号实现校时功能
整点报时和秒针功能也可以单独划分为一个模块

/***************计时模块***************/
module Time(
    clk,
    rst_n,
    mode,
    set_loc,
    set_inc,
    time_data,
    sec,
    hour
    );

    //参数定义
    parameter  CNT_1S = 26'd49_999_999;
    parameter  CNT_1US = 26'd49;
    //输入输出
    input                clk;
    input                rst_n;
    input      [1:0]     mode;
    input      [3:0]     set_loc;
    input                set_inc;
    output     [23:0]    time_data;
    output               sec;
    output               hour;
    wire       [23:0]    time_data;
    reg                  sec;
    reg                  hour;

    /***************校时***************/
    wire set_state;
    assign set_state = ((mode == 0) || (mode == 1)) && (set_loc != 0);
    reg [5:0] inc;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            inc <= 0;
        end
        else begin
            if((mode == 0) && set_inc)
                inc <= {set_loc, 2'b00};
            else if((mode == 1) && set_inc)
                inc <= {2'b00, set_loc};
            else 
                inc <= 0;
        end
    end
    /***************分频***************/
    reg [25:0] cnt_div;
    wire en_div;
    wire co_div;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_div <= 0;
        end
        else if(en_div)begin
            if(co_div)
                cnt_div <= 0;
            else
                cnt_div <= cnt_div + 1;
        end
    end
    assign en_div = !set_state;       
    assign co_div = (en_div) && (cnt_div == CNT_1S);   
    /***************秒个位***************/
    reg [3:0] cnt_s0;
    wire en_s0;
    wire co_s0;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_s0 <= 0;
        end
        else if(en_s0)begin
            if(co_s0)
                cnt_s0 <= 0;
            else
                cnt_s0 <= cnt_s0 + 1;
        end
    end
    assign en_s0 = co_div || inc[0];       
    assign co_s0 = (en_s0) && (cnt_s0 == 9);   
    /***************秒十位***************/
    reg [3:0] cnt_s1;
    wire en_s1;
    wire co_s1;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_s1 <= 0;
        end
        else if(en_s1)begin
            if(co_s1)
                cnt_s1 <= 0;
            else
                cnt_s1 <= cnt_s1 + 1;
        end
    end
    assign en_s1 = co_s0 || inc[1];       
    assign co_s1 = (en_s1) && (cnt_s1 == 5); 
    /***************分个位***************/
    reg [3:0] cnt_m0;
    wire en_m0;
    wire co_m0;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_m0 <= 0;
        end
        else if(en_m0)begin
            if(co_m0)
                cnt_m0 <= 0;
            else
                cnt_m0 <= cnt_m0 + 1;
        end
    end
    assign en_m0 = co_s1 || inc[2];      
    assign co_m0 = (en_m0) && (cnt_m0 == 9);   
    /***************分十位***************/
    reg [3:0] cnt_m1;
    wire en_m1;
    wire co_m1;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_m1 <= 0;
        end
        else if(en_m1)begin
            if(co_m1)
                cnt_m1 <= 0;
            else
                cnt_m1 <= cnt_m1 + 1;
        end
    end
    assign en_m1 = co_m0 || inc[3];      
    assign co_m1 = (en_m1) && (cnt_m1 == 5); 
    /***************时个位***************/
    reg [3:0] cnt_h0;
    reg [3:0] cnt_h1;
    wire en_h0;
    wire co_h0;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_h0 <= 0;
        end
        else if(en_h0)begin
            if(co_h0)
                cnt_h0 <= 0;
            else
                cnt_h0 <= cnt_h0 + 1;
        end
    end
    assign en_h0 = co_m1 || inc[4];      
    assign co_h0 = (en_h0) && ((cnt_h0 == 9) || (((cnt_h1 == 2) && ((cnt_h0 == 3)))));   
    /***************时十位***************/
    wire en_h1;
    wire co_h1;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_h1 <= 0;
        end
        else if(en_h1)begin
            if(co_h1)
                cnt_h1 <= 0;
            else
                cnt_h1 <= cnt_h1 + 1;
        end
    end
    assign en_h1 = co_h0 || inc[5];      
    assign co_h1 = (en_h1) && ((((cnt_h1 == 2) && ((cnt_h0 >= 3)))) || ((cnt_h1 >= 2) && inc[5]));
    assign time_data = {cnt_h1, cnt_h0, cnt_m1, cnt_m0, cnt_s1, cnt_s0};
    /***************整点报时***************/
    reg flag_hour;
    reg [5:0] cnt_hour;
    wire en_hour;
    wire co_hour;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_hour <= 0;
        end
        else begin
            if(en_hour)begin
                if(co_hour)
                    cnt_hour <= 0;
                else
                    cnt_hour <= cnt_hour + 1;
            end
        end
    end
    assign en_hour = ({cnt_h1, cnt_h0} != 0) && ({cnt_m1, cnt_m0} == 0) && flag_hour && co_div;
    assign co_hour = (en_hour) && (cnt_hour >= (2 * (10 * cnt_h1 + cnt_h0) - 1));   

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            flag_hour <= 1;
        end
        else begin
            if(co_hour)
                flag_hour <= 0;
            else if({cnt_m1, cnt_m0} != 0)
                flag_hour <= 1;
        end
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            hour <= 1;
        end
        else begin
            if(set_state == 1)
                hour <= 1;
            else if(({cnt_h1, cnt_h0} != 0) && ({cnt_m1, cnt_m0} == 0) && flag_hour)
                hour <= cnt_hour[0];
        end
    end
    /***************秒针***************/
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            sec <= 1;
        end
        else begin
            if(set_state == 1)
                sec <= 1;
            else
                sec <= cnt_s0[0];
        end
    end

    endmodule

5、闹钟模块Alarm

闹钟设置与校时功能相似
将计时时间与闹钟时间比较输出闹钟信号

/***************闹钟模块***************/
module Alarm(
    clk,
    rst_n,
    mode,
    set_loc,        
    set_inc,
    time_data,
    alm_data,
    alm
    );

    //输入输出
    input                clk;
    input                rst_n;
    input      [1:0]     mode;
    input      [3:0]     set_loc;
    input                set_inc;
    input      [23:0]    time_data;
    output     [23:0]    alm_data;
    output               alm;
    wire       [23:0]    alm_data;
    reg                  alm;

    /***************校时***************/
    reg [3:0] inc;
    always@(*)begin
        if((mode == 2) && set_inc)
            inc = set_loc;
        else
            inc = 4'b0000;
    end
    /***************分个位***************/
    reg [3:0] cnt_m0;
    wire en_m0;
    wire co_m0;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_m0 <= 0;
        end
        else if(en_m0)begin
            if(co_m0)
                cnt_m0 <= 0;
            else
                cnt_m0 <= cnt_m0 + 1;
        end
    end
    assign en_m0 = inc[0];      
    assign co_m0 = (en_m0) && (cnt_m0 == 9);   
    /***************分十位***************/
    reg [3:0] cnt_m1;
    wire en_m1;
    wire co_m1;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_m1 <= 0;
        end
        else if(en_m1)begin
            if(co_m1)
                cnt_m1 <= 0;
            else
                cnt_m1 <= cnt_m1 + 1;
        end
    end
    assign en_m1 = co_m0 || inc[1];      
    assign co_m1 = (en_m1) && (cnt_m1 == 5); 
    /***************时个位***************/
    reg [3:0] cnt_h0;
    reg [3:0] cnt_h1;
    wire en_h0;
    wire co_h0;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_h0 <= 0;
        end
        else if(en_h0)begin
            if(co_h0)
                cnt_h0 <= 0;
            else
                cnt_h0 <= cnt_h0 + 1;
        end
    end
    assign en_h0 = co_m1 || inc[2];      
    assign co_h0 = (en_h0) && ((cnt_h0 == 9) || (((cnt_h1 == 2) && ((cnt_h0 == 3)))));   
    /***************时十位***************/
    wire en_h1;
    wire co_h1;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_h1 <= 0;
        end
        else if(en_h1)begin
            if(co_h1)
                cnt_h1 <= 0;
            else
                cnt_h1 <= cnt_h1 + 1;
        end
    end
    assign en_h1 = co_h0 || inc[3];      
    assign co_h1 = (en_h1) && ((((cnt_h1 == 2) && ((cnt_h0 >= 3)))) || ((cnt_h1 >= 2) && inc[3]));

    assign alm_data = {cnt_h1, cnt_h0, cnt_m1, cnt_m0};
    /***************输出***************/
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            alm <= 1;
        end
        else begin
            if(set_loc != 0)
                alm <= 1;
            else if(time_data[23:8] == alm_data)
                alm <= 0;
            else
                alm <= 1;
        end
    end 

    endmodule

6、显示模块Display

根据当前工作模式确定显示内容

/***************显示模块***************/
module Display(
    clk,
    rst_n,
    mode,
    time_data,
    alm_data,
    set_loc,
    smg_sig,
    smg_loc
    );

    //输入输出
    input                clk;
    input                rst_n;
    input      [1:0]     mode;
    input      [23:0]    time_data;
    input      [15:0]    alm_data;
    input      [3:0]     set_loc;
    output     [7:0]     smg_sig;
    output     [5:0]     smg_loc;
    wire       [7:0]     smg_sig;
    wire       [5:0]     smg_loc;

    /***************取数***************/
    reg [15:0] show_data;
    wire [23:0] num_data;
    wire [5:0] dot_data;
    always@(*)begin
        case(mode)
            0: show_data = time_data[23:8];
            1: show_data = time_data[15:0];
            2: show_data = alm_data;
            default: show_data = 0;
        endcase
    end
    assign num_data = {8'b00000000, show_data};
    assign dot_data = {2'b00, set_loc};
    /***************数码管驱动***************/
    Smg U_smg(
        .clk(clk),
        .rst_n(rst_n),
        .num_data(num_data),
        .dot_data(dot_data),
        .smg_sig(smg_sig),
        .smg_loc(smg_loc)
    );

    endmodule

7、数码管驱动模块Smg

带小数点的数码管驱动模块,可作为基本模块使用

/***************显示模块***************/
module Smg(
    clk,
    rst_n,
    num_data,
    dot_data,
    smg_sig,
    smg_loc
    );

    //参数定义
    parameter  CNT_2MS = 17'd99_999;
    parameter  CNT_200NS = 17'd9;
    //输入输出
    input                clk;
    input                rst_n;
    input      [23:0]    num_data;
    input      [5:0]     dot_data;
    output     [7:0]     smg_sig;
    output     [5:0]     smg_loc;
    reg        [7:0]     smg_sig;
    reg        [5:0]     smg_loc;
    
    /***************分频***************/
    reg [16:0] cnt_div;
    wire en_div;
    wire co_div;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_div <= 0;
        end
        else if(en_div)begin
            if(co_div)
                cnt_div <= 0;
            else
                cnt_div <= cnt_div + 1;
        end
    end
    assign en_div = 1;       
    assign co_div = (en_div) && (cnt_div == CNT_2MS);   
    /***************扫描***************/
    reg [3:0] cnt_scan;
    wire en_scan;
    wire co_scan;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_scan <= 0;
        end
        else if(en_scan)begin
            if(co_scan)
                cnt_scan <= 0;
            else
                cnt_scan <= cnt_scan + 1;
        end
    end
    assign en_scan = co_div;       
    assign co_scan = (en_scan) && (cnt_scan == 5);
    /***************取数***************/
    reg [3:0] smg_data;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            smg_data <= 0;
        end
        else begin
            case(cnt_scan)
                0: smg_data <= num_data[3:0];
                1: smg_data <= num_data[7:4];
                2: smg_data <= num_data[11:8];
                3: smg_data <= num_data[15:12];
                4: smg_data <= num_data[19:16];
                5: smg_data <= num_data[23:20];
            endcase
        end
    end
    /***************显示***************/
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            smg_loc <= 6'b000000;
        end
        else begin
            case(cnt_scan)
                0: smg_loc <= 6'b111110;
                1: smg_loc <= 6'b111101;
                2: smg_loc <= 6'b111011;
                3: smg_loc <= 6'b110111;
                4: smg_loc <= 6'b101111;
                5: smg_loc <= 6'b011111;
            endcase
        end
    end
    /***************译码***************/
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            smg_sig <= 8'b00000011;
        end
        else begin
            case(smg_data)
                0: smg_sig[7:1] = 7'b0000001;
		        1: smg_sig[7:1] = 7'b1001111;
		        2: smg_sig[7:1] = 7'b0010010;
		        3: smg_sig[7:1] = 7'b0000110;
		        4: smg_sig[7:1] = 7'b1001100;
		        5: smg_sig[7:1] = 7'b0100100;
		        6: smg_sig[7:1] = 7'b0100000;
		        7: smg_sig[7:1] = 7'b0001111;
		        8: smg_sig[7:1] = 7'b0000000;
		        9: smg_sig[7:1] = 7'b0000100;
		        default: smg_sig[7:1] = 7'b0110000;//E
            endcase
            smg_sig[0] <= ~dot_data[cnt_scan];
        end
    end

endmodule

四、测试文件

测试文件在之前的基础上进行修改

`timescale 1 ns/ 1 ns

module Digclk_tb();
reg [2:0] btn;
reg clk;
reg rst_n;                                     
wire [2:0]  led;
wire [5:0]  smg_loc;
wire [7:0]  smg_sig;
    
//模拟按键按下
task SWC;
    begin
        #1000 btn[2] = 0;
        #1000 btn[2] = 1;
    end
endtask
task MOV;
    begin
        #1000 btn[1] = 0;
        #1000 btn[1] = 1;
    end
endtask
task INC;
    begin
        #1000 btn[0] = 0;
        #1000 btn[0] = 1;
    end
endtask
    
Digclk u1 (
	.btn(btn),
	.clk(clk),
	.led(led),
	.rst_n(rst_n),
	.smg_loc(smg_loc),
	.smg_sig(smg_sig)
);
initial begin
    clk = 0;
    rst_n = 1;
end

always begin
    #10 clk = ~clk;
end

initial begin
    // Initialize Inputs
    rst_n = 1;
    btn = 3'b111;

    // Wait 200 ns for global rst_n to finish
    #100 rst_n = 0;
    #100 rst_n = 1;
    
    // Add stimulus here
//////////////////////////////////////////////闹钟测试 
    //闹钟置数1200,闹钟指针1000
    INC;//空加
    repeat(2) SWC;//2
    MOV;
    repeat(4) INC;//1
    MOV;
    repeat(2) INC;//2
//////////////////////////////////////////////校时测试
    //时分置数1159
    //置数模式
    #10000;
    SWC;
    MOV;
    INC;//1
    MOV;
    INC;//1
    MOV;
    repeat(5) INC;//5
    MOV;
    repeat(9) INC;//9    
    //秒置数58
    SWC;   
    #10000;
    repeat(3) MOV;
    repeat(1) INC;//5
    MOV;
    repeat(1) INC;//8
    MOV;
//////////////////////////////////////////////状态切换测试
    //显示分秒
    #10000;
    SWC;
    //显示闹钟
    #10000;
    SWC;
//////////////////////////////////////////////清零测试
    //清零
    #10000 rst_n = 0;
    #10000 rst_n = 1;
//////////////////////////////////////////////进位测试
    //分置数59
    SWC;
    MOV;
    repeat(5) INC;//5
    MOV;
    repeat(8) INC;//8
    //时置数23
    repeat(2) SWC;
    #10000 
    MOV;
    repeat(5) INC;//2
    MOV;
    repeat(3) INC;//3
    SWC;
//////////////////////////////////////////////防抖测试
    #10000 btn[2] = 0;//忽略
    #10 btn[2] = 1;
    #30 btn[2] = 0;//触发
    #1000 btn[2] = 1;
    #50 btn[2] = 0;//忽略
    #70 btn[2] = 1;
    #1000 btn[2] = 0;//触发
    #1000 btn[2] = 1;
end

endmodule

五、波形仿真

1、变量名称说明
rst_n:清零按键;
btn[2:0]:切换、移位、加一按键;
xxx_btn_f:经过消抖模块后的按键信号;
mode:工作模式(0:时分,1:分秒,2:闹钟)
time_data:计时时间;
alm_data:闹钟时间;
num_data:显示内容;
smg_loc:数码管位置;
smg_data:数码管数据;
smg_sig:数码管信号;
set_loc:操作位置;
dot_data:小数点信息;
led[2:0]:整点报时LED、闹钟LED,秒LED。

2、闹钟设置测试
将闹钟设置为12:00

3、时钟校时测试
将时钟设置为11:59:58

4、闹钟、整点报时测试
到12:00闹钟响一分钟,整点报时闪12下

5、显示内容测试
切换工作状态,分别显示时分、分秒、闹钟

6、复位测试

7、进位测试
设置计时值为23:59:23,测试数字钟进位

8、消抖测试
对按键btn[2]进行消抖测试,将其转化为swc_btn_f

总结

程序在AX530开发板上实测通过
逻辑部分做了部分改动,主要是为了方便操作
控制模块本来打算用状态机写的,但后来发现没有必要
单独写一个控制模块总感觉有些奇怪
校时的逻辑还是有些混乱,包括整点报时也可以再改改

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: EDA数字钟是一款24小时制的计时钟,可以精确到分钟和秒。它采用了先进的电子数字显示技术,使时间的读取更加清晰和方便。 使用EDA数字钟进行计时非常简单。首先,我们需要设置钟表的当前时间。通常,这可以通过按下设定按钮并根据提示设置小时、分钟和秒来完成。 一旦完成设置,EDA数字钟会自动开始计时。屏幕上的数字将以秒为单位递增,同时分钟和小时也会相应变化。这样,我们可以很容易地了解到经过的时间。 另外,EDA数字钟还配有一些实用的功能。比如,它可以通过按下暂停按钮来暂停计时,以便在需要的时候停止时钟的计时。此外,它还可以通过按下重置按钮将计时器重置为0,以便重新开始计时。 总的来说,EDA数字钟作为一款24小时制的计时器,具有精确计时、数字显示清晰等特点,非常适合用于日常生活和工作中的计时需求。无论是在厨房计时、健身锻炼,还是其他需要时限控制的场合,EDA数字钟都能提供准确且方便的计时服务。 ### 回答2: EDA数字钟是一款具备24小时计时功能的时钟。它不仅能够显示时、分、秒,还能够准确地计时到分和秒。 首先,EDA数字钟采用数字显示,以方便人们快速、直观地读取时间。它通常由七段显示器组成,可以显示0-9的数字。因此,每个数字都可以通过七段显示器的亮灭组合来显示出来。 其次,EDA数字钟具备24小时计时功能。它显示的时间范围从00:00:00到23:59:59,以整点或者分秒为基准进行计时。例如,当时钟显示为15:45:30时,表示当前时间是下午3点45分30秒。 最后,EDA数字钟的计时精确度很高。它使用具有高精度的计时器,能够准确测量分和秒的流逝。无论是计时一段较短的时间,还是计时一整天的时间,EDA数字钟都能提供准确的计时结果。 总而言之,EDA数字钟是一款24小时计时的时钟,它以数字显示的方式展示时间,并且具备高精确度的计时功能。无论是日常生活中的时间管理,还是一些需要精确计时的场合,EDA数字钟都能够满足人们的需求。 ### 回答3: EDA数字钟是一款具有24小时制的计时功能的数字钟。它使用分和秒来表示时间,并且可以进行倒计时。 对于24小时制,每天被分为24个小时,每个小时有60分钟,每分钟有60秒。而EDA数字钟使用分和秒来展示时间,以及进行倒计时。它的显示屏通常具有大号数字和清晰的显示,以便用户可以轻松读取。 当使用EDA数字钟进行计时时,它会以分和秒的形式显示时间。例如,如果时间是12:34:56,那么EDA数字钟的显示屏上会显示12分34秒56。这种直观的方式使得人们能够迅速了解当前的时间,并进行相关的操作。 此外,EDA数字钟还可以进行倒计时。用户可以设置一个特定的时间,然后EDA数字钟会自动开始倒计时,并在倒计时结束时发出警报。这样,人们可以方便地使用EDA数字钟来进行各种计时活动,如烹饪、运动比赛等等。 总结而言,EDA数字钟是一种具有24小时制的计时功能的数字钟,使用分和秒来表示时间,并能进行倒计时。它的设计直观简单,易于使用,让人们能够方便地了解当前时间,并进行各种计时活动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值