简易数字时钟 按键可校准

1 课程设计目的
2 课程设计内容及要求
2.1 设计任务
2.2 设计要求
3 verilog程序设计
3.1方案论证
3.2 系统结构框图
3.3设计思路与方法
3.3.1功能模块
1.按键消抖
2.时钟状态
3.时钟调整状态
3.3.2显示模块
1.段选模块
2.位选模块
4.课程设计总结,包括.收获、体会和建议
附件:1.程序清单。2.整体RTL试图。3.整体模块的仿真图。

1 课程设计目的
(1)通过设计数字钟熟练掌握EDA软件(QUARTUS II)的使用方法,熟练进行设计、编译,为以后实际工程问题打下设计基础。
(2)熟悉verilog 硬件描述语言,提升分析、寻找和排除电子设计中常见故障的能力。
(3)通过课程设计,锻炼书写有理论根据的、实事求是的、文理通顺的课程设计报告。
2 课程设计内容及要求
2.1 设计任务
6个数字显示器显示时分秒
2.2 设计要求
在原有的时钟上增加四个轻触按键
状态键:按键按下,时间停止,状态在时分秒中来回跳转。
加键:状态在时分秒状态下,按键按下数值加一。
减键:状态在时分秒状态下,按键按下数值减一
3 Verilog程序设计
3.1方案论证
该数字钟可以实现:时间显示、预置时间和时间校准的功能,因此时钟系统可分为2个模块。功能模块,显示模块。
(1)功能选择模块是有状态机构成的,功能为依次进行、预置时间、校准时间。
调整工作状态:数字钟的初始状态显示时分秒,而该部分可以在上电前,在程序中预置开始的时间。
校准时间:状态键按下,时间停止,按键停在秒状态下,加减键可以调节。当按第四次时,时间校准完毕,从校准的时间点上开始工作。
(2)3.2系统结构框图

