EDA数字钟(三)

文章目录

  • 前言
  • 一、设计内容
  • 二、模块结构
  • 三、代码编写
    • 1、顶层模块Digclk
    • 2、状态控制模块Ctrl
    • 3、按键消抖模块Filter
    • 4、计时模块Time
    • 5、闹钟模块Alarm
    • 6、显示模块Display
    • 7、数码管驱动模块Smg
  • 四、测试文件
  • 五、波形仿真
  • 总结


前言

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/26824.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mysql的事务

MySQL中的事务是一组数据库操作&#xff0c;这些操作被视为单个逻辑单元并且被当做原子操作执行&#xff0c;这意味着它们要么全部成功&#xff0c;要么全部失败&#xff0c;没有中间状态。事务通常用于确保数据库中的数据完整性和一致性。 在MySQL中&#xff0c;事务可以使用以…

玩转css逐帧动画,努力成为更优质的Ikun~

&#x1f389; 一、前言 css3的animation想必大家都知道吧&#xff0c;那 steps 逐帧动画你知道吗&#xff1f;对于我来说&#xff0c;实际工作及练习中也很少用到这种跳跃式变化的动画&#xff0c;而它start和end的解释又比较“不说人话”&#xff0c;以前用到steps动画的时候…

Linux - 第23节 - Linux高级IO(一)

目录 1.IO的基本概念 2.钓鱼五人组 3.五种IO模型 3.1.阻塞IO 3.2.非阻塞IO 3.3.信号驱动IO 3.4.IO多路转接 3.5.异步IO 4.高级IO重要概念 4.1.同步通信 VS 异步通信 4.2.阻塞 VS 非阻塞 5.其他高级IO 6.阻塞IO 7.非阻塞IO 7.1.fcntl函数介绍 7.2.fcntl函数的使…

MobPush 推送查询API

IP绑定 工作台可以绑定服务器IP地址&#xff0c;未绑定之前所有IP均可进行REST API的调用&#xff0c;绑定后进仅绑定的IP才有调用权限。 设备信息查询接口 根据RegistrationId查询设备信息 接口地址 http://api.push.mob.com/device-v3/getById/{registrationId} 请求方式…

三种编码方式(费诺曼编码,霍夫曼编码,哈夫曼树编码)的简单解释和介绍

一. 费诺曼(Fano)编码是一种前缀编码&#xff0c;其基本原理是将出现频率较高的符号用短的编码表示&#xff0c;而出现频率较低的符号则用长的编码表示。通过这种方式进行编码&#xff0c;可以达到更好的压缩效果。 费诺曼编码的具体过程如下&#xff1a; 将要编码的符号按照…

一个小时入门 Android Compose 动画

0. 前言 前段时间对于Android中的Compose动画做了系统性的学习&#xff0c;相关文章发布在 Compose 动画 专栏里。系统性学完Compose动画后&#xff0c;又对此做了系统性的回顾&#xff0c;抽取其比较重要的部分&#xff0c;希望能帮助大家快速入门Compose动画&#xff0c;所…

ChatGPT新突破:打造自己的智能机器人控制系统

&#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是Zeeland&#xff0c;全栈领域优质创作者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 我的博客&#xff1a;Zeeland&#x1f4da; Github主页: Undertone0809 (Zeeland) (github.com)&…

【论文速览】根据人脑fMRI信号重建图像 Image Reconstruction from human brain activity

文章目录 前言文章一研究背景主要方法部分实验结果总结与思考参考资料 文章二研究背景主要方法部分实验结果总结与思考 前言 人类的视觉神经系统对于真实世界的视觉刺激有着非凡的感知与理解能力&#xff0c;比如我们能够准确地识别物体距离和三维几何关系等&#xff0c;这是当…

三维数字沙盘交互大数据可视化GIS地理信息系统第十课

三维电子沙盘交互无人机倾斜摄影大数据可视化GIS地理信息系统第十课 设置system.ini 如下内容 Server122.112.229.220 userGisTest Passwordchinamtouch.com 该数据库中只提供 成都市火车南站附近的数据请注意&#xff0c;104.0648,30.61658 在SDK中自带了一个自定义的基础面…

pycharm和virtualBox虚拟机的安装(包括本地环境和远程环境配置)

