厨房计时器

功能:

1. 正计时,按键控制开始、暂停、清零,数码管显示时间,最大可到99分59秒

附加功能:

1.倒计时:分别设定分钟(最大可设值99)、秒钟(最大可设值59秒),按键控制开始、暂停

2.倒计时至零提醒,提醒10s后自动复位至前一次设定的初值,按键清零则回到0000,此时按“开始/暂停”键,开始正计时

3.倒计时结束提醒时,按暂停键,则停止提示并停在0000处,按置数键(与清零键相同)回到初值,再按一次清零,在此基础上,可以重新设定初值

创新创意:

1.按键设置初值时,可以自动进位和清零

2.设置一些闪烁效果帮助引导用户操作

3.设置了一排led来指示1秒的长度和加减计数,同时增加观感

4.在提醒10s的过程中添加了“快速倒计时的功能”,比如想要立刻将时间延长3分钟,只需要在这10s内按下设值时的加按键就可以快速方便地设置一个3分钟的倒计时。(懒人必备)

按键设置和led灯提示:

  • 开始/暂停键:S2(R15)
  • 清零/置数键(置数清零按键):S0(R11)
  • 设置正计时和倒计时切换按键:S1(R17)
  • 置数时选择位按键:S3(V1)
  • 置数时加按键:S4(U4)
  • 系统复位开关:SW0-R1
  • LD1-2(L1)亮表示倒计时
  • LD1-4(J5)亮表示可以设置倒计时初始值
  • LD1-6(H6)亮表示倒计时结束的10s提示

代码:

1.顶层模块:zhsj.v顶层文件连接作用

2. cnt60.v计数器模块,加减计数置位

3..sec_pule_1秒脉冲模块,给计数器

4. led_paoma.v跑马灯模块,美观指示

5.x7seg_4bit.v四位七段数码管模块,显示

6.state.v状态机模块,七个状态

7.key_FSM.v按键消抖模块,所有按键都进行消抖

这个是我使用的板子的型号

顶层文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/10/26 08:22:01
// Design Name: 
// Module Name: xiti
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module zhsj(
    input clk,
    input rst_n,
    input jj,
    input key_load,            //清零置数按键
    input key_start_stop,            //暂停按键
    input key_shezhi_yiwei,     //用来选择设值的位
    input key_shezhi_jia,       //用来设值
    output [6:0] a_to_g,
    output [3:0] an,
    output led00,led01,led02,led03,
    output [7:0]led0_7          //跑马灯
    );
    wire sec_pule_2;
    wire [15:0] x;
    wire jj_1,jj_2;     //jj_1用于状态机的控制连接,jj_2用于按键消抖连接
    wire jian_flag;     //用于检测减法计数器是否归零
    wire flag_1;    //0表示设值时清零回到加计数,1表示置0但还在减计数
    wire cnt_en;
    wire load;
    wire key_pule;
    wire flag_en_shezhi;
    wire key_shezhi_yiwei_2;    //消抖连接
    wire key_shezhi_jia_2;    //消抖连接
    wire key_load_2;    //消抖连接
    wire [1:0]wei;           //读取cnt60中的位信息并给数码管,实现闪烁
    wire flag_jieshu_daojishi;  //用于提示报警
    wire flag_3;    //10s倒计时标志位
sec_pule_1 u1(
    .clk(clk),
    .rst_n(rst_n),
    .set_pule(sec_pule_2)
    );
cnt60 u2(
    .clk(clk),
    .rst_n(rst_n),
    .jj(jj_1),
    .cnt_en(cnt_en),
    .load(load),
    .sec_pule(sec_pule_2),
    .flag_1(flag_1),        //0表示设值时清零回到加计数,1表示置0但还在减计数
    .flag_3(flag_3),        //10s倒计时标志位
    .flag_en_shezhi(flag_en_shezhi),
    .key_shezhi_yiwei(key_shezhi_yiwei_2),
    .key_shezhi_jia(key_shezhi_jia_2),
    .jian_flag(jian_flag),   //减法计数器是否归零,等于1表示归零
    .wei_out(wei),
    .x(x),
    .led02(led02)       //指示是否能够设值
    );
led_paoma uu3(
    .clk(clk),
    .rst_n(rst_n),
    .jj(jj_1),
    .cnt_en(cnt_en),
    .sec_pule(sec_pule_2),
    .led0_7(led0_7)
    );
x7seg_4bit u3(
    .clk(clk),
    .rst_n(rst_n),
    .x(x),
    .jj(jj_1),
    .wei(wei),
    .load(load),
    .flag_jieshu_daojishi(flag_jieshu_daojishi),
    .a_to_g(a_to_g),
    .an(an)
    );
state u5(
    .clk(clk),
    .rst_n(rst_n),
    .key_load(key_load_2),
    .key_start_stop(key_pule),
    .key_jj(jj_2),            //正计数和倒计时按键
    .cnt_jian(jian_flag),           //检测减法计数是否归零,等于1表示归零
    .key_shezhi_jia(key_shezhi_jia_2),
    .cnt_en(cnt_en),
    .jj(jj_1),         //输出加还是减,0减1加
    .led01(led01),          //用于指示正计数还是倒计时,0是正计数,1是倒计时
    .led03(led03),          //用来指示倒计时结束的10s
    .flag_jieshu_daojishi(flag_jieshu_daojishi),
    .load(load),
    .flag_1(flag_1),     //0表示设值时清零回到加计数,1表示置0但还在减计数
    .flag_en_shezhi(flag_en_shezhi),
    .flag_3(flag_3)
    );
