诗人的眼YI

5、简单的数码管时钟

0
阅读(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