3.3设计思路与方法
3.3.1 功能模块
功能模块中调用(例化)了三个按键消抖模块,用于按键的控制。即状态键,加键,减键。
这个状态的设置,我选择使用状态机(FSM),状态键控制状态的跳转。
状态0:正常的时钟显示。在这个模块我曾想过做一个十进制计数器,然后例化4个做成60进制和24进制两个模块,然后再例化2个60进制和一个24进制。方案可行,但是后来由于反复例化令人思路不够清晰,所以我想直接做成一个时钟模块。
状态1:秒状态
两个if语句二层嵌套,第一层判断按键(加或减)按下,数值变化,所以二层if则是数值的控制。满9进1,或者是降0归9。
同理,粘贴复制
状态2:分状态
状态3:时状态。
1.按键消抖
由于控制按键按一下,只能加一下。而实际中轻触按键由于自身原因肯定会抖动。
例外,由于通常控制在一个全局脉冲下,加一。而一个脉冲的周期只有20ns,所以采用延时消抖的话(20ms或10ms)是不行的。所以才会有两个方案,改时钟或采集消抖后的一个脉冲的边沿。
为了以后使用(模块化),所以我采用了后者,在按键消抖模块中,加上自己的考虑,方便以后使用。
按键消抖代码如下:
/*
信号名称 方向 说明
clk in 时钟输入
rst_n in 异步复位输入,低复位
button_in in 按键输入
button_posedge out 消抖后按键上升沿,高有效,1 个时钟周期
button_negedge out 消抖后按键下升沿,高有效,1 个时钟周期
button_out out 消抖后按键输出
按键消抖模块(ax_debounce)端口
*/
`timescale 1 ns / 100 ps
module ax_debounce
(
input clk,
input rst,
input button_in,
output reg button_posedge,
output reg button_negedge,
output reg button_out
);
---------------- internal constants --------------
parameter N = 32 ; // debounce timer bitwidth
parameter FREQ = 50; //model clock :Mhz
parameter MAX_TIME = 20; //ms
localparam TIMER_MAX_VAL = MAX_TIME * 1000 * FREQ;
---------------- internal variables ---------------
reg [N-1 : 0] q_reg; // timing regs
reg [N-1 : 0] q_next;
reg DFF1, DFF2; // input flip-flops
wire q_add; // control flags
wire q_reset;
reg button_out_d0;
------------------------------------------------------
contenious assignment for counter control
assign q_reset = (DFF1 ^ DFF2); // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0
combo counter to manage q_next
always @ ( q_reset, q_add, q_reg)
begin
case( {q_reset , q_add})
2’b00 :
q_next <= q_reg;
2’b01 :
q_next <= q_reg + 1;
default :
q_next <= { N {1’b0} };
endcase
end
Flip flop inputs and q_reg update
always @ ( posedge clk or posedge rst)
begin
if(rst == 1’b1)
begin
DFF1 <= 1’b0;
DFF2 <= 1’b0;
q_reg <= { N {1’b0} };
end
else
begin
DFF1 <= button_in;
DFF2 <= DFF1;
q_reg <= q_next;
end
end

counter control
always @ ( posedge clk or posedge rst)
begin
if(rst == 1’b1)
button_out <= 1’b1;
else if(q_reg == TIMER_MAX_VAL)
button_out <= DFF2;
else
button_out <= button_out;
end
always @ ( posedge clk or posedge rst)
begin
if(rst == 1’b1)
begin
button_out_d0 <= 1’b1;
button_posedge <= 1’b0;
button_negedge <= 1’b0;
end
else
begin
button_out_d0 <= button_out;
button_posedge <= ~button_out_d0 & button_out;
button_negedge <= button_out_d0 & ~button_out;
end
end
endmodule
模块中通过了两级 D 触发器来寄存键值,只有当键值稳定时才将键值输出。我们可以看到在 assign 赋值语句中有一条“assign a_reset=(DFF1 ^ DFF2)”,学过数字电路的应该都知道“ ^ ” 是异或运算符,运算符两边相同运算结果为 0,不同运算结果为 1。在程序中 DFF1 和 DFF2 比较 运算后的值通过“assign”赋给“a_reset”表示比较锁存键值的前后两级寄存器的值是否一致,只有前后两级寄存器的值一致,也就是 a_reset 的值为 0 时才表示当前锁存的键值没有变化。当计数器累加到“TIMER_MAX_VAL”,表示锁存的键值已经稳定可以输出。另外在模块中我们可以看
到“{…}”符号,要注意这可不是大括号,这表示位拼接运算符,其作用是将运算符内的两位, 或是多位信号拼接在一起。
最后,程序中需要说明的是“button_posedge”和“button_negedge”两个输出信号,这是 一种常用的上升沿和下降沿的采集方法,其描述的 RTL 视图如下:
在这里插入图片描述

波形仿真图:
在这里插入图片描述

可以清晰的看到边沿检测中采集的上升沿和下降沿。
2.时钟状态
parameter cnt_max = 32’d4999_9999;//一秒所要达到的计数

0:
//当计满一秒并且秒的个位小于9时,秒的个位加一
if(cnt == cnt_max && count_miao_ge_reg<4’d9)
begin
count_miao_ge_reg <= count_miao_ge_reg + 4’d1;
cnt <= 32’d0;
end
//当计满一秒并且秒的个位等于9时,秒的十位加一,秒的个位清零
else if(cnt == cnt_max && count_miao_ge_reg4’d9 && count_miao_shi_reg<3’d5)
begin
count_miao_shi_reg <= count_miao_shi_reg + 3’d1;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
//当计满一秒,秒到达59并且分的个位小于9时,分的个位加1
else if(cnt == cnt_max && count_miao_ge_reg
4’d9 && count_miao_shi_reg3’d5 && count_fen_ge_reg<4’d9)
begin
count_fen_ge_reg <= count_fen_ge_reg + 4’d1;
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
//当计满一秒,秒到达59并且分的个位等于9时,分的十位加1
else if(cnt == cnt_max && count_miao_ge_reg
4’d9 && count_miao_shi_reg3’d5 && count_fen_ge_reg4’d9 && count_fen_shi_reg < 3’d5)
begin
count_fen_shi_reg <= count_fen_shi_reg + 3’d1;
count_fen_ge_reg <= 4’d0;
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
//当计满一秒,秒到达59,分等于59时,时的个位小于<9,时的十位小于2时,时的个位加一
else if(cnt == cnt_max && count_miao_ge_reg4’d9 && count_miao_shi_reg3’d5 && count_fen_ge_reg4’d9 && count_fen_shi_reg 3’d5 && count_shi_ge_reg < 4’d9 && count_shi_shi < 2’d2)
begin
count_shi_ge_reg <= count_shi_ge_reg + 4’d1;
count_fen_shi_reg <= 3’d0;
count_fen_ge_reg <= 4’d0;
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
//当计满一秒,秒到达59,分等于59时,时的个位等于9时,时的十位<2,时的十位加一
else if(cnt == cnt_max && count_miao_ge_reg
4’d9 && count_miao_shi_reg
3’d5 && count_fen_ge_reg4’d9 && count_fen_shi_reg 3’d5 && count_shi_ge_reg == 4’d9 && count_shi_shi < 2’d2)
begin
count_shi_shi_reg <= count_shi_shi + 2’d1;
count_shi_ge_reg <= 4’d0;
count_fen_shi_reg <= 3’d0;
count_fen_ge_reg <= 4’d0;
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
//当计满一秒,秒到达59,分等于59时,时的个位小于3时,时的十位等于2,时的个位加一
else if(cnt == cnt_max && count_miao_ge_reg
4’d9 && count_miao_shi_reg
3’d5 && count_fen_ge_reg4’d9 && count_fen_shi_reg 3’d5 && count_shi_ge_reg < 4’d3 && count_shi_shi == 2’d2)
begin
count_shi_ge_reg <= count_shi_ge_reg + 4’d1;
count_fen_shi_reg <= 3’d0;
count_fen_ge_reg <= 4’d0;
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
//当计满一秒,秒到达59,分等于59时,时等于23,所有清零
else if(cnt == cnt_max && count_miao_ge_reg
4’d9 && count_miao_shi_reg
3’d5 && count_fen_ge_reg4’d9 && count_fen_shi_reg 3’d5 && count_shi_ge_reg == 4’d3 && count_shi_shi == 2’d2)
begin
count_shi_shi_reg <= 2’d0;
count_shi_ge_reg <= 4’d0;
count_fen_shi_reg <= 3’d0;
count_fen_ge_reg <= 4’d0;
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
cnt <= 32’d0;
end
else
begin
cnt <= cnt + 32’d1;
End
在整个电路中,只用到了两个分频时钟 秒数控制和数码管刷新频率,为了方便,所以没有用PLL锁相环IP核,直接在内部计数。
3.时钟校准状态
always@(posedge clk or negedge reset)
begin
if(!reset)
state <= 2’d0;
else if(button_negedge1)
// else if(!key1)
begin
state <= state + 2’d1;
if(state == 2’d3)
state <= 2’d0;
end
else
state = state;
end
状态的控制端。
按一下,状态记下一位。
实现端:
1:
begin
if(button_negedge2)
//if(!key2)
begin
if( count_miao_ge_reg<4’d9)
begin
count_miao_ge_reg <= count_miao_ge_reg + 4’d1;
end
else if(count_miao_ge_reg
4’d9 && count_miao_shi_reg<3’d5)
begin
count_miao_shi_reg<=count_miao_shi_reg + 3’d1;
count_miao_ge_reg <= 4’d0;
end
else if(count_miao_shi_reg
3’d5 && count_miao_ge4’d9)
begin
count_miao_shi_reg <= 3’d0;
count_miao_ge_reg <= 4’d0;
end
end
if(button_negedge3)
//if(!key3)
begin
if( count_miao_ge_reg>4’d0)
begin
count_miao_ge_reg <= count_miao_ge_reg - 4’d1;
end
else if(count_miao_ge_reg
4’d0 && count_miao_shi_reg>3’d0)
begin
count_miao_shi_reg <= count_miao_shi_reg - 3’d1;
count_miao_ge_reg <= 4’d9;
end
else if(count_miao_shi_reg3’d0 && count_miao_ge_reg4’d0)
begin
count_miao_shi_reg <= 3’d5;
count_miao_ge_reg <= 4’d9;
end
end
end
2:
begin
if(button_negedge2)
//if(!key2)
begin
if( count_fen_ge_reg<4’d9)
begin
count_fen_ge_reg <= count_fen_ge_reg + 4’d1;
end
else if(count_fen_ge_reg4’d9 && count_fen_shi_reg<3’d5)
begin
count_fen_shi_reg <= count_fen_shi_reg + 3’d1;
count_fen_ge_reg <= 4’d0;
end
else if(count_fen_shi_reg
3’d5 && count_fen_ge4’d9)
begin
count_fen_shi_reg <= 3’d0;
count_fen_ge_reg <= 4’d0;
end
end
if(button_negedge3)
//if(!key3)
begin
if( count_fen_ge_reg>4’d0)
begin
count_fen_ge_reg <= count_fen_ge_reg - 4’d1;
end
else if(count_fen_ge_reg
4’d0 && count_fen_shi_reg>3’d0)
begin
count_fen_shi_reg <= count_fen_shi_reg - 3’d1;
count_fen_ge_reg <= 4’d9;
end
else if(count_fen_shi_reg3’d0 && count_fen_ge_reg4’d0)
begin
count_fen_shi_reg <= 3’d5;
count_fen_ge_reg <= 4’d9;
end
end
end
3:
begin
if(button_negedge2)
//if(!key2)
begin
if( count_shi_ge_reg<4’d9)
begin
count_shi_ge_reg <= count_shi_ge_reg + 4’d1;
end
else if(count_shi_ge_reg4’d9 && count_shi_shi_reg<2’d2)
begin
count_shi_shi_reg <= count_shi_shi_reg + 2’d1;
count_shi_ge_reg <= 4’d0;
end
else if(count_shi_shi_reg
3’d2 && count_shi_ge4’d4)
begin
count_shi_shi_reg <= 2’d0;
count_shi_ge_reg <= 4’d0;
end
end
if(button_negedge3)
//if(!key3)
begin
if( count_shi_ge_reg>4’d0)
begin
count_shi_ge_reg <= count_shi_ge_reg - 4’d1;
end
else if(count_shi_ge_reg
4’d0 && count_shi_shi_reg>2’d0)
begin
count_shi_shi_reg <= count_shi_shi_reg - 2’d1;
count_shi_ge_reg <= 4’d9;
end
else if(count_shi_shi_reg3’d0 && count_shi_ge_reg4’d0)
begin
count_shi_shi_reg <= 2’d2;
count_shi_ge_reg <= 4’d3;
end
end
End
实际上就是将时钟状态粘贴复制将计数去掉,然后将时分秒拆开。加上按键控制加减的电路。所以感觉复杂,但贵在好理解。
RTL试图:

3.3.2显示模块
该系统中用到的显示模块是数码管,六位数码管分别显示时分秒。
而数码管显示有两个部分,段选和位选。
我将它分成了两个部分。
段选译码,位选动态显示
//段选译码
module decoding(
input clk,
input reset,
input [3:0] count_miao_ge,
input [2:0] count_miao_shi,
input [3:0] count_fen_ge,
input [2:0] count_fen_shi,
input [3:0] count_shi_ge,
input [1:0] count_shi_shi,
output reg [7:0] code_miao_ge,
output reg [7:0] code_miao_shi,
output reg [7:0] code_fen_ge,
output reg [7:0] code_fen_shi,
output reg [7:0] code_shi_ge,
output reg [7:0] code_shi_shi
);
always@(posedge clk or negedge reset)
begin
if(!reset)
code_miao_ge <= 8’b1111_1111;
else
begin
case(count_miao_ge)
4’d0:code_miao_ge <= 8’b1100_0000;
4’d1:code_miao_ge <= 8’b1111_1001;
4’d2:code_miao_ge <= 8’b1010_0100;
4’d3:code_miao_ge <= 8’b1011_0000;
4’d4:code_miao_ge <= 8’b1001_1001;
4’d5:code_miao_ge <= 8’b1001_0010;
4’d6:code_miao_ge <= 8’b1000_0010;
4’d7:code_miao_ge <= 8’b1111_1000;
4’d8:code_miao_ge <= 8’b1000_0000;
4’d9:code_miao_ge <= 8’b1001_0000;
default:code_miao_ge <= 8’b1011_1111;
endcase
end
end
always@(posedge clk or negedge reset)
begin
if(!reset)
code_miao_shi <= 8’b1111_1111;
else
begin
case(count_miao_shi)
3’d0:code_miao_shi <= 8’b1100_0000;
3’d1:code_miao_shi <= 8’b1111_1001;
3’d2:code_miao_shi <= 8’b1010_0100;
3’d3:code_miao_shi <= 8’b1011_0000;
3’d4:code_miao_shi <= 8’b1001_1001;
3’d5:code_miao_shi <= 8’b1001_0010;
default:code_miao_shi <= 8’b1011_1111;
endcase
end
end
always@(posedge clk or negedge reset)
begin
if(!reset)
code_fen_ge <= 8’b1111_1111;
else
begin
case(count_fen_ge)
4’d0:code_fen_ge <= 8’b0100_0000;
4’d1:code_fen_ge <= 8’b0111_1001;
4’d2:code_fen_ge <= 8’b0010_0100;
4’d3:code_fen_ge <= 8’b0011_0000;
4’d4:code_fen_ge <= 8’b0001_1001;
4’d5:code_fen_ge <= 8’b0001_0010;
4’d6:code_fen_ge <= 8’b0000_0010;
4’d7:code_fen_ge <= 8’b0111_1000;
4’d8:code_fen_ge <= 8’b0000_0000;
4’d9:code_fen_ge <= 8’b0001_0000;
default:code_fen_ge <= 8’b1011_1111;
endcase
end
end
always@(posedge clk or negedge reset)
begin
if(!reset)
code_fen_shi <= 8’b1111_1111;
else
begin
case(count_fen_shi)
3’d0:code_fen_shi <= 8’b1100_0000;
3’d1:code_fen_shi <= 8’b1111_1001;
3’d2:code_fen_shi <= 8’b1010_0100;
3’d3:code_fen_shi <= 8’b1011_0000;
3’d4:code_fen_shi <= 8’b1001_1001;
3’d5:code_fen_shi <= 8’b1001_0010;
default:code_fen_shi <= 8’b1011_1111;
endcase
end
end
always@(posedge clk or negedge reset)
begin
if(!reset)
code_shi_ge <= 8’b1111_1111;
else
begin
case(count_shi_ge)
4’d0:code_shi_ge <= 8’b0100_0000;
4’d1:code_shi_ge <= 8’b0111_1001;
4’d2:code_shi_ge <= 8’b0010_0100;
4’d3:code_shi_ge <= 8’b0011_0000;
4’d4:code_shi_ge <= 8’b0001_1001;
4’d5:code_shi_ge <= 8’b0001_0010;
4’d6:code_shi_ge <= 8’b0000_0010;
4’d7:code_shi_ge <= 8’b0111_1000;
4’d8:code_shi_ge <= 8’b0000_0000;
4’d9:code_shi_ge <= 8’b0001_0000;
default:code_shi_ge <= 8’b1011_1111;
endcase
end

	end

always@(posedge clk or negedge reset)
begin
if(!reset)
code_shi_shi <= 8’b1111_1111;
else
begin
case(count_shi_shi)
2’d0:code_shi_shi <= 8’b1100_0000;
2’d1:code_shi_shi <= 8’b1111_1001;
2’d2:code_shi_shi <= 8’b1010_0100;
default:code_shi_shi <= 8’b1011_1111;
endcase
End
end
endmodule
//位选动态显示
module sel_show(
input clk,
input reset,
input [7:0] code_miao_ge,
input [7:0] code_miao_shi,
input [7:0] code_fen_ge,
input [7:0] code_fen_shi,
input [7:0] code_shi_ge,
input [7:0] code_shi_shi,
output reg [7:0] led,
output reg [5:0] sel
);
reg [15:0] cnt;
reg flag;
//产生1000Hz的时钟
always@(posedge clk or negedge reset)
begin
if(!reset)
begin
cnt <=16’d0;
flag <= 1’b0;
end
else if(cnt == 16’d500_00)
begin
cnt <= 16’d0;
flag <= 1’b1;
end
else
begin
cnt <= cnt + 16’d1;
flag <= 1’b0;
end
end
reg [2:0] state;
parameter start = 3’d0; //开始状态
parameter sel_1 = 3’d1; //位选1
parameter sel_2 = 3’d2; //位选2
parameter sel_3 = 3’d3; //位选3
parameter sel_4 = 3’d4; //位选4
parameter sel_5 = 3’d5; //位选5
parameter sel_6 = 3’d6; //位选6
parameter ending = 3’d7;//结束
always @ (posedge clk or negedge reset)
begin
if(!reset)
begin
state <= 3’d0;
sel <= 6’b000_000;
end
else
case(state)
start:
begin
if(flag == 1’b1)
state <= sel_1;
else
state <= state;
end
sel_1:
begin
if(flag == 1’b1)
begin
state <= sel_2;
sel <= 6’b111_110;
led <= code_miao_ge;
end
else
state <= state;
end
sel_2:
begin
if(flag == 1’b1)
begin
state <= sel_3;
sel <= 6’b111_101;
led <= code_miao_shi;
end
else
state <= state;
end
sel_3:
begin
if(flag == 1’b1)
begin
state <= sel_4;
sel <= 6’b111_011;
led <= code_fen_ge;
end
else
state <= state;
end
sel_4:
begin
if(flag == 1’b1)
begin
state <= sel_5;
sel <= 6’b110_111;
led <= code_fen_shi;
end
else
state <= state;
end
sel_5:
begin
if(flag == 1’b1)
begin
state <= sel_6;
sel <= 6’b101_111;
led <= code_shi_ge;
end
else
state <= state;
end
sel_6:
begin
if(flag == 1’b1)
begin
state <= ending;
sel <= 6’b011_111;
led <= code_shi_shi;
end
else
state <= state;
end
ending:
state <= start;
default:
state <= start;
endcase
end
endmodule

RTL视图:
在这里插入图片描述

  1. 课程设计总结(收获、体会和建议)
    本次verilog设计的数字钟定义了三种类型的端口,分别是in、out、buffer。In和out端口使用简单,buffer端口具有回读功能,因为buffer类型的端口不能连接到其他类型的端口上,因此不利于子模块原件例化,不利于大型设计。
    进程(Process)是verilog中最为重要的部分,在本次设计中。我出现了对于时钟引入,输出多驱动,一个进程中不允许出现两个时钟沿触发的错误,这些错误在未来的设计中都是应该避免的。顺序语句如IF语句、CASE语句、变量赋值语句等必须出现在进程、函数或子程序内部,而不能单独出现在进程之外。
    本次实验让我对verilog 语言有了更深的认识,对语言的运用更加熟悉,为未来的实际应用打下了良好的基础。因为实验室的条件限制,并没有将程序下载到实际器件中观察现象,只是通过软件对系统进行仿真,希望以后可以机会接触并使用实际器件。
    附件1:

顶层模块:
module top_time_colck(
input clk,
input reset,
input key1,
input key2,
input key3,
output [7:0] led,
output [5:0] sel
//output Led
);
wire [3:0] count_miao_ge;
wire [2:0] count_miao_shi;
wire [3:0] count_fen_ge;
wire [2:0] count_fen_shi;
wire [3:0] count_shi_ge;
wire [1:0] count_shi_shi;
wire [7:0] code_miao_ge;
wire [7:0] code_miao_shi;
wire [7:0] code_fen_ge;
wire [7:0] code_fen_shi;
wire [7:0] code_shi_ge;
wire [7:0] code_shi_shi;
count u_count(
.clk (clk ),
.reset (reset ),
.key1 (key1 ),
.key2 (key2 ),
.key3 (key3 ),
.count_miao_ge (count_miao_ge ),
.count_miao_shi (count_miao_shi ),
.count_fen_ge (count_fen_ge ),
.count_fen_shi (count_fen_shi ),
.count_shi_ge (count_shi_ge ),
.count_shi_shi (count_shi_shi )
);
decoding u_decoding(
.clk (clk ),
.reset (reset ),
.count_miao_ge (count_miao_ge ),
.count_miao_shi (count_miao_shi ),
.count_fen_ge (count_fen_ge ),
.count_fen_shi (count_fen_shi ),
.count_shi_ge (count_shi_ge ),
.count_shi_shi (count_shi_shi ),
.code_miao_ge (code_miao_ge ),
.code_miao_shi (code_miao_shi ),
.code_fen_ge (code_fen_ge ),
.code_fen_shi (code_fen_shi ),
.code_shi_ge (code_shi_ge ),
.code_shi_shi (code_shi_shi )

);
sel_show u_sel_show(
.clk (clk ),
.reset (reset ),
.code_miao_ge (code_miao_ge ),
.code_miao_shi (code_miao_shi ),
.code_fen_ge (code_fen_ge ),
.code_fen_shi (code_fen_shi ),
.code_shi_ge (code_shi_ge ),
.code_shi_shi (code_shi_shi ),
.led (led ),
.sel (sel )

);
endmodule
功能模块:
//功能模块//
/*
clk:全局时钟
reset:全局复位信号
key1: (KEY0)状态键
key2: (KEY1)加键
key3:(KEY1)减键
*/
module count(
input clk,
input reset,
input key1,
input key2,
input key3,
output [3:0] count_miao_ge,
output [2:0] count_miao_shi,
output [3:0] count_fen_ge,
output [2:0] count_fen_shi,
output [3:0] count_shi_ge,
output [1:0] count_shi_shi
);
wire button_negedge1;
wire button_negedge2;
wire button_negedge3;
ax_debounce u_ax_debounce1
(
.clk(clk),
.rst(~reset),
.button_in(key1),
.button_posedge(),
.button_negedge(button_negedge1),
.button_out()
);
ax_debounce u_ax_debounce2
(
.clk(clk),
.rst(~reset),
.button_in(key2),
.button_posedge(),
.button_negedge(button_negedge2),
.button_out()
);
ax_debounce u_ax_debounce3
(
.clk(clk),
.rst(~reset),
.button_in(key3),
.button_posedge(),
.button_negedge(button_negedge3),
.button_out()
);
reg [31:0] cnt;
reg [3:0] count_miao_ge_reg;
reg [2:0] count_miao_shi_reg;
reg [3:0] count_fen_ge_reg;
reg [2:0] count_fen_shi_reg;
reg [3:0] count_shi_ge_reg;
reg [1:0] count_shi_shi_reg;
reg [1:0] state;

assign count_miao_ge = count_miao_ge_reg; //秒的个位
assign count_miao_shi = count_miao_shi_reg;//秒的十位
assign count_fen_ge = count_fen_ge_reg;//分的个位
assign count_fen_shi = count_fen_shi_reg;//分的十位
assign count_shi_ge = count_shi_ge_reg;//时的个位
assign count_shi_shi = count_shi_shi_reg;//时的十位
always@(posedge clk or negedge reset)
begin
if(!reset)
state <= 2’d0;
else if(button_negedge1)
// else if(!key1)
begin
state <= state + 2’d1;
if(state == 2’d3)
state <= 2’d0;
end
else
state = state;
end
parameter cnt_max = 32’d4999_9999;
always@(posedge clk or negedge reset)
begin
if(!reset)
begin
cnt <= 32’d0;
count_miao_ge_reg <= 4’d0;
count_miao_shi_reg <= 3’d4;
count_fen_ge_reg <= 4’d9;
count_fen_shi_reg <= 3’d5;
count_shi_ge_reg <= 4’d2;
count_shi_shi_reg <= 2’d2;
end

				else
                case(state)
                0:
                //当计满一秒并且秒的个位小于9时,秒的个位加一
                if(cnt == cnt_max && count_miao_ge_reg<4'd9)
					begin
						count_miao_ge_reg <= count_miao_ge_reg + 4'd1;
						cnt <= 32'd0;
					end
				//当计满一秒并且秒的个位等于9时,秒的十位加一,秒的个位清零
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg<3'd5)
					begin
						count_miao_shi_reg <= count_miao_shi_reg + 3'd1;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
				//当计满一秒,秒到达59并且分的个位小于9时,分的个位加1	
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg==3'd5 && count_fen_ge_reg<4'd9)
					begin
						count_fen_ge_reg <= count_fen_ge_reg + 4'd1;	
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
				//当计满一秒,秒到达59并且分的个位等于9时,分的十位加1	
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg==3'd5 && count_fen_ge_reg==4'd9 && count_fen_shi_reg < 3'd5)
					begin
					   count_fen_shi_reg <= count_fen_shi_reg + 3'd1;
						count_fen_ge_reg <= 4'd0;
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
					//当计满一秒,秒到达59,分等于59时,时的个位小于<9,时的十位小于2时,时的个位加一	
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg==3'd5 && count_fen_ge_reg==4'd9 && count_fen_shi_reg ==3'd5 && count_shi_ge_reg < 4'd9 && count_shi_shi < 2'd2)
					begin
						count_shi_ge_reg <= count_shi_ge_reg + 4'd1;
						count_fen_shi_reg <= 3'd0;
						count_fen_ge_reg <= 4'd0;
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
					//当计满一秒,秒到达59,分等于59时,时的个位等于9时,时的十位<2,时的十位加一	
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg==3'd5 && count_fen_ge_reg==4'd9 && count_fen_shi_reg ==3'd5 && count_shi_ge_reg == 4'd9 && count_shi_shi < 2'd2)
					begin
						count_shi_shi_reg <= count_shi_shi + 2'd1;
					   count_shi_ge_reg <= 4'd0;
						count_fen_shi_reg <= 3'd0;
						count_fen_ge_reg <= 4'd0;
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
					//当计满一秒,秒到达59,分等于59时,时的个位小于3时,时的十位等于2,时的个位加一
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg==3'd5 && count_fen_ge_reg==4'd9 && count_fen_shi_reg ==3'd5 && count_shi_ge_reg < 4'd3 && count_shi_shi == 2'd2)
					begin
						count_shi_ge_reg <= count_shi_ge_reg + 4'd1;
						count_fen_shi_reg <= 3'd0;
						count_fen_ge_reg <= 4'd0;
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
				//当计满一秒,秒到达59,分等于59时,时等于23,所有清零
				else if(cnt == cnt_max && count_miao_ge_reg==4'd9 && count_miao_shi_reg==3'd5 && count_fen_ge_reg==4'd9 && count_fen_shi_reg ==3'd5 && count_shi_ge_reg == 4'd3 && count_shi_shi == 2'd2)
					begin
						count_shi_shi_reg <= 2'd0;
						count_shi_ge_reg <= 4'd0;
						count_fen_shi_reg <= 3'd0;
						count_fen_ge_reg <= 4'd0;
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
						cnt <= 32'd0;
					end
				else 
					begin
						cnt <= cnt + 32'd1;
					end
             1:
             begin
                if(button_negedge2)
                //if(!key2)
                begin
                if( count_miao_ge_reg<4'd9)
					begin
						count_miao_ge_reg <= count_miao_ge_reg + 4'd1;
					end
				else if(count_miao_ge_reg==4'd9 && count_miao_shi_reg<3'd5)
					begin
						count_miao_shi_reg <= count_miao_shi_reg + 3'd1;
						count_miao_ge_reg <= 4'd0;
					end
                 else if(count_miao_shi_reg==3'd5 && count_miao_ge==4'd9)
					begin
						count_miao_shi_reg <= 3'd0;
						count_miao_ge_reg <= 4'd0;
					end
                end
                 if(button_negedge3)
                 //if(!key3)
                begin
                if( count_miao_ge_reg>4'd0)
					begin
						count_miao_ge_reg <= count_miao_ge_reg - 4'd1;
					end
				else if(count_miao_ge_reg==4'd0 && count_miao_shi_reg>3'd0)
					begin
						count_miao_shi_reg <= count_miao_shi_reg - 3'd1;
						count_miao_ge_reg <= 4'd9;
					end
                 else if(count_miao_shi_reg==3'd0 && count_miao_ge_reg==4'd0)
					begin
						count_miao_shi_reg <= 3'd5;
						count_miao_ge_reg <= 4'd9;
					end
                end
                end
              2:
             begin
                if(button_negedge2)
                //if(!key2)
                begin
                if( count_fen_ge_reg<4'd9)
					begin
						count_fen_ge_reg <= count_fen_ge_reg + 4'd1;
					end
				else if(count_fen_ge_reg==4'd9 && count_fen_shi_reg<3'd5)
					begin
						count_fen_shi_reg <= count_fen_shi_reg + 3'd1;
						count_fen_ge_reg <= 4'd0;
					end
                 else if(count_fen_shi_reg==3'd5 && count_fen_ge==4'd9)
					begin
						count_fen_shi_reg <= 3'd0;
						count_fen_ge_reg <= 4'd0;
					end
                end
                 if(button_negedge3)
                 //if(!key3)
                begin
                if( count_fen_ge_reg>4'd0)
					begin
						count_fen_ge_reg <= count_fen_ge_reg - 4'd1;
					end
				else if(count_fen_ge_reg==4'd0 && count_fen_shi_reg>3'd0)
					begin
						count_fen_shi_reg <= count_fen_shi_reg - 3'd1;
						count_fen_ge_reg <= 4'd9;
					end
                 else if(count_fen_shi_reg==3'd0 && count_fen_ge_reg==4'd0)
					begin
						count_fen_shi_reg <= 3'd5;
						count_fen_ge_reg <= 4'd9;
					end
                end
                end
                3:
             begin
                if(button_negedge2)
                //if(!key2)
                begin
                if( count_shi_ge_reg<4'd9)
					begin
						count_shi_ge_reg <= count_shi_ge_reg + 4'd1;
					end
				else if(count_shi_ge_reg==4'd9 && count_shi_shi_reg<2'd2)
					begin
						count_shi_shi_reg <= count_shi_shi_reg + 2'd1;
						count_shi_ge_reg <= 4'd0;
					end
                 else if(count_shi_shi_reg==3'd2 && count_shi_ge==4'd4)
					begin
						count_shi_shi_reg <= 2'd0;
						count_shi_ge_reg <= 4'd0;
					end
                end
                 if(button_negedge3)
                 //if(!key3)
                begin
                if( count_shi_ge_reg>4'd0)
					begin
						count_shi_ge_reg <= count_shi_ge_reg - 4'd1;
					end
				else if(count_shi_ge_reg==4'd0 && count_shi_shi_reg>2'd0)
					begin
						count_shi_shi_reg <= count_shi_shi_reg - 2'd1;
						count_shi_ge_reg <= 4'd9;
					end
                 else if(count_shi_shi_reg==3'd0 && count_shi_ge_reg==4'd0)
					begin
						count_shi_shi_reg <= 2'd2;
						count_shi_ge_reg <= 4'd3;
					end
                end
                end
                endcase
                    
	end

endmodule
//段选译码
module decoding(
input clk,
input reset,
input [3:0] count_miao_ge,
input [2:0] count_miao_shi,
input [3:0] count_fen_ge,
input [2:0] count_fen_shi,
input [3:0] count_shi_ge,
input [1:0] count_shi_shi,
output reg [7:0] code_miao_ge,
output reg [7:0] code_miao_shi,
output reg [7:0] code_fen_ge,
output reg [7:0] code_fen_shi,
output reg [7:0] code_shi_ge,
output reg [7:0] code_shi_shi
);

always@(posedge clk or negedge reset)
begin
if(!reset)
code_miao_ge <= 8’b1111_1111;
else
begin
case(count_miao_ge)
4’d0:code_miao_ge <= 8’b1100_0000;
4’d1:code_miao_ge <= 8’b1111_1001;
4’d2:code_miao_ge <= 8’b1010_0100;
4’d3:code_miao_ge <= 8’b1011_0000;
4’d4:code_miao_ge <= 8’b1001_1001;
4’d5:code_miao_ge <= 8’b1001_0010;
4’d6:code_miao_ge <= 8’b1000_0010;
4’d7:code_miao_ge <= 8’b1111_1000;
4’d8:code_miao_ge <= 8’b1000_0000;
4’d9:code_miao_ge <= 8’b1001_0000;
default:code_miao_ge <= 8’b1011_1111;
endcase
end

	end

always@(posedge clk or negedge reset)
begin
if(!reset)
code_miao_shi <= 8’b1111_1111;
else
begin
case(count_miao_shi)
3’d0:code_miao_shi <= 8’b1100_0000;
3’d1:code_miao_shi <= 8’b1111_1001;
3’d2:code_miao_shi <= 8’b1010_0100;
3’d3:code_miao_shi <= 8’b1011_0000;
3’d4:code_miao_shi <= 8’b1001_1001;
3’d5:code_miao_shi <= 8’b1001_0010;
default:code_miao_shi <= 8’b1011_1111;
endcase
end

	end

always@(posedge clk or negedge reset)
begin
if(!reset)
code_fen_ge <= 8’b1111_1111;
else
begin
case(count_fen_ge)
4’d0:code_fen_ge <= 8’b0100_0000;
4’d1:code_fen_ge <= 8’b0111_1001;
4’d2:code_fen_ge <= 8’b0010_0100;
4’d3:code_fen_ge <= 8’b0011_0000;
4’d4:code_fen_ge <= 8’b0001_1001;
4’d5:code_fen_ge <= 8’b0001_0010;
4’d6:code_fen_ge <= 8’b0000_0010;
4’d7:code_fen_ge <= 8’b0111_1000;
4’d8:code_fen_ge <= 8’b0000_0000;
4’d9:code_fen_ge <= 8’b0001_0000;
default:code_fen_ge <= 8’b1011_1111;
endcase
end

	end

always@(posedge clk or negedge reset)
begin
if(!reset)
code_fen_shi <= 8’b1111_1111;
else
begin
case(count_fen_shi)
3’d0:code_fen_shi <= 8’b1100_0000;
3’d1:code_fen_shi <= 8’b1111_1001;
3’d2:code_fen_shi <= 8’b1010_0100;
3’d3:code_fen_shi <= 8’b1011_0000;
3’d4:code_fen_shi <= 8’b1001_1001;
3’d5:code_fen_shi <= 8’b1001_0010;
default:code_fen_shi <= 8’b1011_1111;
endcase
end

  end

always@(posedge clk or negedge reset)
begin
if(!reset)
code_shi_ge <= 8’b1111_1111;
else
begin
case(count_shi_ge)
4’d0:code_shi_ge <= 8’b0100_0000;
4’d1:code_shi_ge <= 8’b0111_1001;
4’d2:code_shi_ge <= 8’b0010_0100;
4’d3:code_shi_ge <= 8’b0011_0000;
4’d4:code_shi_ge <= 8’b0001_1001;
4’d5:code_shi_ge <= 8’b0001_0010;
4’d6:code_shi_ge <= 8’b0000_0010;
4’d7:code_shi_ge <= 8’b0111_1000;
4’d8:code_shi_ge <= 8’b0000_0000;
4’d9:code_shi_ge <= 8’b0001_0000;
default:code_shi_ge <= 8’b1011_1111;
endcase
end

	end

always@(posedge clk or negedge reset)
begin
if(!reset)
code_shi_shi <= 8’b1111_1111;
else
begin
case(count_shi_shi)
2’d0:code_shi_shi <= 8’b1100_0000;
2’d1:code_shi_shi <= 8’b1111_1001;
2’d2:code_shi_shi <= 8’b1010_0100;
default:code_shi_shi <= 8’b1011_1111;
endcase
end

  end

Endmodule
//位选动态显示
module sel_show(
input clk,
input reset,
input [7:0] code_miao_ge,
input [7:0] code_miao_shi,
input [7:0] code_fen_ge,
input [7:0] code_fen_shi,
input [7:0] code_shi_ge,
input [7:0] code_shi_shi,
output reg [7:0] led,
output reg [5:0] sel
);

reg [15:0] cnt;
reg flag;
//产生1000Hz的时钟
always@(posedge clk or negedge reset)
begin
if(!reset)
begin
cnt <=16’d0;
flag <= 1’b0;
end

		else if(cnt == 16'd500_00)
				begin
				   cnt <= 16'd0;
					flag <= 1'b1;
				end
		else
				begin
					cnt <= cnt + 16'd1;
					flag <= 1'b0;
				end
	end

reg [2:0] state;
parameter start = 3’d0; //开始状态
parameter sel_1 = 3’d1; //位选1
parameter sel_2 = 3’d2; //位选2
parameter sel_3 = 3’d3; //位选3
parameter sel_4 = 3’d4; //位选4
parameter sel_5 = 3’d5; //位选5
parameter sel_6 = 3’d6; //位选6
parameter ending = 3’d7;//结束
always @ (posedge clk or negedge reset)
begin
if(!reset)
begin
state <= 3’d0;
sel <= 6’b000_000;
end
else
case(state)
start:
begin
if(flag == 1’b1)
state <= sel_1;
else
state <= state;
end
sel_1:
begin
if(flag == 1’b1)
begin
state <= sel_2;
sel <= 6’b111_110;
led <= code_miao_ge;
end
else
state <= state;
end
sel_2:
begin
if(flag == 1’b1)
begin
state <= sel_3;
sel <= 6’b111_101;
led <= code_miao_shi;
end
else
state <= state;
end
sel_3:
begin
if(flag == 1’b1)
begin
state <= sel_4;
sel <= 6’b111_011;
led <= code_fen_ge;
end
else
state <= state;
end
sel_4:
begin
if(flag == 1’b1)
begin
state <= sel_5;
sel <= 6’b110_111;
led <= code_fen_shi;
end
else
state <= state;
end
sel_5:
begin
if(flag == 1’b1)
begin
state <= sel_6;
sel <= 6’b101_111;
led <= code_shi_ge;
end
else
state <= state;
end
sel_6:
begin
if(flag == 1’b1)
begin
state <= ending;
sel <= 6’b011_111;
led <= code_shi_shi;
end
else
state <= state;
end
ending:
state <= start;
default:
state <= start;
endcase
end
endmodule
在这里插入图片描述
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值