基于FPGA的数字钟(四)——时钟控制模块

一、需求分析

时钟控制模块,需要生成秒,分,时三路信号,需要有外部信号能对其进行控制。
按照正常时钟逻辑:
秒满60归零;
分在秒满60时进1,分满60归零;
时在分满60时进1,时满24归零。
外部控制方案选用键盘,因此需要引入按键消抖模块(见本人博客 基于FPGA的数字钟——(二)按键消抖模块设计)
本文链接:https://blog.csdn.net/qq_43650722/article/details/103808539

二、方案实现

方案一:

直接产生秒,分,时信号,以二进制数进行编码:
模块代码如下:

//////////////////////////////////////////////////////////////////////////////////
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
// 
// Create Date: 2019/12/29 15:55:40
// Design Name: clock
// Module Name: clock
// Project Name: Clock
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module clock(
	input 				clk,					//system clock
	input 				rst,					//system rst
	output reg[4:0] 	h,						//output h,0-24
	output reg[5:0] 	min,					//output min,0-60
	output reg[5:0] 	s,						//output s,0-60
	output reg[9:0] 	ms,					//output ms,0-1000
	input 				h_plus,				//h_plus_signal(posedge valid)
	input 				min_plus,			//min_plus_signal(posedge valid)
	input 				s_plus				//s_plus_signal(posedge valid)
);
	reg[15:0] 			ms_cnt;
	reg 					h_plus_temp0;
	reg 					h_plus_temp1;
	reg 					min_plus_temp0;
	reg 					min_plus_temp1;
	reg 					s_plus_temp0;
	reg 					s_plus_temp1;
	
	wire 					h_plus_pedge;
	wire 					min_plus_pedge;
	wire 					s_plus_pedge;
	assign 				h_plus_pedge = (h_plus_temp0)&(!h_plus_temp1);//时间改变信号上升沿检测
	assign 				min_plus_pedge = (min_plus_temp0)&(!min_plus_temp1);
	assign 				s_plus_pedge = (s_plus_temp0)&(!s_plus_temp1);
	//**************************************
	//外部增加时间信号采集
	always@(posedge clk or negedge rst)begin
		if(!rst)begin
			h_plus_temp0 <= 1'b0;
			h_plus_temp1 <= 1'b0;
		end
		else begin
			h_plus_temp0 <= h_plus;
			h_plus_temp1 <= h_plus_temp0;
		end
	end
	
	always@(posedge clk or negedge rst)begin
		if(!rst)begin
			min_plus_temp0 <= 1'b0;
			min_plus_temp1 <= 1'b0;
		end
		else begin
			min_plus_temp0 <= min_plus;
			min_plus_temp1 <= min_plus_temp0;
		end
	end
	
	always@(posedge clk or negedge rst)begin
		if(!rst)begin
			s_plus_temp0 <= 1'b0;
			s_plus_temp1 <= 1'b0;
		end
		else begin
			s_plus_temp0 <= s_plus;
			s_plus_temp1 <= s_plus_temp0;
		end
	end
	//****************************************************
	//毫秒计数器,计数值50000
	always@(posedge clk or negedge rst)begin
	if(!rst)
		ms_cnt <= 16'd0;
	else	
		if(ms_cnt == 16'd50000)
			ms_cnt <= 16'd0;
		else
			ms_cnt <= ms_cnt + 1'b1;
	end
//毫秒逻辑,满1000归零
	always@(posedge clk or negedge rst)begin
	if(!rst)
		ms <= 10'd0;
	else
		if(ms == 10'd1000)
			ms <= 10'd0;
		else
			if(ms_cnt == 16'd50000)
				ms <= ms + 1'b1;
			else
				ms <= ms;
	end
//秒逻辑,逢毫秒满1000进1,满60归零
	always@(posedge clk or negedge rst)begin
	if(!rst)
		s <= 6'd0;
	else	
		if(s == 6'd60)
			s <= 6'd0;
		else
			if(ms == 10'd1000)
				s <= s + 1'b1;
			else
				if(s_plus_pedge)
					s <= s + 1'b1;
				else
					s <= s;
	end
	//分钟逻辑,逢秒满60进1,满60归零
	always@(posedge clk or negedge rst)begin
	if(!rst)
		min <= 6'd0;
	else
		if(min == 6'd60)
			min <= 6'd0;
		else
			if(s == 6'd60)
				min <= min + 1'b1;
			else
				if(min_plus_pedge)
					min <= min + 1'b1;
				else
					min <= min;
	end	
	//时逻辑,逢分钟满60进1,满24归零
	always@(posedge clk or negedge rst)begin
	if(!rst)
		h <= 5'd0;
	else
		if(h == 5'd24)
			h <= 5'd0;
		else
			if(min == 6'd60)
				h <= h + 1'b1;
			else
				if(h_plus_pedge)
					h <= h + 1'b1;
				else
					h <= h;
	end

endmodule

此方案由于直接生成三路二进制编码时间信号,而数码管显示模块中每个数码管是独立的,每一位数码管只能显示个位数,而多位数码管无法在输入以二进制编码数据情况下直接显示多位数。参照(基于FPGA的数字钟——(三)时钟显示模块(数码管)本文链接:https://blog.csdn.net/qq_43650722/article/details/104010569)
例:若需要显示数字56,则需要将56分为5和6分别给两位数码管进行显示。
在此情况下则需要引入 数据解码模块 将两位十进制数分离出单独的十位和个位

在此情境下,有两种方案可选择

方案1:

此方法转载自 stubben_bear 的 利用verilog将二进制码转换为十进制BCD码 文
原文链接:https://blog.csdn.net/li200503028/article/details/19507061

方法:
首先给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例):

           1.将二进制码左移一位(或者乘2)

           2.找到左移后的码所对应的个,十,百位。

           3.判断在个位和百位的码是否大于5,如果是则该段码加3。

           4.继续重复以上三步直到移位8次后停止。

代码:

`timescale 1ns / 1ps

module bin_dec(clk,bin,rst_n,one,ten,hun,count,shift_reg
    );
input  [7:0] bin;
input        clk,rst_n;
output [3:0] one,ten;
output [3:0] count;
output [1:0] hun;
output [17:0]shift_reg;
reg    [3:0] one,ten;
reg    [1:0] hun;
reg    [3:0] count;
reg    [17:0]shift_reg=18'b000000000000000000;
////////////////////// 计数部分 ////////////////////////
always @ ( posedge clk or negedge rst_n )
begin
 if( !rst_n )
   count<=0;
 else if (count==9)
   count<=0;
 else
   count<=count+1;
end

////////////////////// 二进制转换为十进制 /////////////////
always @ (posedge clk or negedge rst_n )
begin
  if (!rst_n)
       shift_reg=0;
  else if (count==0)
       shift_reg={10'b0000000000,bin};
  else if ( count<=8)                //实现8次移位操作
   begin
      if(shift_reg[11:8]>=5)         //判断个位是否>5,如果是则+3  
          begin
             if(shift_reg[15:12]>=5) //判断十位是否>5,如果是则+3  
                 begin
   shift_reg[15:12]=shift_reg[15:12]+2'b11;   
   shift_reg[11:8]=shift_reg[11:8]+2'b11;
shift_reg=shift_reg<<1;  //对个位和十位操作结束后,整体左移
 end
             else
       begin
                   shift_reg[15:12]=shift_reg[15:12];
shift_reg[11:8]=shift_reg[11:8]+2'b11;
shift_reg=shift_reg<<1;
 end
          end              
      else
          begin
             if(shift_reg[15:12]>=5)
                 begin
   shift_reg[15:12]=shift_reg[15:12]+2'b11;
   shift_reg[11:8]=shift_reg[11:8];
shift_reg=shift_reg<<1;
 end
             else
       begin
                   shift_reg[15:12]=shift_reg[15:12];
shift_reg[11:8]=shift_reg[11:8];
shift_reg=shift_reg<<1;
 end
          end        
  end
  end

/////////////////输出赋值//////////////////////////
always @ ( posedge clk or negedge rst_n )
begin
 if ( !rst_n )
  begin
    one<=0;
    ten<=0;
    hun<=0; 
  end
 else if (count==9)  //此时8次移位全部完成,将对应的值分别赋给个,十,百位
  begin
    one<=shift_reg[11:8];
ten<=shift_reg[15:12];
hun<=shift_reg[17:16]; 
  end
end
endmodule

仿真结果:
在这里插入图片描述

方案2:

由于本设计中需要显示的数字最大为59,数据量并不大,因此可以采用查找表法将十位数分离。
代码:

//////////////////////////////////////////////////////////////////////////////////
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
// 
// Create Date: 2019/12/29 15:55:40
// Design Name: seg_encoder
// Module Name: seg_encoder
// Project Name: Clock
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module seg_encoder(
	clk,
	rst,
	data_in,
	out_10bit,
	out_1bit
);
	input clk;
	input rst;
	input[5:0] data_in;
	output reg[3:0] out_10bit;
	output reg[3:0] out_1bit;
	
	always@(posedge clk or negedge rst)
	if(!rst)begin
		out_10bit <= 4'd0;
		out_1bit <= 4'd0;
	end
	else begin
		case(data_in)
			6'd0:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd0;
			end
			6'd1:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd1;
			end
			6'd2:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd2;
			end
			6'd3:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd3;
			end
			6'd4:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd4;
			end
			6'd5:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd5;
			end
			6'd6:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd6;
			end
			6'd7:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd7;
			end
			6'd8:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd8;
			end
			6'd9:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd9;
			end
			6'd10:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd0;
			end
			6'd11:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd1;
			end
			6'd12:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd2;
			end
			6'd13:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd4;
			end
			6'd15:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd5;
			end
			6'd16:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd6;
			end
			6'd17:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd7;
			end
			6'd18:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd8;
			end
			6'd19:begin
				out_10bit <= 4'd1;
				out_1bit <= 4'd9;
			end
			6'd20:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd0;
			end
			6'd21:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd1;
			end
			6'd22:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd2;
			end
			6'd23:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd3;
			end
			6'd24:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd4;
			end
			6'd25:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd5;
			end
			6'd26:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd6;
			end
			6'd27:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd7;
			end
			6'd28:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd8;
			end
			6'd29:begin
				out_10bit <= 4'd2;
				out_1bit <= 4'd9;
			end
			6'd30:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd0;
			end
			6'd31:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd1;
			end
			6'd32:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd2;
			end
			6'd33:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd3;
			end
			6'd34:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd4;
			end
			6'd35:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd5;
			end
			6'd36:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd6;
			end
			6'd37:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd7;
			end
			6'd38:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd8;
			end
			6'd39:begin
				out_10bit <= 4'd3;
				out_1bit <= 4'd9;
			end
			6'd40:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd0;
			end
			6'd41:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd1;
			end
			6'd42:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd2;
			end
			6'd43:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd3;
			end
			6'd44:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd4;
			end
			6'd45:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd5;
			end
			6'd46:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd6;
			end
			6'd47:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd7;
			end
			6'd48:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd8;
			end
			6'd49:begin
				out_10bit <= 4'd4;
				out_1bit <= 4'd9;
			end
			6'd50:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd0;
			end
			6'd51:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd1;
			end
			6'd52:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd2;
			end
			6'd53:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd3;
			end
			6'd54:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd4;
			end
			6'd55:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd5;
			end
			6'd56:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd6;
			end
			6'd57:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd7;
			end
			6'd58:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd8;
			end
			6'd59:begin
				out_10bit <= 4'd5;
				out_1bit <= 4'd9;
			end
			6'd60:begin
				out_10bit <= 4'd6;
				out_1bit <= 4'd0;
			end
			default:begin
				out_10bit <= 4'd0;
				out_1bit <= 4'd0;
			end
		endcase
	end

endmodule

仿真图(部分):
在这里插入图片描述

发布了8 篇原创文章 · 获赞 13 · 访问量 4400

猜你喜欢

转载自blog.csdn.net/qq_43650722/article/details/104044757
今日推荐