• 方案介绍
  • 相关推荐
申请入驻 产业图谱

秒表计时器 FPGA 设计 Verilog Vivado

06/15 14:39
159
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

名称:秒表计时器 FPGA 设计 Verilog Vivado

软件:Vivado

语言:Verilog

功能介绍

本设计实现一个 FPGA 秒表计时器,核心功能包括启动计时、暂停保持和复位清零。计时精度以 10ms 为单位,输出包含 10毫秒、秒、分三组 BCD 风格计数数据,适合用于 FPGA 入门计时器、数码管显示控制、按键状态机控制等实验场景。

秒表控制通过 start_key 与 reset_key 两个按键信号完成。start_key 用于在空闲、计时、暂停状态之间切换,reset_key 用于进入复位状态并清零计时结果。计时范围按 10ms、秒、分逐级进位,10ms 计数到 99 后秒加 1,秒计数到 59 后分加 1,分计数到 59 后回到 0。

工程采用 Verilog 编写,配套 Vivado 工程文件和 XDC 管脚约束文件,便于直接查看源码结构、综合实现结果以及板级管脚分配。整体结构清晰,适合作为 FPGA 秒表、数字计时显示、按键控制状态机设计的参考工程。

运行环境

开发语言:Verilog

开发软件:Vivado

工程类型:FPGA 工程

主要文件:stopwatch.v、Digital_clock.v、display.v、fenping.v、key_jitter.v、pins.xdc、stopwatch.xpr

顶层相关模块:stopwatch、Digital_clock、display、fenping、key_jitter

设计思路

设计以秒表计时状态机为核心,通过 idle_state、cnt_time_state、hold_time_state、reset_time_state 四个状态描述秒表的工作流程。复位按键优先级最高,触发后进入复位状态并清空计时值;在空闲状态下按下启动键进入计时状态;计时过程中再次按下启动键进入暂停状态;暂停状态下再次按下启动键恢复计时。

计时部分采用 50MHz 系统时钟驱动寄存器更新,并通过 100Hz 节拍信号作为 10ms 计时使能。这样既保留了统一时钟域下的同步逻辑结构,又能用低频节拍控制实际计数递增,便于综合实现和时序分析。

计数逻辑分为 10毫秒、秒、分三个层级。10毫秒计数器在 0 到 99 之间循环,达到 99 后回零并推动秒计数;秒计数器在 0 到 59 之间循环,达到 59 后回零并推动分钟计数;分钟计数器同样在 0 到 59 之间循环。该结构直观体现了数字秒表的级联进位关系。

工程还包含显示、分频、按键消抖等配套模块,可将核心秒表计数结果进一步用于数码管动态显示。按键消抖模块用于提升机械按键输入的稳定性,分频模块用于产生计时和显示所需的节拍信号,显示模块负责将计时数据转换为可显示的输出形式。

模块结构

stopwatch:秒表核心计时模块,完成启动、暂停、复位状态控制,以及 10毫秒、秒、分计数。

Digital_clock:工程顶层相关模块,用于组织秒表、显示、分频和按键处理等功能单元。

display:显示控制模块,用于计时数据的显示驱动。

fenping:分频模块,用于产生低频计时或扫描节拍。

key_jitter:按键消抖模块,用于处理启动、复位等机械按键信号。

开发板验证

工程包含 Vivado XDC 管脚约束文件 pins.xdc,并已给出实现流程相关文件,可用于 FPGA 开发板管脚分配和上板验证。约束文件为时钟、按键和显示相关信号提供了板级连接依据,适合在对应硬件环境中进行下载测试与功能观察。

部分代码

以下展示顶层模块 stopwatch 的部分代码,完整源码请下载压缩包查看。

module stopwatch(
input clk_50M,
input clk_100Hz,//100Hz--对应10ms
input start_key,//启动//暂停
input reset_key,//复位
output [7:0] stopwatch_Millisecond,//10毫秒
output [7:0] stopwatch_second,//秒
output [7:0] stopwatch_minute//分
);

parameter idle_state=3\'d0;
parameter cnt_time_state=3\'d1;
parameter hold_time_state=3\'d2;
parameter reset_time_state=3\'d3;

reg [2:0] state=3\'d0;
//计时状态机
always@(posedge clk_50M)
	if(reset_key)
		state<=reset_time_state;//复位状态
	else
		case(state)
			reset_time_state://复位状态
				state<=idle_state;
			idle_state://空闲状态
				if(start_key)
					state<=cnt_time_state;
				else
					state<=idle_state;
			cnt_time_state://计时状态
				if(start_key)
					state<=hold_time_state;
				else
					state<=cnt_time_state;
			hold_time_state://暂停状态
				if(start_key)
					state<=cnt_time_state;
				else
					state<=hold_time_state;
			default:;
		endcase

reg [7:0] Millisecond_cnt=8\'d0;//10毫秒
reg [7:0] second_cnt=8\'d0;//秒
reg [7:0] minute_cnt=8\'d0;//分

always@(posedge clk_50M)
if(state==reset_time_state)//复位状态
	minute_cnt<=8\'d0;
else
	if(state==cnt_time_state && clk_100Hz==1)//计时状态
		if(Millisecond_cnt==8\'d99 && second_cnt==8\'d59)//59秒99\'时向前记1分
			if(minute_cnt<8\'d59)
				minute_cnt<=minute_cnt+8\'d1;//计时到990ms,下一次就到1秒了
			else
				minute_cnt<=8\'d0;
		else
			minute_cnt<=minute_cnt;
	else;

always@(posedge clk_50M)
if(state==reset_time_state)//复位状态
	second_cnt<=8\'d0;
else
	if(state==cnt_time_state && clk_100Hz==1)//计时状态
		if(Millisecond_cnt==8\'d99)//990ms时向前记1秒
			if(second_cnt<8\'d59)
				second_cnt<=second_cnt+8\'d1;//计时到990ms,下一次就到1秒了
			else
				second_cnt<=8\'d0;
		else
			second_cnt<=second_cnt;
	else;

always@(posedge clk_50M)
if(state==reset_time_state)//复位状态
	Millisecond_cnt<=8\'d0;
else
	if(state==cnt_time_state && clk_100Hz==1)//计时状态
		if(Millisecond_cnt<8\'d99)//计时到990ms,下一次就到1秒了
			Millisecond_cnt<=Millisecond_cnt+8\'d1;
		else
			Millisecond_cnt<=8\'d0;//计时到990ms,下一次就到1秒了
	else;

assign stopwatch_Millisecond=Millisecond_cnt;
assign stopwatch_second=second_cnt;
assign stopwatch_minute=minute_cnt;
	
endmodule

代码文件(付费下载)

相关推荐