5、简单的数码管时钟
0赞
发表于 7/9/2016 10:18:13 AM
阅读(1889)
//简单的数字时钟,六个数码管,分别显示秒的个位、秒的十位,分的个位、分的十位,时的个位、分的十位;二十四时钟计数显示制。
module seg8_clock(clk, rst_n, En, seg, sel);
input clk; //50MHz
input rst_n;
input En; //使能信号
output [5:0]sel; //6位
output reg[7:0]seg; //8段
reg [14:0]cnt1; //为了得到数码管扫描始终clk_1k
reg [25:0]cnt2; //为了得到计数1s(即second)
reg clk_1k;
reg second;
reg [7:0]disp_data_m; //定义2个数码管,每四位对应一个“秒”数码管上要显示的数字
reg [7:0]disp_data_f; //定义2个数码管,每四位对应一个“分”数码管上要显示的数字
reg [7:0]disp_data_s; //定义2个数码管,每四位对应一个“时”数码管上要显示的数字
reg [5:0]sel_r; //配合En使用,可以选择全部关闭数码管
reg [3:0]data_tmp; //暂时寄存软件工具输入的数据disp_data
reg cn; //“秒”计数到59之后,需要进1给“分”,cn一个时钟高电平
reg cm; //“分”计数到59之后,需要进1给“时”,cm一个时钟高电平
//计数器计数
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt1 <= 15'd0;
else if(!En)
cnt1 <= 15'd0;
else if(cnt1 == 15'd24_999)
cnt1 <= 15'd0;
else
cnt1 <= cnt1 + 1'b1;
//分频计数后产生clk_1k,1ms
always@(posedge clk or negedge rst_n)
if(!rst_n)
clk_1k <= 1'b0;
else if(cnt1 == 15'd24_999)
clk_1k <= ~clk_1k;
else
clk_1k <= clk_1k;
//-------------------------------------------
//分频计数,计数1s
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt2 <= 26'd0;
else if(cnt2 == 26'd49_999_999)
cnt2 <= 26'd0;
else
cnt2 <= cnt2 + 1'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
second <= 1'b0;
else if(cnt2 == 26'd49_999_999)
second <= 1'b1;
else
second <= 1'b0;
//----------------------------------------------
//6个数码管依次从左往右点亮,低电平点亮
always@(posedge clk_1k or negedge rst_n)
if(!rst_n)
sel_r <= 6'b11_1110;
else if(sel_r == 6'b01_1111)
sel_r <= 6'b11_1110;
else
sel_r <= {sel_r[4:0],sel_r[5]}; //右移,注意这里用"<<"以为要注意补位的情况
//位选,当sel_r等于对应的值时点亮对应的数码管,数码管显示软件工具输入的值,低电平点亮
reg a;
always@( * )
case(sel_r)
6'b11_1110: data_tmp = disp_data_m[3:0];//时
6'b11_1101: data_tmp = disp_data_m[7:4];//时
6'b11_1011: data_tmp = disp_data_f[3:0];//分
6'b11_0111: data_tmp = disp_data_f[7:4];//分
6'b10_1111: data_tmp = disp_data_s[3:0];//秒
6'b01_1111: data_tmp = disp_data_s[7:4];//秒
default:data_tmp = 4'b0000;
endcase
//段选,显示0-f在数码管上,板子上的是共阳数码管,低电平点亮
always@(*)
case(data_tmp)
4'h0: seg = 8'b1100_0000;
4'h1: seg = 8'b1111_1001;
4'h2: seg = 8'b1010_0100;
4'h3: seg = 8'b1011_0000;
4'h4: seg = 8'b1001_1001;
4'h5: seg = 8'b1001_0010;
4'h6: seg = 8'b1000_0010;
4'h7: seg = 8'b1111_1000;
4'h8: seg = 8'b1000_0000;
4'h9: seg = 8'b1001_0000;
default: seg = 8'b1100_0000;
endcase
//-----------------------------计数处理--------------------------------
//“秒”的处理
always@(posedge second or negedge rst_n)
if(!rst_n) begin
disp_data_m[3:0] <= 4'd0;
disp_data_m[7:4] <= 4'd0;
cn <= 0;
end
else begin
cn <= 0;
disp_data_m[3:0] <= disp_data_m[3:0] + 1'b1;
if(disp_data_m[3:0] == 4'd9) begin
disp_data_m[3:0] <= 4'd0;
disp_data_m[7:4] <= disp_data_m[7:4] + 1'b1;
if(disp_data_m[7:4] == 4'd5) begin
disp_data_m[7:4] <= 4'd0;
cn <= 1;
end
end
end
//“分”的处理,与“秒的处理”基本一样
always@(posedge cn or negedge rst_n)
if(!rst_n) begin
disp_data_f[3:0] <= 4'd0;
disp_data_f[7:4] <= 4'd0;
cm <= 0;
end
else begin
cm <= 0;
disp_data_f[3:0] <= disp_data_f[3:0] + 1'b1;
if(disp_data_f[3:0] == 4'd9) begin
disp_data_f[3:0] <= 4'd0;
disp_data_f[7:4] <= disp_data_f[7:4] + 1'b1;
if(disp_data_f[7:4] == 4'd5) begin
disp_data_f[7:4] <= 4'd0;
cm <= 1;
end
end
end
//“时”的处理
always@(posedge cm or negedge rst_n)
if(!rst_n) begin
disp_data_s[3:0] <= 4'd0;
disp_data_s[7:4] <= 4'd0;
end
else if(disp_data_s[7:4] == 4'd2 && disp_data_s[3:0] >= 4'd3) begin
disp_data_s[3:0] <= 4'd0;
disp_data_s[7:4] <= 4'd0;
end
else begin
disp_data_s[3:0] <= disp_data_s[3:0] + 1'b1;
if(disp_data_s[3:0] == 4'd9) begin
disp_data_s[3:0] <= 4'd0;
disp_data_s[7:4] <= disp_data_s[7:4] + 1'b1;
end
end
assign sel = (En)?sel_r:6'b11_1111;
endmodule顶层
module seg8_clock_top(clk, rst_n, seg, sel); input clk; //50MHz input rst_n; output [5:0]sel; //6位 output [7:0]seg; //8段 seg8_clock seg8_clock( .clk(clk), .rst_n(rst_n), .En(1'b1), .seg(seg), .sel(sel) ); endmodule
