好久没有登博客了,周末出去浪了一转!!!
今天给大家讲一下数字时钟计数器,上个月写的。只是简单的数字时钟计数,没有设置闹钟、设置时间和秒表的功能,下次我会发一个带有功能的数字时钟,今天只是简单的数字时钟计数器。
由于我的板子只有4位数码管,因此该数字时钟我将用两位数码管进行分钟显示,两位数码管进行时钟显示,用一个LED灯进行秒钟闪烁。
(1)分频
数字时钟计数器,最重要的是分频系数。数字时钟所要进行的计数有秒钟计数、分钟计数、和时钟计数。
①
我所使用的板子内部时钟是50Mhz,首先要进行秒钟分频,由于要利用LED灯闪烁一次(高电平、低电平交替一次)代表1s,因此秒钟输出Ts=0.5s为一个周期,fs=1/Ts = 2Hz,分频系数为n_s=50Mhz/2hz-1=24999999;
②
接下来是时钟分频,时钟分频由秒钟输出时钟来计算,当秒钟上升沿到30次时,分钟时钟翻转一次,到59次时,再翻转一次,实现分钟计数(分钟时钟高电平、低电平交替一次为1分钟);
③
接下来是时钟分频,时钟分频原理类似于由秒钟时钟分频分钟时钟。
(2)有了秒钟时钟、分钟时钟、小时时钟,可以在各自的always块中设置对应数码管显示的参数,秒钟到分钟数字进制为60进制,分钟到时钟数字进制为60进制,时钟到天的数字进制为24进制,由于个位、十位在数码管上分开显示,我使用个位、十位分别计数(hg,hs,sg,ss)。
(3)然后我们还需要一个数码管动态显示的时钟,分频系数我设置为499,这个时钟大家可以根据人眼暂停原理自己设置满足该定理的分频系数即可。
(4)最后就是我们的动态显示,利用case语句和设置i变量循环实现动态显示。
代码如下:
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Grace
//
// Create Date: 19:59:03 10/17/2018
// Design Name:
// Module Name: D_CLOCK
// Project Name: D_clock
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module D_CLOCK(
input clk, //系统时钟输入
output reg [3:0] wei, //数码管位选
output reg [6:0] data_out, //数码管段选
output reg clk_s //秒钟输出
);
parameter n_s=24999999; //秒钟分频系数
parameter n_m=59; //分钟计数系数
parameter n_h=23; //时钟计数系数
parameter n_kj=499; //数码管显示时钟系数
reg clk_m; //分钟时钟
reg clk_h; //时钟时钟
reg [24:0] counts ; //秒钟计数器
reg [5:0] countm ; //分钟计数器
reg [4:0] counth ; //时钟计数器
reg [5:0] count_s; //秒钟计数器2,当此计数器为59时,分钟计数器+1
reg [5:0] count_m; //分钟计数器2,当此计数器为59时,时钟计数器+1
reg [3:0] hg; //时钟个位(用于显示)
reg [3:0] hs; //时钟十位(用于显示)
reg [3:0] mg; //分钟个位(用于显示)
reg [3:0] ms; //分钟十位(用于显示)
reg [8:0] count_kj; //数码管显示计数
reg clk_kj; //数码管显示时钟
integer i = 0;
initial //初始化个计数器
begin
counts = 25'b0;
counth = 5'b0;
countm = 6'b0;
count_s = 6'b0;
count_m = 6'b0;
clk_h = 1'b1;
clk_m = 1'b1;
hg = 4'b0;
hs = 4'b0;
ms = 4'b0;
mg = 4'b0;
end
/**********************************************************************************
数码管显示时钟分频
***********************************************************************************/
always @(posedge clk)
begin
if (count_kj == n_kj)
begin
clk_kj <= ~clk_kj;
count_kj <= 9'b0;
end
else
count_kj <= count_kj + 1'b1;
end
/***********************************************************************************
秒钟分频
***********************************************************************************/
always @(posedge clk)
begin
if (counts == n_s) //当秒钟计数到达时
begin
clk_s <= ~clk_s; //秒钟电平翻转,秒钟灯暗(亮)
counts <=25'b0; //秒钟计数器清零,用于重新计数
end
else //若秒钟计数未达到翻转值
counts <= counts + 1'b1; //秒钟计数+1
end
/************************************************************************************
分钟分频
************************************************************************************/
always @(posedge clk_s)
begin
count_s <= count_s + 1'b1;
if(count_s == 5'd30)
begin
count_s <= 6'b0;
clk_m <= ~clk_m;
end
else if(count_s == 6'd59)
begin
count_s <= 6'b0;
clk_m <= ~clk_m;
end
else
count_s <= count_s +1'b1;
end
end
/*************************************************************************************
分钟计数显示
*************************************************************************************/
always @(posedge clk_m)
begin
countm <= countm +1'b1;
if(count_m == n_m)
begin
countm <= 6'b0;
mg <= 6'b0;
ms <= 6'b0;
end
else
begin
mg <= mg +1'b1;
if(mg == 4'd9)
begin
mg <= 4'd0;
ms <= ms +1'b1;
end
end
end
/****************************************************************************************
时钟计数分频
****************************************************************************************/
always @(posedge clk_m)
begin
count_m <= count_m + 1'b1;
if(count_m == 5'd30)
begin
count_m <= 6'b0;
clk_h <= ~clk_h;
end
else if(count_m == 6'd59)
begin
count_m <= 6'b0;
clk_h <= ~clk_h;
end
else
count_m <= count_m +1'b1;
end
/****************************************************************************************
时钟计数显示
****************************************************************************************/
always @(posedge clk_h)
begin
counth <= counth +1'b1;
if(counth == n_h)
begin
counth <= 6'b0;
hg <= 6'b0;
hs <= 6'b0;
end
begin
hg <= hg +1'b1;
if(hg == 4'd9)
begin
hg <= 4'd0;
hs <= hs +1'b1;
end
end
end
/******************************************************************************************
数码管显示
*******************************************************************************************/
always @(posedge clk_kj)
begin
i = i +1;
if(i == 1)
begin
wei <= 4'b1110;
case (mg)
4'b0000: data_out <= 7'b1000000; // 0
4'b0001: data_out <= 7'b1111001; // 1
4'b0010: data_out <= 7'b0100100; // 2
4'b0011: data_out <= 7'b0110000; // 3
4'b0100: data_out <= 7'b0011001; // 4
4'b0101: data_out <= 7'b0010010; // 5
4'b0110: data_out <= 7'b0000011; // 6
4'b0111: data_out <= 7'b1111000; // 7
4'b1000: data_out <= 7'b0000000; // 8
4'b1001: data_out <= 7'b0011000; // 9
default: data_out <= 7'b1000000; // 0
endcase
end
else if(i == 2)
begin
wei <= 4'b1101;
case (ms)
4'b0000: data_out <= 7'b1000000; // 0
4'b0001: data_out <= 7'b1111001; // 1
4'b0010: data_out <= 7'b0100100; // 2
4'b0011: data_out <= 7'b0110000; // 3
4'b0100: data_out <= 7'b0011001; // 4
4'b0101: data_out <= 7'b0010010; // 5
default: data_out <= 7'b1000000; // 0
endcase
end
if(i == 3)
begin
wei <= 4'b1011;
case (hg)
4'b0000: data_out <= 7'b1000000; // 0
4'b0001: data_out <= 7'b1111001; // 1
4'b0010: data_out <= 7'b0100100; // 2
4'b0011: data_out <= 7'b0110000; // 3
4'b0100: data_out <= 7'b0011001; // 4
4'b0101: data_out <= 7'b0010010; // 5
4'b0110: data_out <= 7'b0000011; // 6
4'b0111: data_out <= 7'b1111000; // 7
4'b1000: data_out <= 7'b0000000; // 8
4'b1001: data_out <= 7'b0011000; // 9
default: data_out <= 7'b1000000; // 0
endcase
end
else if(i == 4)
begin
wei <= 4'b0111;
case (hs)
4'b0000: data_out <= 7'b1000000; // 0
4'b0001: data_out <= 7'b1111001; // 1
4'b0010: data_out <= 7'b0100100; // 2
default: data_out <= 7'b1000000; // 0
endcase
i = 0;
end
end
endmodule