FPGA-Verilog HDL 数字跑表详细版(附代码)

本文详细介绍了使用Verilog HDL在FPGA上设计数字跑表的过程,包括分频模块、毫秒转秒分模块以及数码管显示模块的分析与代码实现。通过对50MHz系统时钟的分频,生成毫秒、秒和分钟的信号,并最终在动态数码管上进行显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目分析

在这里插入图片描述

题目分析:
输入系统时钟CLK50MHZ。我们要做的就是通过计算经过多少个系统的CLK时钟,得到一个毫秒(百分秒)的输出,让它进一步作为秒、分钟的输入时钟信号。
如:通过100个毫秒的输入得到1个1秒的输出,再通过60个1秒得到1个1分钟的输出。

C L R , P A U S E 两 个 控 制 信 号 的 作 用 如 下 图 所 示 。 \tt CLR,PAUSE两个控制信号的作用如下图所示。 CLR,PAUSE
在这里插入图片描述

二、代码逻辑

从题目分析我们看到:
1、我们需要一个将系统内部时钟转换为一个毫秒信号时钟的分频模块。

2、需要将输入毫秒ms时钟信号转化能输出秒s,分钟m的模块。

3、需要能将毫秒ms、秒s、分钟m在数码管上显示的模块。

4、最后通过顶层模块top将所有模块串联起来实现功能。

1、分频模块的实现

1.1 divider模块分析

我们需要一个分频 m o d u l e \tt module module实现将50MHZ的输入系统sysclk转换成1个毫秒的输出CLK。

通过公式算出:
输入: T 1 = 1 50 M = 1 5 ∗ 1 0 7 T1=\frac {1}{50M}=\frac {1}{5*10^7} T1=50M1=51071

输出:1MS(毫秒) = T 2 = 1 100 T2=\frac {1}{100} T2=1001

T 2 = 5 ∗ 1 0 5 ∗ T 1 T2=5*10^5*T1 T2=5105T1,也就是经过500000个周期T1的系统sysclk才输出一个毫秒信号 C L K \tt CLK CLK

1.2 代码详解

通过定义一个线宽为19位的reg型中间变量count(因为500000的二进制有19位),每过一个50MHZ系统输入sysclk就加一。

每经过一个上升沿时第一步先判断count是否等于499999,不等于就加一;当第500000个sysclk上升沿来到,说明系统时钟已经经过了500000个周期了,此时count等于499999,就清零count重新开启下一轮的计数,并产生一个毫秒的上升沿的信号CLK输出,CLK从0变为1。

当CLR清零信号有效时,计数变量count清零,从头开始计数。

在这里插入图片描述

2、毫秒MS转化秒S、分钟M的模块实现

2.1 模块分析

1、通过将百分秒输出的CLK计算累计到100个,将毫秒向秒进位,标志count_ms从0置1。
2、低位L都是满9后,在下一个时钟周期来到高位H进一 ,并将低位L清零。例如:秒低SL=9,当下一个count_ms来到,秒高位SH+1,SL=0。
3、当高位秒SH满5,且SL满9产生秒S进位分钟M,标志count_s从0置1。

2.2 代码详解

MS代表毫秒,S代表秒,M代表分钟。L代表低位,H代表高位。

例如,当毫秒的时钟CLK 上升沿来临,低位百分秒MSL加一,当MSL=9时,在下一个时钟周期CLK来临,高位百分秒MSH就进位加一,并将MSL清零。以此往复待到MS满99,再下一个CLK,就产生秒S的时钟进位上升沿count_ms,激发低位秒SL加一。

同理当S满59时,产生分钟的时钟进位上升沿count_s,激发低位分钟ML加一。以此循环往复、、、。

module stop_watch(CLK,CLR,PAUSE,MSL,MSH,SL,SH,ML,MH);
input CLK,CLR,PAUSE;
output [3:0]MSL,MSH,SL,SH,ML,MH;

reg [3:0]MSL,MSH,SL,SH,ML,MH;
reg count_ms,count_s;//产生进位的标志

initial 
begin
    MSL<=0;MSH<=0;SL<=0;SH<=0;ML<=0;MH<=0;
end

always @(posedge CLK or posedge CLR)
begin
	if(CLR)
		begin
			MSL<=0;
			MSH<=0;
		end
	else if(!PAUSE)
		begin
			if(MSL==9)
				begin
					MSL<=0;
					if(MSH==9)
						begin
							MSH<=0;
							count_ms<=1;//百分秒为99,标志为1
						end
					else 
						begin
						MSH<=MSH+1;
						count_ms<=0;
						end
				end
			else
				begin
					MSL<=MSL+1;
				end
		end
	else
		begin
			MSL<=MSL;
			MSH<=MSH;
		end
