改进的可调分秒的数字钟
经过上一篇文章改进而来
module CLK(
input sys_clk,
input rst_n,
input key,//分+
input key1,//秒+
output reg [5:0]sel_seg,//位选
output reg [7:0]seg_led//段选
);
localparam MAX_NUM = 14'd5000;
reg [7:0]sec;
reg [7:0]min;
reg [7:0]hour;
reg flag_sec;//秒进位信号
reg flag_min;//分进位信号
//分频模块
parameter CLK_DIV=4'd10;//分频系数
reg dri_clk;//5MHz数码管驱动时钟
reg [3:0]div_cnt;//分频计数
reg [23:0]sec_cnt;//秒计数,sec_cnt计满5M次为1s
wire [3:0]data0;//秒个位
wire [3:0]data1;//秒十位
wire [3:0]data2;//分个位
wire [3:0]data3;//分十位
wire [3:0]data4;//时个位
wire [3:0]data5;//时十位
assign data5=hour/4'd10;
assign data4=hour%4'd10;
assign data3=min/4'd10;
assign data2=min%4'd10;
assign data1=sec/4'd10;
assign data0=sec%4'd10;
wire key_value;
wire key_flag;
wire key_value1;
wire key_flag1;
key_debounce u_key_debounce(
.sys_clk(dri_clk),.sys_rst_n(rst_n),
.key(key),.key_flag(key_flag),.key_value(key_value));//消抖模块,借鉴的是正点原子的例程
key_debounce u_key_debounce1(
.sys_clk(dri_clk),.sys_rst_n(rst_n),
.key(key1),.key_flag(key_flag1),.key_value(key_value1));
always @(posedge sys_clk or negedge rst_n)begin
if(!rst_n)begin
div_cnt<=1'b0;
dri_clk<=1'b0;
end
else if(div_cnt==CLK_DIV/2-1)begin
dri_clk<=~dri_clk;
div_cnt<=4'd0;
end
else begin
div_cnt<=div_cnt+1'b1;
dri_clk<=dri_clk;
end
end
//秒计数模块
always @(posedge dri_clk or negedge rst_n)begin
if(!rst_n)begin
sec_cnt<=1'b0;
sec<=8'd0;
flag_sec<=1'b0;
end
else if(key_flag1&&(~key_value1))begin
if(sec==8'd59)
begin
sec<=8'd0;
flag_sec<=1'b1;
end
else begin
flag_sec<=1'b0;
sec<=sec+1'b1;
end
end
else if(sec_cnt==24'd500_0000)begin
if(sec==8'd59)begin
sec_cnt<=24'd0;
sec<=8'd0;
flag_sec<=1'b1;
end
else begin
flag_sec<=1'b0;
sec_cnt<=24'd0;
sec<=sec+1'b1;
end
end
else begin
flag_sec<=1'b0;
sec<=sec;
sec_cnt<=sec_cnt+1'b1;
end
end
//分计数模块
always @(posedge dri_clk or negedge rst_n)begin
if(!rst_n)begin
min<=8'd0;
flag_min<=1'b0;
end
else if(key_flag&&(~key_value)) begin
if(min==8'd59)
begin
min<=8'd0;
flag_min<=1'b1;
end
else begin
flag_min<=1'b0;
min<=min+1'b1;
end
end
else if(flag_sec)begin
if(min==8'd59)begin
flag_min<=1'b1;
min<=8'd0;
end
else begin
flag_min<=1'b0;
min<=min+1'b1;
end
end
else begin
flag_min<=1'b0;
min<=min;
end
end
//时计数模块
always @(posedge dri_clk or negedge rst_n)begin
if(!rst_n)begin
hour<=8'd0;
end
else if(flag_min)begin
if(hour==8'd24)
hour<=8'd0;
else hour<=hour+1'b1;
end
else hour<=hour;
end
reg [3:0]display_num;
reg [2:0]cnt0;//位选计数
reg [13:0]cnt1;
//数码管位选
reg flag;
always @(posedge dri_clk or negedge rst_n)begin
if(!rst_n)begin
cnt1<=14'd0;
flag<=1'b0;
end
else if(cnt1==MAX_NUM-1)begin
cnt1<=14'd0;
flag<=1'b1;
end
else begin
flag<=1'b0;
cnt1<=cnt1+1'b1;
end
end
always @(posedge dri_clk or negedge rst_n)begin
if(!rst_n)begin
cnt0<=3'd0;
end
else if(flag)begin
if(cnt0==3'd5)
cnt0<=3'd0;
else cnt0<=cnt0+1'b1;
end
else cnt0<=cnt0;
end
always @(posedge dri_clk or negedge rst_n)begin
if(!rst_n)begin
sel_seg<=6'b111111;
display_num<=4'd0;
end
else begin
case(cnt0)
3'd0:begin
sel_seg<=6'b111110;
display_num<=data0;
end
3'd1:begin
sel_seg<=6'b111101;
display_num<=data1;
end
3'd2:begin
sel_seg<=6'b111011;
display_num<=data2;
end
3'd3:begin
sel_seg<=6'b110111;
display_num<=data3;
end
3'd4:begin
sel_seg<=6'b101111;
display_num<=data4;
end
3'd5:begin
sel_seg<=6'b011111;
display_num<=data5;
end
default:begin
sel_seg<=6'b111111;
display_num<=4'd0;
end
endcase
end
end
//数码管显示
always@(posedge dri_clk or negedge rst_n)begin
if(!rst_n)
seg_led<=8'd1111111;
else begin
case(display_num)
4'd0:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b01000000;
else seg_led<=8'b11000000;
end
4'd1:begin
if(cnt0==3'd2||cnt0==3'd4) seg_led<=8'b01111001;
else seg_led<=8'b11111001;
end
4'd2:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00100100;
else seg_led<=8'b10100100;
end
4'd3:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00110000;
else seg_led<=8'b10110000;
end
4'd4:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00011001;
else seg_led<=8'b10011001;
end
4'd5:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00010010;
else
seg_led<=8'b10010010;
end
4'd6:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00000010;
else seg_led<=8'b10000010;
end
4'd7:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b01111000;
else seg_led<=8'b11111000;
end
4'd8:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00000000;
else seg_led<=8'b10000000;
end
4'd9:begin
if(cnt0==3'd2||cnt0==3'd4)
seg_led<=8'b00010000;
else seg_led<=8'b10010000;
end
default:seg_led<=8'b1111111;
endcase
end
end
endmodule