功能:
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++了),最后放一个状态机的逻辑,记录一下这个工程,希望能帮助其他同学,有问题可以评论哈。