end

always @(posedge count_ms or posedge CLR)
begin
	if(CLR)
		begin
			SH<=0;
			SL<=0;
		end
	else if(PAUSE)
			begin
				SH<=SH;
				SL<=SL;
			end
	else
		begin
			if(SL==9)
				begin
					SL<=0;
					if(SH==5)
						begin
						SH<=0;
						count_s<=1;//秒为59,标志为1
						end
					else
						begin
						SH<=SH+1;
						count_s<=0;
						end
				end
			else
				begin
					SL<=SL+1;
				end
		end
end

always @(posedge count_s or posedge CLR)
begin
	if(CLR)
		begin
			MH<=0;
			ML<=0;
		end
	else if(PAUSE)
		begin
			MH<=MH;
			ML<=ML;
		end
	else
		begin
			if(ML==9)
				begin
					ML<=0;
					if(MH==5)
							MH<=0;//分钟为59清零	
					else
						MH<=MH+1;
				end
			else
				begin
					ML<=ML+1;
				end
		end
end

endmodule

3、毫秒、秒、分钟显示到动态数码管

毫秒、秒、分钟各有十位、个位。将其个位、十位都按顺序显示到动态数码管上。一共要用到6根数码管。
通过段选确定数据管0~9的显示。

因为动态数码管只能显示一个,实质是通过快速位选信号,在6’b000001,6’b000010,、、、,6’b100000快速变动(如6’b000001表示第一根数码管亮)。
这样使得人眼无法察觉数码管之间的跳变,达到在人眼看起来6根数码管在同时显示。

3.1 代码

//动态数码管显示代码

module led(CLK,CLR,MSL,MSH,SL,SH,ML,MH,OUT);

input CLK,CLR;
input [3:0]MSL,MSH,SL,SH,ML,MH;
output [13:0]OUT;

reg [2:0]H_out;
reg [13:0]OUT;
always @(posedge CLK ,posedge CLR)
begin
	if(CLR)
		H_out<=0;
	else if(H_out==6)
		H_out<=0;
	else 
		H_out<=H_out+1;
end

function [7:0]Xrom;
	input [3:0] sum;
	case(sum)
		4'b0000 : Xrom = 8'b00111111;
		4'b0001 : Xrom = 8'b00000110;
		4'b0010 : Xrom = 8'b01011011;
		4'b0011 : Xrom = 8'b01001111;	
		4'b0100 : Xrom = 8'b01100110;
		4'b0101 : Xrom = 8'b01101101;
		4'b0110 : Xrom = 8'b01111101;
		4'b0111 : Xrom = 8'b00000111;
		4'b1000 : Xrom = 8'b01111111;
		4'b1001 : Xrom = 8'b01101111;
		default:Xrom =8'b00111111;
	endcase
endfunction

always @(CLR or H_out)
begin
		if(CLR) 
		       OUT<=0;
     	else 
			begin
				case(H_out) 		
					0: OUT  <= {6'b000001,Xrom(MSL)};  
					1: OUT  <= {6'b000010,Xrom(MSH)};  
					2: OUT  <= {6'b000100,Xrom(SL)};  
					3: OUT  <= {6'b001000,Xrom(SH)}; 
					4: OUT  <= {6'b010000,Xrom(ML)};  
					5: OUT  <= {6'b100000,Xrom(MH)};    
					default : OUT  <= 0;  
				endcase
			end
end
endmodule

三、总结

数字跑表,首先要想好,如何通过FPGA板子内部时钟获得毫秒?通过毫秒如何获得秒、分钟?
其次如何将毫秒、秒、分钟各自的个位、十位对应显示到动态数码管上?

//TOP顶层模块设计

module top(sysclk,CLR,PAUSE,OUT);
input sysclk,CLR,PAUSE;
output [13:0]OUT;

wire CLK;
wire [3:0]MSL,MSH,SL,SH,ML,MH;
wire led_clk;

divider u1(.sysclk(sysclk),.CLR(CLR),.CLK(CLK));
stop_watch u2(.CLK(CLK),.CLR(CLR),.PAUSE(PAUSE),.MSL(MSL),.MSH(MSH),.SL(SL),.SH(SH),.ML(ML),.MH(MH));	
assign led_clk=CLK/10;
led u3(.CLK(led_clk),.CLR(CLR),.MSL(MSL),.MSH(MSH),.SL(SL),.SH(SH),.ML(ML),.MH(MH),.OUT(OUT));

endmodule
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值