key_FSM u60(
    .clk(clk),            //系统时钟
    .rst_n(rst_n),          //系统复位
    .key(key_start_stop),            //按键复位
    .key_p_flag(key_pule)     //上升沿标志位
    );
key_FSM u61(
    .clk(clk),            //系统时钟
    .rst_n(rst_n),          //系统复位
    .key(jj),            //按键复位
    .key_p_flag(jj_2)     //上升沿标志位
    );
key_FSM u62(
    .clk(clk),            //系统时钟
    .rst_n(rst_n),          //系统复位
    .key(key_shezhi_yiwei),            //按键复位
    .key_p_flag(key_shezhi_yiwei_2)     //上升沿标志位
    );
key_FSM u63(
    .clk(clk),            //系统时钟
    .rst_n(rst_n),          //系统复位
    .key(key_shezhi_jia),            //按键复位
    .key_p_flag(key_shezhi_jia_2)     //上升沿标志位
    );
key_FSM u64(
    .clk(clk),            //系统时钟
    .rst_n(rst_n),          //系统复位
    .key(key_load),            //按键复位
    .key_p_flag(key_load_2)     //上升沿标志位
    );
endmodule

单个模块(名称直接看模块名就行):

`timescale 1ns / 1ps

 Company: 
 Engineer: 
 
 Create Date: 2023/10/25 07:41:59
 Design Name: 
 Module Name: sec_pule
 Project Name: 
 Target Devices: 
 Tool Versions: 
 Description: 
 
 Dependencies: 
 
 Revision:
 Revision 0.01 - File Created
 Additional Comments:
 


module sec_pule_1(
    input clk,
    input rst_n,
    output reg set_pule=0
    );
    parameter N_s=27'd100000000;    //秒脉冲
    reg [26:0] cnt=26'd0;    //计时器cnt,最多能计2^27=134217728>100000000
    always@(posedge clk,negedge rst_n)
        if(!rst_n)
            cnt<=0;
        else if(cnt==N_s-1)
            cnt<=0;
        else
            cnt<=cnt+1;
     always@(posedge clk,negedge rst_n)
        if(!rst_n)
            set_pule<=0;
        else if(cnt==N_s-1)
            set_pule<=1;
        else
            set_pule<=0;
endmodule

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/10/25 07:25:34
// Design Name: 
// Module Name: cnt60
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module cnt60(
    input clk,rst_n,jj,cnt_en,load,sec_pule,//jj0是减,1是加
    flag_1,        //0表示设值时清零回到加计数,1表示置0但还在减计数
    flag_3,        //10s倒计时标志位,1有效
    flag_en_shezhi,      //标志能否设置数值,1表示可以设置
    input key_shezhi_yiwei,     //用来选择设值的位
    input key_shezhi_jia,       //用来设值
    output jian_flag,   //减法计数器是否归零,等于1表示归零
    output [1:0] wei_out,   //将wei输出给数码管
    output reg [15:0] x,        //给数码管
    output reg led02,led00
    );
    reg [1:0] wei;
    reg [15:0] y_jiyi_1,y_jiyi_2;
    reg flag_reg = 1,flag_reg_1 = 1;       //标志是否应该读取寄存器的值,1标志读取,0表示不读取
    reg [1:0] flag_jishu_1 = 2'b00;
    //描述flag_reg_1
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            begin
                flag_jishu_1 <= 2'b00;
                flag_reg_1 <= 0;
            end
        else if(jj==0&&flag_en_shezhi==1&&flag_jishu_1 != 2'b11)
            begin
                flag_jishu_1 <= flag_jishu_1 + 2'b01;
                flag_reg_1 <= 1;
            end
        else if(jj==0&&cnt_en==1)
            begin
                flag_jishu_1 <= 0;
                flag_reg_1 <= 0;
            end
        else if(jj==0&&flag_en_shezhi==1&&flag_jishu_1 == 2'b11)
            begin
                flag_jishu_1 <= flag_jishu_1;
                flag_reg_1 <= 0;
            end
        else
            begin
                flag_jishu_1 <= flag_jishu_1;
                flag_reg_1 <= flag_reg_1;
            end
    //描述y_jiyi_2
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            y_jiyi_2 <= 0;
        else if(jj==0&&flag_en_shezhi==0)
            y_jiyi_2 <= y_jiyi_1;
        else
            y_jiyi_2 <= y_jiyi_2;
    //描述y_jiyi_1
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            y_jiyi_1 <= 0;
        else if(jj==0&&flag_en_shezhi==1)
            y_jiyi_1 <= x;
        else
            y_jiyi_1 <= y_jiyi_1;
    //描述led02
    always @(posedge clk,negedge rst_n)
        begin
        if(!rst_n)
            led02 <= 0;
        else if(flag_en_shezhi==1)
            led02 <= 1;
        else
            led02 <= 0;
        end
    //描述led00
    always @(posedge clk,negedge rst_n)
        begin
        if(!rst_n)
            led00 <= 0;
        else if(load==1)
            led00 <= 1;
        else
            led00 <= 0;
        end
    //描述wei
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n)
                wei <= 2'b00;
            else if(key_shezhi_yiwei==1&&flag_en_shezhi==1)
                wei <= wei + 2'b01;
            else 
                wei <= wei;
        end
    //描述秒个位
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n||load == 1)
                begin
                    if(jj==1)
                        x[3:0]<=4'd0;
                    else if(jj==0&&flag_en_shezhi==1)   //设值
                        begin
                            if(wei == 2'b00 && key_shezhi_jia == 1 && x[3:0] != 4'd9)
                                x[3:0] <= x[3:0] + 4'b1;    //这行代码调整一下
                            else if((wei == 2'b00 && key_shezhi_jia == 1 && x[3:0] == 4'd9)||(wei == 2'b10 && key_shezhi_jia == 1 && x[15:12] == 4'd9 && x[11:8] == 4'd9)||(wei == 2'b01 && key_shezhi_jia == 1 && x[15:12] == 4'd9 && x[11:8] == 4'd9 && x[7:4] == 4'd5)||(wei == 2'b11 && key_shezhi_jia == 1 && x[15:12] == 4'd9))
                                x[3:0] <= 4'd0;
                            else if(flag_reg_1 == 1)
                                x[3:0] <= y_jiyi_2[3:0];
                            else
                                x[3:0] <= x[3:0];
                        end
                    else if(jj==0&&flag_en_shezhi==0)   //设0
                        x[3:0] <= 4'd0;
                    else
                        x[3:0] <= x[3:0];
                end
            else if(x[3:0]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0) //变成9下一个是1
                x[3:0]<=4'd0;
            else if(jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                begin
                    x[3:0]<=x[3:0]+4'b1;
                end
            else if(x[3:0]==4'd0&&(x[7:4]!=4'd0||x[11:8] != 0 ||x[15:12] != 0)&&jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[3:0]<=4'd9;
            else if(jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                begin
                    x[3:0]<=x[3:0]-4'b1;
                end
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&x[11:8]==4'd9&&x[15:12]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)  //减到零置数
                x[3:0]<=4'd0;
            else if(flag_3 == 1 && jj==0 && key_shezhi_jia == 1)        //这个if单纯的是创意中的快速3分钟功能
                x[3:0]<=4'd0;
            else
                x[3:0]<=x[3:0];
        end
    //描述秒十位
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n||load == 1)
                begin
                    if(jj==1)
                        x[7:4]<=4'd0;
                    else if(jj==0&&flag_en_shezhi==1)   //设值
                        begin
                            if((wei == 2'b01 && key_shezhi_jia == 1 && x[7:4] != 4'd5)||(wei == 2'b00 && key_shezhi_jia == 1 && x[7:4] != 4'd5 && x[3:0] == 4'd9)) //考虑进位
                                x[7:4] <= x[7:4] + 4'b1;
                            else if((wei == 2'b01 && key_shezhi_jia == 1 && x[7:4] == 4'd5)||(wei == 2'b10 && key_shezhi_jia == 1 && x[15:12] == 4'd9 && x[11:8] == 4'd9)||(wei == 2'b11 && key_shezhi_jia == 1 && x[15:12] == 4'd9)||(wei == 2'b00 && key_shezhi_jia == 1 && x[7:4] == 4'd5 && x[3:0] == 4'd9))    //溢出清零
                                x[7:4] <= 4'd0;
                            else if(flag_reg_1 == 1)    //设值初值
                                x[7:4] <= y_jiyi_2[7:4];
                            else
                                x[7:4] <= x[7:4];
                        end
                    else if(jj==0&&flag_en_shezhi==0)   //设0
                        x[7:4] <= 4'd0;
                    else
                        x[7:4] <= x[7:4];
                end
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[7:4]<=4'd0;
            else if(x[3:0]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[7:4]<=x[7:4]+4'd1;
            else if(x[3:0]==4'd0&&x[7:4]==4'd0&&(x[11:8] != 0||x[15:12] != 0)&&jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[7:4]<=4'd5;
            else if(x[3:0]==4'd0&&jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[7:4]<=x[7:4]-4'd1;
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&x[11:8]==4'd9&&x[15:12]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)  //计满清零
                x[7:4]<=4'd0;
            else if(flag_3 == 1 && jj==0 && key_shezhi_jia == 1)        //这个if单纯的是创意中的快速3分钟功能
                x[7:4]<=4'd0;
            else
                x[7:4]<=x[7:4];
        end
//描述分钟的个位
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n||load == 1)
                begin
                    if(jj==1)
                        x[11:8]<=4'd0;
                    else if(jj==0&&flag_en_shezhi==1)   //设值
                        begin
                            if((wei == 2'b10 && key_shezhi_jia == 1 && x[11:8] != 4'd9)||(wei == 2'b01 && key_shezhi_jia == 1 && x[11:8] != 4'd9 && x[7:4] == 4'd5)||(wei == 2'b00 && key_shezhi_jia == 1 && x[11:8] != 4'd9 && x[7:4] == 4'd5 && x[3:0] == 4'd9))      //考虑进位
                                x[11:8] <= x[11:8] + 4'b1;
                            else if((wei == 2'b10 && key_shezhi_jia == 1 && x[11:8] == 4'd9)||(wei == 2'b11 && key_shezhi_jia == 1 && x[15:12] == 4'd9)||(wei == 2'b01 && key_shezhi_jia == 1 && x[11:8] == 4'd9 && x[7:4] == 4'd5)||(wei == 2'b00 && key_shezhi_jia == 1 && x[11:8] == 4'd9 && x[7:4] == 4'd5 && x[3:0] == 4'd9)) //溢出清零
                                x[11:8] <= 4'd0;
                            else if(flag_reg_1 == 1)
                                x[11:8] <= y_jiyi_2[11:8];
                            else
                                x[11:8] <= x[11:8];
                        end
                    else if(jj==0&&flag_en_shezhi==0)   //设0
                        x[11:8] <= 4'd0;
                    else
                        x[11:8] <= x[11:8];
                end
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&x[11:8]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[11:8]<=4'd0;
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[11:8]<=x[11:8]+4'd1;
            else if(x[3:0]==4'd0&&x[7:4]==4'd0&&x[11:8]==0&&x[15:12]!=0&&jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[11:8]<=4'd9;
            else if(x[3:0]==4'd0&&x[7:4]==4'd0&&x[11:8]!=0&&jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[11:8]<=x[11:8]-4'd1;
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&x[11:8]==4'd9&&x[15:12]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)  //计满清零
                x[11:8]<=4'd0;
            else if(flag_3 == 1 && jj==0 && key_shezhi_jia == 1)        //这个if单纯的是创意中的快速3分钟功能
                x[11:8]<=4'd3;
            else
                x[11:8]<=x[11:8];
        end
//描述分钟的十位
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n||load == 1)
                begin
                    if(jj==1)
                        x[15:12]<=4'd0;
                    else if(jj==0&&flag_en_shezhi==1)   //设值
                        begin
                            if((wei == 2'b11 && key_shezhi_jia == 1 && x[15:12] != 4'd9)||(wei == 2'b10 && key_shezhi_jia == 1 && x[15:12] != 4'd9 && x[11:8] == 4'd9)||(wei == 2'b01 && key_shezhi_jia == 1 && x[15:12] != 4'd9 && x[11:8] == 4'd9 && x[7:4] == 4'd5)||(wei == 2'b00 && key_shezhi_jia == 1 && x[15:12] != 4'd9 && x[11:8] == 4'd9 && x[7:4] == 4'd5 && x[3:0] == 4'd9))   //考虑进位
                                x[15:12] <= x[15:12] + 4'b1;
                            else if((wei == 2'b11 && key_shezhi_jia == 1 && x[15:12] == 4'd9)||(wei == 2'b10 && key_shezhi_jia == 1 && x[15:12] == 4'd9 && x[11:8] == 4'd9)||(wei == 2'b01 && key_shezhi_jia == 1 && x[15:12] == 4'd9 && x[11:8] == 4'd9 && x[7:4] == 4'd5)||(wei == 2'b00 && key_shezhi_jia == 1 && x[15:12] == 4'd9 && x[11:8] == 4'd9 && x[7:4] == 4'd5 && x[3:0] == 4'd9)) //加满溢出置零
                                x[15:12] <= 4'd0;
                            else if(flag_reg_1 == 1)
                                x[15:12] <= y_jiyi_2[15:12];
                            else
                                x[15:12] <= x[15:12];
                        end
                    else if(jj==0&&flag_en_shezhi==0)   //设0
                        x[15:12] <= 4'd0;
                    else
                        x[15:12] <= x[15:12];
                end
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&x[11:8]==4'd9&&x[15:12]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)      //计满清零
                x[15:12]<=4'd0;
            else if(x[3:0]==4'd9&&x[7:4]==4'd5&&x[11:8]==4'd9&&jj==1&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[15:12]<=x[15:12]+4'd1;
            else if(x[3:0]==4'd0&&x[7:4]==4'd0&&x[11:8]==0&&x[15:12]!=0&&jj==0&&cnt_en == 1&&sec_pule == 1&&flag_en_shezhi==0)
                x[15:12]<=x[15:12]-4'd1;
            else if(flag_3 == 1 && jj==0 && key_shezhi_jia == 1)        //这个if单纯的是创意中的快速3分钟功能
                x[15:12]<=4'd0;
            else
                x[15:12]<=x[15:12];
        end
    assign jian_flag = (x[15:0] == 16'b0000000000000000)?1:0;
    assign wei_out = wei;
endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/15 08:30:43
// Design Name: 
// Module Name: led_paoma
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module led_paoma(
    input clk,rst_n,
    input jj,        //0是减
    input cnt_en,   //计数使能
    input sec_pule, //尝试与计数同步
    output reg [7:0]led0_7
    );
    
    parameter N_s = 28'd100000000;
    reg [27:0] cnt = 28'd0;
//cnt
always @(posedge clk,negedge rst_n)
    if(!rst_n)
        cnt <= 28'd0;
    else if(cnt_en == 1 && cnt != N_s)
        cnt <= cnt + 28'd1;
    else if(cnt_en == 1 && sec_pule == 1)
        cnt <= 28'd0;
    else
        cnt <= 28'd0;

//led
always @(posedge clk,negedge rst_n)
    if(!rst_n)
        led0_7 <= 8'b00000000;
    else if(jj == 1 && cnt_en == 1)
        begin
            if(cnt == 28'd75000000)
                begin
                    led0_7[0] <= 1;
                    led0_7[7:1] <= 7'b0000000;
                end
            else if(cnt == 28'd87500000)
                begin
                    led0_7[0] <= 1;
                    led0_7[1] <= 1;
                    led0_7[7:2] <= 6'b000000;
                end
            else if(cnt == 28'd0)
                begin
                    led0_7[0] <= 0;
                    led0_7[1] <= 1;
                    led0_7[2] <= 1;
                    led0_7[7:3] <= 5'b00000;
                end
            else if(cnt == 28'd12500000)
                begin
                    led0_7[0] <= 0;
                    led0_7[1] <= 0;
                    led0_7[2] <= 1;
                    led0_7[3] <= 1;
                    led0_7[7:4] <= 4'b0000;
                end
            else if(cnt == 28'd25000000)
                begin
                    led0_7[0] <= 0;
                    led0_7[1] <= 0;
                    led0_7[2] <= 0;
                    led0_7[3] <= 1;
                    led0_7[4] <= 1;
                    led0_7[7:5] <= 3'b000;
                end
            else if(cnt == 28'd37500000)
                begin
                    led0_7[0] <= 0;
                    led0_7[1] <= 0;
                    led0_7[2] <= 0;
                    led0_7[3] <= 0;
                    led0_7[4] <= 1;
                    led0_7[5] <= 1;
                    led0_7[7:6] <= 2'b00;
                end
            else if(cnt == 28'd50000000)
                begin
                    led0_7[0] <= 0;
                    led0_7[1] <= 0;
                    led0_7[2] <= 0;
                    led0_7[3] <= 0;
                    led0_7[4] <= 0;
                    led0_7[5] <= 1;
                    led0_7[6] <= 1;
                    led0_7[7] <= 1'b0;
                end
            else if(cnt == 28'd62500000)
                begin
                    led0_7[7] <= 1;
                    led0_7[6:0] <= 7'b1000000;
                end
            else
                led0_7 <= led0_7;
            end
    else if(jj==0)
        begin
            if(cnt == 0)
                begin
                    led0_7[7] <= 1;
                    led0_7[6:0] <= 7'b0000000;
                end
            else if(cnt == N_s/8)
                begin
                    led0_7[7] <= 1;
                    led0_7[6] <= 1;
                    led0_7[5:0] <= 6'b000000;
                end
            else if(cnt == N_s/4)
                begin
                    led0_7[7] <= 0;
                    led0_7[6] <= 1;
                    led0_7[5] <= 1;
                    led0_7[4:0] <= 5'b00000;
                end
            else if(cnt == N_s/8*3)
                begin
                    led0_7[7] <= 0;
                    led0_7[6] <= 0;
                    led0_7[5] <= 1;
                    led0_7[4] <= 1;
                    led0_7[3:0] <= 4'b0000;
                end
            else if(cnt == N_s/2)
                begin
                    led0_7[7] <= 0;
                    led0_7[6] <= 0;
                    led0_7[5] <= 0;
                    led0_7[4] <= 1;
                    led0_7[3] <= 1;
                    led0_7[2:0] <= 3'b000;
                end
            else if(cnt == N_s/8*5)
                begin
                    led0_7[7] <= 0;
                    led0_7[6] <= 0;
                    led0_7[5] <= 0;
                    led0_7[4] <= 0;
                    led0_7[3] <= 1;
                    led0_7[2] <= 1;
                    led0_7[1:0] <= 2'b00;
                end
            else if(cnt == N_s/8*6)
                begin
                    led0_7[0] <= 0;
                    led0_7[1] <= 1;
                    led0_7[2] <= 1;
                    led0_7[3] <= 0;
                    led0_7[4] <= 0;
                    led0_7[5] <= 0;
                    led0_7[6] <= 0;
                    led0_7[7] <= 1'b0;
                end
            else if(cnt == N_s/8*7)
                begin
                    led0_7[0] <= 1;
                    led0_7[7:1] <= 7'b0000001;
                end
            else
                led0_7 <= led0_7;
        end
    else
        led0_7 <= 1;

endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/01 22:33:05
// Design Name: 
// Module Name: x7seg_4bit
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module x7seg_4bit(
    input clk,
    input rst_n,
    input [15:0] x,
    input jj,       //当jj=0时表示减计数
    input [1:0] wei,      //用于选择闪烁
    input load,
    input flag_jieshu_daojishi, //用于报警
    output reg [6:0] a_to_g,
    output reg [3:0] an,
    output reg led00
    );
    reg [20:0] clkdiv;
    wire [1:0] bitcnt;
    parameter N_s=27'd100000000;    //秒脉冲
    reg [26:0] cnt_ss;      //闪烁计时
    reg flag_ss;            //闪烁标志
    //闪烁计时1s闪一次
    always @(posedge clk, negedge rst_n)
        if(!rst_n)
            cnt_ss <= 21'd0;
        else if(cnt_ss == N_s)
            cnt_ss <= 0;
        else
            cnt_ss <= cnt_ss + 1;
    //闪烁标志赋值
    always @(posedge clk, negedge rst_n)
        if(!rst_n)
            flag_ss <= 0;
        else if(cnt_ss > N_s / 2)
            flag_ss <= 1;
        else
            flag_ss <= 0;
    always @(posedge clk, negedge rst_n)
        if(!rst_n)
            clkdiv <= 21'd0;
        else
            clkdiv <= clkdiv + 1;
            
    assign bitcnt = clkdiv[20:19];
    
    always @(*)
        begin
            if(!rst_n)
                an=4'd0;
            else                //这里可以加点东西,实现那什么,警报
                case(bitcnt)
                    2'd0:
                        if(flag_ss == 0 && wei == 2'b00 && jj == 0 && load == 1)
                            an=4'd0;
                        else if(flag_jieshu_daojishi == 1 && flag_ss == 0 )
                            an=4'd0;
                        else
                            an = 4'b0001;
                    2'd1:
                        if(flag_ss == 0 && wei == 2'b01 && jj == 0 && load == 1)
                            an=4'd0;
                        else if(flag_jieshu_daojishi == 1 && flag_ss == 0 )
                            an=4'd0;
                        else
                            an = 4'b0010;
                    2'd2:
                        if(flag_ss == 0 && wei == 2'b10 && jj == 0 && load == 1)
                            an=4'd0;
                        else if(flag_jieshu_daojishi == 1 && flag_ss == 0 )
                            an=4'd0;
                        else
                            an = 4'b0100;
                    2'd3:
                        if(flag_ss == 0 && wei == 2'b11 && jj == 0 && load == 1)
                            an=4'd0;
                        else if(flag_jieshu_daojishi == 1 && flag_ss == 0 )
                            an=4'd0;
                        else
                            an = 4'b1000;
                    default:an=4'd0;
                endcase
        end 
            
    reg [3:0] digit;
    always @(*)
        begin
            if(!rst_n)
                digit = 4'd0;
            else
                case(bitcnt)
                    2'd0:digit=x[3:0];
                    2'd1:digit=x[7:4];
                    2'd2:digit=x[11:8];
                    2'd3:digit=x[15:12];
                    default digit=4'd0;
                endcase
        end
            
    always @(*)
        begin
            if(!rst_n)
                a_to_g=7'b1111111;
            else
                begin
                    case(digit)
                        0:a_to_g=7'b1111110;
                        1:a_to_g=7'b0110000;
                        2:a_to_g=7'b1101101;
                        3:a_to_g=7'b1111001;
                        4:a_to_g=7'b0110011;
                        5:a_to_g=7'b1011011;
                        6:a_to_g=7'b1011111;
                        7:a_to_g=7'b1110000;
                        8:a_to_g=7'b1111111;
                        9:a_to_g=7'b1111011;
                        default:a_to_g=7'b1111110;
                   endcase
               end
       end 
endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/07 22:37:58
// Design Name: 
// Module Name: key_FSM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module state(
    input       clk,            //系统时钟
    input       rst_n,          //系统复位
    input       key_load,            //置零置数按键
    input       key_start_stop,            //开始暂停按键
    input       key_jj,            //正计数和倒计时按键
    input       cnt_jian,           //检测减法计数是否归零,等于1表示归零
    input       key_shezhi_jia,     //快速计时需要
    output  reg cnt_en,     //1就是计数,0就是停止
    output  reg jj,         //输出加还是减,0减1加
    output  reg led01,          //用于指示正计数还是倒计时,0是正计数,1是倒计时
    output  reg led03,          //用于指示倒计时10s,亮了表明在倒计时,在提示
    output      flag_jieshu_daojishi,          //用于指示倒计时10s,亮了表明在倒计时,在提示
    output  reg load,     //1就是置零,0无反应
    output  reg flag_1 = 0,  //0表示设值时清零回到加计数,1表示置0但还在减计数
    output  reg flag_en_shezhi = 0,      //标志能否设置数值,1表示可以设置
    output  reg flag_3 = 0           //用来标记,看看倒计时设值的时候按下清零键的操作,第2,3个用来检测10s
    );
    reg key_tmp1;                           //按键输入寄存器
    parameter N_ms=30'd1000000000;            //10秒计时
    reg [30:0] delay_cnt;                   //延时计数器
    wire end_cnt;                           //计数结束标志位
    parameter WORK_INIT = 2'b000,                 //延时时间
                COUNT = 2'b001,         //无按键输入的空闲状态
                PAUSE = 2'b010,      //有效按键发生,等待按键释放状态
                DAOJISHI_INIT = 3'b011,
                COUNT_JIAN = 3'b100,
                PAUSE_JIAN = 3'b101,
                JIESHU_JIAN = 3'b110;

    reg [2:0] cstate = 0,nstate = 0; 
    //cstate
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            cstate <= 0;
        else
            cstate <= nstate;
    //nstate
    always @(*)
        if(!rst_n)
            nstate = WORK_INIT;
        else
            case(cstate)
                WORK_INIT:
                    if(key_start_stop == 1) nstate = COUNT;
                    else if(key_jj == 1) nstate = DAOJISHI_INIT;
                    else    nstate = cstate;
                COUNT:
                    if(key_start_stop == 1) nstate = PAUSE;
                    else    nstate = cstate;
                PAUSE:
                    if(key_load == 1)   nstate = WORK_INIT;
                    else if(key_start_stop == 1)    nstate = COUNT;
                    else    nstate = cstate;
                DAOJISHI_INIT:
                    if(key_start_stop == 1) nstate = COUNT_JIAN;
                    else if(key_jj == 1) nstate = WORK_INIT;
                    else if(flag_1 == 0&&key_load == 1) nstate = WORK_INIT;
                    else    nstate = cstate;
                COUNT_JIAN:
                    if(key_start_stop == 1) nstate = PAUSE_JIAN;
                    else if(cnt_jian == 1) nstate = JIESHU_JIAN;        //计数完成
                    else    nstate = cstate;
                PAUSE_JIAN:
                    if(key_start_stop == 1) nstate = COUNT_JIAN;
                    else if(key_load == 1) nstate = DAOJISHI_INIT;
                    else    nstate = cstate;
                JIESHU_JIAN:
                    if(key_start_stop == 1) nstate = PAUSE_JIAN;
                    else if(end_cnt == 1) nstate = DAOJISHI_INIT;
                    else if(key_shezhi_jia == 1) 
                        begin
                            #40;
                            nstate = COUNT_JIAN;
                        end
                    else    nstate = cstate;
            endcase
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            begin
                cnt_en <= 0;
                load <= 1;
                jj <= 1;
                led01 <= 0;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= 1;
                flag_en_shezhi <= 0;
            end
        else if(cstate == WORK_INIT)
            begin
                cnt_en <= 0;
                load <= 1;
                jj <= 1;
                led01 <= 0;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= 1;
                flag_en_shezhi <= 0;
            end
        else if(cstate == COUNT)
            begin
                cnt_en <= 1;
                load <= 0;
                jj <= 1;
                led01 <= 0;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= flag_1;
                flag_en_shezhi <= 0;
            end
        else if(cstate == PAUSE)
            begin
                cnt_en <= 0;
                load <= 0;
                jj <= 1;
                led01 <= 0;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= flag_1;
                flag_en_shezhi <= 0;
            end
        else if(cstate == DAOJISHI_INIT)
            begin
                cnt_en <= 0;
                load <= 1;
                jj <= 0;
                led01 <= 1;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= flag_1;
                if(flag_1 == 1&&key_load == 1)
                    begin
                        flag_en_shezhi <= 0;
                    end
                else
                    begin
                        flag_en_shezhi <= 1;
                    end
            end
        else if(cstate == COUNT_JIAN)
            begin
                cnt_en <= 1;
                load <= 0;
                jj <= 0;
                led01 <= 1;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= flag_1;
                flag_en_shezhi <= 0;
            end
        else if(cstate == PAUSE_JIAN)
            begin
                cnt_en <= 0;
                load <= 0;
                jj <= 0;
                led01 <= 1;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= 1;
                flag_en_shezhi <= 0;
            end
        else if(cstate == JIESHU_JIAN)
            begin
                cnt_en <= 0;
                load <= 0;
                jj <= 0;
                led01 <= 1;
                led03 <= 1;
                flag_3 <= 1;
                flag_1 <= 0;
                flag_en_shezhi <= 0;
            end
        else
            begin
                cnt_en <= 0;
                load <= 1;
                jj <= 1;
                led01 <= 0;
                led03 <= 0;
                flag_3 <= 0;
                flag_1 <= 1;
                flag_en_shezhi <= 0;
            end
    always@(posedge clk,negedge rst_n)
        if(!rst_n)
            delay_cnt <= 0;
        else if(flag_3 == 1)
            delay_cnt <= delay_cnt + 1;
        else
            delay_cnt <= 0;
    assign end_cnt = ( delay_cnt == (N_ms - 1) )?1:0;
    assign flag_jieshu_daojishi = led03;
endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/07 22:37:58
// Design Name: 
// Module Name: key_FSM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_FSM(
    input       clk,            //系统时钟
    input       rst_n,          //系统复位
    input       key,            //按键复位
    output  reg key_p_flag,     //上升沿标志位
    output  reg key_n_flag,     //下降沿标志位
    output  reg key_value       //有效按键值
    );
    reg key_tmp1;                           //按键输入寄存器
    reg [20:0] delay_cnt;                   //延时计数器
    wire end_cnt;                           //计数结束标志位
    parameter   DELAY_TIME = 21'd1500000;   //延时时间
    parameter IDLE = 2'b00,                 //延时时间
                DELAY_HIGH = 2'b01,         //无按键输入的空闲状态
                CHECK_RELEASE = 2'b10,      //有效按键发生,等待按键释放状态
                DELAY_LOW = 2'b11;          //检测到下降沿并计数状态
   reg [1:0] cstate = 0,nstate = 0;         
   //ker_tmp1
   always @(posedge clk,negedge rst_n)
    if(!rst_n)
        key_tmp1 <= 1'b0;
    else
        key_tmp1 <= key;
    //delay_cnt
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            delay_cnt <= 0;
        else if(delay_cnt == DELAY_TIME - 1)
            delay_cnt <= 0;
        else if(cstate == DELAY_HIGH || cstate == DELAY_LOW)
            delay_cnt <= delay_cnt + 1;
        else
            delay_cnt <= 0;
    //end_cnt
    assign end_cnt = ( delay_cnt == (DELAY_TIME - 1) )?1:0;
    //catate
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            cstate <= IDLE;
        else 
            cstate <= nstate;
    //nstate
    always @(*)
        if(!rst_n)
            nstate = IDLE;
        else
            case(cstate)
                IDLE:
                    if(key_tmp1 == 1)   nstate = DELAY_HIGH;
                    else    nstate = cstate;
                DELAY_HIGH:
                    if(end_cnt == 1)    nstate = CHECK_RELEASE;
                    else if(key_tmp1 == 0)  nstate = IDLE;
                    else    nstate = cstate;
                CHECK_RELEASE:
                    if(key_tmp1 == 0)   nstate = DELAY_LOW;
                    else    nstate = cstate;
                DELAY_LOW:
                    if(end_cnt == 1)    nstate = IDLE;
                    else if(key_tmp1 == 1)  nstate = CHECK_RELEASE;
                    else    nstate = cstate;
                default:
                    nstate = IDLE;
            endcase
    //key_p_flag
    always  @(posedge clk,negedge rst_n)
        if(!rst_n)
            key_p_flag <= 0;
        else if(end_cnt == 1 && cstate == DELAY_HIGH)
            key_p_flag <= 1;
        else
            key_p_flag <= 0;
     //key_n_flag
    always  @(posedge clk,negedge rst_n)
        if(!rst_n)
            key_n_flag <= 0;
        else if(end_cnt == 1 && cstate == DELAY_LOW)
            key_n_flag <= 1;
        else
            key_n_flag <= 0;               
    //key_value
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            key_value <= 0;
        else if(end_cnt == 1)
            key_value <= key;
endmodule

然后是约束文件

set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports jj]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property PACKAGE_PIN R1 [get_ports rst_n]
set_property PACKAGE_PIN R17 [get_ports jj]
set_property PACKAGE_PIN P17 [get_ports clk]
set_property PACKAGE_PIN G6 [get_ports {an[0]}]
set_property PACKAGE_PIN E1 [get_ports {an[1]}]
set_property PACKAGE_PIN F1 [get_ports {an[2]}]
set_property PACKAGE_PIN G1 [get_ports {an[3]}]
set_property PACKAGE_PIN D2 [get_ports {a_to_g[0]}]
set_property PACKAGE_PIN E2 [get_ports {a_to_g[1]}]
set_property PACKAGE_PIN F3 [get_ports {a_to_g[2]}]
set_property PACKAGE_PIN F4 [get_ports {a_to_g[3]}]
set_property PACKAGE_PIN D3 [get_ports {a_to_g[4]}]
set_property PACKAGE_PIN E3 [get_ports {a_to_g[5]}]
set_property PACKAGE_PIN D4 [get_ports {a_to_g[6]}]

set_property PACKAGE_PIN R11 [get_ports key_load]
set_property IOSTANDARD LVCMOS33 [get_ports key_load]
set_property PACKAGE_PIN R15 [get_ports key_start_stop]
set_property IOSTANDARD LVCMOS33 [get_ports key_start_stop]

set_property IOSTANDARD LVCMOS33 [get_ports key_shezhi_jia]
set_property IOSTANDARD LVCMOS33 [get_ports key_shezhi_yiwei]
set_property IOSTANDARD LVCMOS33 [get_ports led00]
set_property IOSTANDARD LVCMOS33 [get_ports led01]
set_property IOSTANDARD LVCMOS33 [get_ports led02]
set_property PACKAGE_PIN U4 [get_ports key_shezhi_jia]
set_property PACKAGE_PIN V1 [get_ports key_shezhi_yiwei]
set_property PACKAGE_PIN K3 [get_ports led00]
set_property PACKAGE_PIN L1 [get_ports led01]
set_property PACKAGE_PIN J5 [get_ports led02]

set_property IOSTANDARD LVCMOS33 [get_ports led03]
set_property PACKAGE_PIN H6 [get_ports led03]

set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led0_7[0]}]
set_property PACKAGE_PIN K2 [get_ports {led0_7[7]}]
set_property PACKAGE_PIN J2 [get_ports {led0_7[6]}]
set_property PACKAGE_PIN J3 [get_ports {led0_7[5]}]
set_property PACKAGE_PIN H4 [get_ports {led0_7[4]}]
set_property PACKAGE_PIN J4 [get_ports {led0_7[3]}]
set_property PACKAGE_PIN G3 [get_ports {led0_7[2]}]
set_property PACKAGE_PIN G4 [get_ports {led0_7[1]}]
set_property PACKAGE_PIN F6 [get_ports {led0_7[0]}]

上面就是全部文件,下面放一个拨码开关的消抖(与按键消抖的原理不同,按键消抖输出的是一个时钟周期的上升沿,拨码开关消抖是防抖动,输出稳定在1或0)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/01 23:03:20
// Design Name: 
// Module Name: key_debounce
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_debounce(
    input clk,
    input rst_n,
    input key,
    output reg key_value,a1
    );
    reg key_reg;
    reg [20:0] delay_cnt=0;
    parameter DELAY_TIME = 21'd1500000;
    
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            key_reg <= 1'b0;
        else
            key_reg <= key;
     //下面代码可以直接注释掉,这样就没有按键消抖
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            delay_cnt <= 21'b0;
        else if(key != key_reg)
            delay_cnt <= DELAY_TIME;
        else if(delay_cnt >0 )
            delay_cnt <= delay_cnt-1'b1;
        else
            delay_cnt <= 21'd0;
    always @(posedge clk,negedge rst_n)
        if(!rst_n)
            key_value <= key;
        else if(delay_cnt == 1'b1)
            begin
                key_value <= key;
                a1 = a1 + 1'b0;
            end
 
endmodule

这个里面的逻辑比较复杂(我自己看都容易晕,由于没有verilog的语言,只能选择比较接近的C++了),最后放一个状态机的逻辑,记录一下这个工程,希望能帮助其他同学,有问题可以评论哈。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值