目录 一、安装时需要的软件二、安装virtualBox三、安装pycharm四、创建pycharm本地环境五、创建pycharm远程环境 一、安装时需要的软件 Pycharm&#xff0c;jetbrains-agent-latest破解包&#xff08;破解pycharm&#xff09;;镜像文件ubuntu20&#xff0c;虚拟机virtualBox …

Zellij – 颜值爆表,比tmux、screen更好用的多窗口终端

如果你曾经使用过多窗口终端&#xff0c;如tmux、screen&#xff0c;那么你可能对Zellij上手会更快。下面将介绍这个惊艳出众的多窗口终端利器。 一、Zellij 特点 Zellij最大的特点是支持插件&#xff0c;与WebAssembly编译兼容。与screen和tmux相比&#xff0c;Zellij是以细…

Linux 之Python 定制篇-APT 软件管理和远程登录

Linux 之Python 定制篇-APT 软件管理和远程登录 apt 介绍 apt 是Advanced Packaging Tool 的简称&#xff0c;是一款安装包管理工具。在Ubuntu 下&#xff0c;我们可以使用apt 命令进行软件包的安装、删除、清理等&#xff0c;类似于Windows 中的软件管理工具。 unbuntu 软件…

LVS-DR负载群集的优势和部署实例(我们都会在各自喜欢的事情里变得可爱)

文章目录 一、DR模式数据包流向分析二、DR模式的特点三、DR模式中需要解决的问题问题1解决方式 问题2解决方式 四、LVS-DR部署实例1.配置NFS共享存储器2.配置节点web服务&#xff08;两台的配置相同&#xff09;3.配置LVS负载调度器 一、DR模式数据包流向分析 1.Client 客户端…

《计算机网络——自顶向下方法》精炼——3.7(2)

读书有三到&#xff1a;谓心到&#xff0c;眼到&#xff0c;口到。——明朱熹 文章目录 对链接吞吐量的简化描述高带宽路径的TCP公平性 对链接吞吐量的简化描述 为了简化对一条TCP连接吞吐量的描述&#xff0c;我们首先忽略连接过程中处于慢启动状态的时间&#xff0c;因为这一…

chatgpt赋能python:Python将yyyymmdd转换成yyyy-mm-dd的方法

Python将yyyymmdd转换成yyyy-mm-dd的方法 Python语言不仅易于学习&#xff0c;而且是一种功能强大的语言&#xff0c;广泛应用于数据分析、人工智能和Web开发等领域。在实际开发过程中&#xff0c;我们经常遇到需要将日期格式转换为其他格式的需求。本文将介绍如何使用Python将…

Nginx rewrite

目录 一、location 1.location 匹配规则介绍 2. 实际网站使用中匹配规则 2.1第一个必选规则 2.2第二个必选规则是处理静态文件请求&#xff0c;这是nginx作为http服务器的强项 2.3第三个规则就是通用规则 3.location 匹配规则演示 2.1一般前缀匹配 2.2正则匹配 2.3正则…

电池状态估计 | Matlab实现利用卡尔曼滤波器估计电池充电状态

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 电池状态估计 | Matlab实现利用卡尔曼滤波器估计电池充电状态 研究内容 目前,常用的电池模型有:数

斐波那契数列题解(非递归c++方法实现)

在做信奥赛&#xff08;信息学奥赛&#xff09;中的for循环题目时&#xff0c;有一道斐波那契数列&#xff0c;想到的第一个方法是使用递归求解&#xff1b;因为以往题目最多使用的就是递归形式&#xff0c;但鉴于该题目在for循环题目堆&#xff0c;所以就思考了一些新方法&…

仙境传说RO:添加限购物品刷新物品库存教程

仙境传说RO&#xff1a;添加限购物品刷新物品库存教程 大家好我是艾西&#xff0c;在游戏中我们会有普通的基础装备那么必然就会有到顶的套装&#xff0c;往往可能一套到顶的套装就可能霸服。那么就需要GM去做游戏的设定以及限制&#xff0c;上一篇文章中我给大家讲述了如果创…

RabbitMQ的基本概念

目录 1、MQ 的基本概念 1.1 MQ概述 1.2 MQ 的优势和劣势 1.3 MQ 的优势 1. 应用解耦 2. 异步提速 3. 削峰填谷 小结: 1.4 MQ 的劣势 1.5 常见的 MQ 产品 1.6 RabbitMQ 简介 1.7 JMS 1、MQ 的基本概念 1.1 MQ概述 MQ全称 Message Queue&#xff08;消息队列&#…