fpga:分秒计时器

任务目标

分秒计数器核心功能:实现从00:00到59:59的循环计数,通过四个七段数码管显示分钟和秒。

复位功能:支持硬件复位,将计数器归零并显示00:00。

启动/暂停控制:通过按键控制计时的启动和暂停。

消抖处理:消除按键抖动对计时逻辑的影响,确保按键响应稳定。

实现思路

核心功能

计数逻辑:

使用两个BCD(二进制编码的十进制)计数器分别存储分钟和秒:

秒计数器:个位(0-9)和十位(0-5)。

分钟计数器:个位(0-9)和十位(0-5)。

每秒递增秒计数器:

当秒的个位达到9时,十位加一,个位归零。

当秒的十位达到5且个位达到9时,分钟计数器加一,秒计数器归零。

当分钟的个位达到9且十位达到5时,计数器归零。

显示逻辑:

将BCD计数器的值转换为七段数码管的段码。

使用查找表(case语句)将每个数字映射到对应的段码。

确保数码管的段码格式正确(共阳极或共阴极)。

边界条件:

秒从59递增到0(即60)时,分钟加一。

分钟从59递增到0(即60)时,计数器归零。

七段数码管

数码管的一种是半导体发光器件,数码管可分为七段数码管和八段数码管,区别在于八段数码管比七段数码管多一个用于显示小数点的发光二极管单元DP(decimal point),其基本单元是发光二极管。

七段数码管分为共阳极及共阴极,共阳极的七段数码管的正极(或阳极)为八个发光二极管的共有正极,其他接点为独立发光二极管的负极(或阴极),使用者只需把正极接电,不同的负极接地就能控制七段数码管显示不同的数字。共阴极的七段数码管与共阳极的只是接驳方法相反而已。

如图是数码管显示编码表,包含了共阳和共阴两种不同的极性。

复位功能

复位信号:

使用一个硬件按键作为复位输入,按下时复位信号激活。

复位信号为低电平有效或高电平有效,需根据具体硬件设计确定。

复位逻辑:

当复位信号激活时,将所有计数器清零。

同时将状态机重置到初始状态(暂停状态)。

确保复位信号优先级高于其他操作,避免复位过程中计数器继续运行。

启动/暂停控制功能

状态管理:

使用状态机管理计时逻辑,定义两个状态:

IDLE(暂停状态)。

RUNNING(运行状态)。

按键按下时,状态在IDLE和RUNNING之间切换。

按键检测:

使用边沿检测识别按键的按下事件,避免误触发。

在状态机中,根据当前状态和按键输入更新下一个状态。

状态输出:

在RUNNING状态下,每秒递增计数器。

在IDLE状态下,计数器保持不变。

消抖功能

抖动特性:

按键抖动会导致信号短时间内多次变化,需要通过延时采样消除抖动。

消抖逻辑:

使用一个计时器检测按键状态的稳定性:

当检测到按键状态变化时,启动计时器。

如果在设定时间(如20ms)内状态保持稳定,则更新按键状态。

计时器的位宽需足够大,确保能够覆盖设定的延时。

稳定输出:

只有当按键状态稳定后,才输出有效的控制信号。

确保消抖后的信号与原始按键信号的极性一致。

思考

为什么要消抖?

机械按键在按下或释放的瞬间,由于物理触点的弹性作用,会产生一系列快速的开闭跳变,这种现象称为按键抖动。抖动信号表现为一系列短暂的高低电平变化,而不是理想的单一电平变化。

抖动信号可能导致电路误判按键状态,例如,一次按键可能被误认为多次按键。同时抖动信号会导致输出不稳定,影响后续逻辑电路的正常工作;频繁的信号变化可能增加电路的功耗和资源占用等。

因此消抖处理在数字电路设计中至关重要。

如下是按键原理图

状态机思想

状态机思想是一种用于设计和分析数字系统行为的模型,通过定义一系列状态、输入信号和状态转移规则来描述系统的动态行为。状态机的核心在于将复杂的行为分解为若干个简单的状态,并根据输入信号触发状态之间的转移,每个状态对应特定的输出或行为。状态机通常分为Moore型(输出仅取决于当前状态)和Mealy型(输出取决于当前状态和输入信号),具有模块化设计、清晰逻辑和高效资源利用的优点。

在本次任务中我们可以设置IDLE(暂停状态,计数器停止运行)RUNNING(运行状态,计数器每秒递增)两个状态。

代码实现

在这里我们采用分模块化编写代码,具体使用为:在Visual Studio Code中分模块化编写代码,然后编译(配置verilog语言编写环境,可以参考上期报告),编写无误后,使用Quartus 烧录下载,进行实现。

这里分为分频模块、消抖模块、暂停模块、计数器模块、显示模块、顶层模块

分频模块

module clock_divider #(parameter DIVISOR = 50000000  // 默认50MHz->1Hz)(input clk_in,input reset_n,output reg clk_out);reg [31:0] counter;always @(posedge clk_in or negedge reset_n) beginif (!reset_n) begincounter <= 0;clk_out <= 0;endelse beginif (counter >= (DIVISOR/2 - 1)) begincounter <= 0;clk_out <= ~clk_out;endelse begincounter <= counter + 1;endendendendmodule

消抖模块

module debounce(input clk,input reset_n,input key_in,output reg key_pulse);reg [19:0] count;  // 20ms 消抖计数器 (50MHz时钟下,1ms=50000个周期)reg key_in_sync1, key_in_sync2;reg key_stable;always @(posedge clk or negedge reset_n) beginif (!reset_n) beginkey_in_sync1 <= 1'b1;key_in_sync2 <= 1'b1;key_stable <= 1'b1;count <= 20'd0;key_pulse <= 1'b0;endelse begin// 同步输入信号key_in_sync1 <= key_in;key_in_sync2 <= key_in_sync1;// 检测按键状态变化if (key_in_sync2 != key_stable) beginkey_stable <= key_in_sync2;count <= 20'd0;endelse if (count < 20'd1000000) begin  // 20ms (50MHz * 0.02s)count <= count + 1'b1;endelse beginkey_pulse <= key_in_sync2 & ~key_stable;  // 产生上升沿脉冲endendendendmodule

暂停模块

module pause_control(input clk,input reset_n,input pause_pulse,output reg pause_toggle);always @(posedge clk or negedge reset_n) beginif (!reset_n) beginpause_toggle <= 1'b0;endelse if (pause_pulse) beginpause_toggle <= ~pause_toggle;endendendmodule

计数器模块

module top(input clk_50m,         // 50MHz 时钟输入input reset_n,         // 复位按键 (低电平有效)input pause_key,       // 暂停/继续按键output [6:0] hex0,     // 秒个位数码管output [6:0] hex1,     // 秒十位数码管output [6:0] hex2,     // 分个位数码管output [6:0] hex3,     // 分十位数码管output [7:0] ledg      // LED 显示秒数 (可选));// 内部信号定义wire clk_1hz;             // 1Hz 时钟wire pause_pulse;         // 消抖后的暂停脉冲信号wire pause_toggle;        // 暂停状态信号wire [3:0] sec_ones;      // 秒个位wire [3:0] sec_tens;      // 秒十位wire [3:0] min_ones;      // 分个位wire [3:0] min_tens;      // 分十位// 时钟分频模块clock_divider #(.DIVISOR(50000000)    // 50MHz -> 1Hz) clk_div (.clk_in(clk_50m),.reset_n(reset_n),.clk_out(clk_1hz));// 按键消抖模块debounce debounce_pause (.clk(clk_50m),.reset_n(reset_n),.key_in(pause_key),.key_pulse(pause_pulse));// 暂停控制模块 (将脉冲信号转换为 toggle 信号)pause_control pause_ctrl (.clk(clk_50m),.reset_n(reset_n),.pause_pulse(pause_pulse),.pause_toggle(pause_toggle));// 分秒计数器模块min_sec_counter counter (.clk(clk_1hz),.reset_n(reset_n),.pause(pause_toggle),.sec_ones(sec_ones),.sec_tens(sec_tens),.min_ones(min_ones),.min_tens(min_tens));// 数码管显示模块seven_seg_display seg0 (.digit(sec_ones), .seg(hex0));seven_seg_display seg1 (.digit(sec_tens), .seg(hex1));seven_seg_display seg2 (.digit(min_ones), .seg(hex2));seven_seg_display seg3 (.digit(min_tens), .seg(hex3));endmodule

显示模块

module seven_seg_display(input [3:0] digit,output reg [6:0] seg);always @(*) begincase (digit)4'h0: seg = 7'b1000000;  // 04'h1: seg = 7'b1111001;  // 14'h2: seg = 7'b0100100;  // 24'h3: seg = 7'b0110000;  // 34'h4: seg = 7'b0011001;  // 44'h5: seg = 7'b0010010;  // 54'h6: seg = 7'b0000010;  // 64'h7: seg = 7'b1111000;  // 74'h8: seg = 7'b0000000;  // 84'h9: seg = 7'b0010000;  // 9default: seg = 7'b1111111;  // 全灭endcaseendendmodule

顶层模块

module top(input clk_50m,         // 50MHz 时钟输入input reset_n,         // 复位按键 (低电平有效)input pause_key,       // 暂停/继续按键output [6:0] hex0,     // 秒个位数码管output [6:0] hex1,     // 秒十位数码管output [6:0] hex2,     // 分个位数码管output [6:0] hex3,     // 分十位数码管output [7:0] ledg      // LED 显示秒数 (可选));// 内部信号定义wire clk_1hz;             // 1Hz 时钟wire pause_pulse;         // 消抖后的暂停脉冲信号wire pause_toggle;        // 暂停状态信号wire [3:0] sec_ones;      // 秒个位wire [3:0] sec_tens;      // 秒十位wire [3:0] min_ones;      // 分个位wire [3:0] min_tens;      // 分十位// 时钟分频模块clock_divider #(.DIVISOR(50000000)    // 50MHz -> 1Hz) clk_div (.clk_in(clk_50m),.reset_n(reset_n),.clk_out(clk_1hz));// 按键消抖模块debounce debounce_pause (.clk(clk_50m),.reset_n(reset_n),.key_in(pause_key),.key_pulse(pause_pulse));// 暂停控制模块 (将脉冲信号转换为 toggle 信号)pause_control pause_ctrl (.clk(clk_50m),.reset_n(reset_n),.pause_pulse(pause_pulse),.pause_toggle(pause_toggle));// 分秒计数器模块min_sec_counter counter (.clk(clk_1hz),.reset_n(reset_n),.pause(pause_toggle),.sec_ones(sec_ones),.sec_tens(sec_tens),.min_ones(min_ones),.min_tens(min_tens));// 数码管显示模块seven_seg_display seg0 (.digit(sec_ones), .seg(hex0));seven_seg_display seg1 (.digit(sec_tens), .seg(hex1));seven_seg_display seg2 (.digit(min_ones), .seg(hex2));seven_seg_display seg3 (.digit(min_tens), .seg(hex3));endmodule

顶层模块是整个分秒计数器系统的集成中心,它负责协调各个子模块的工作,实现从时钟输入到数码管显示的完整功能链路。

编译无误过后就可以通过Quartus 烧录了。

实物效果

分秒计数器

总结

通过这次分秒计时器的设计实践,我对数字电路的模块化设计和状态机思想有了更深刻的理解。模块化设计将复杂系统分解为分频、消抖、暂停控制、计数器和显示等独立模块,不仅降低了设计难度,还提高了代码的可维护性和可扩展性。状态机的应用则通过定义IDLE和RUNNING两种状态,清晰地实现了计时器的启动和暂停功能。此外,硬件设计中的细节处理,如按键消抖和七段数码管的显示逻辑,让我认识到细节对系统稳定性的重要性。通过延时采样和段码转换,我解决了抖动和显示错误的问题,确保了计时器的准确性和可靠性。

这次实践让我更加体会到硬件设计是一个不断试错和优化的过程。从分频模块的调试到显示模块的优化,每一步都需要反复测试和调整。通过逐步集成和模块化测试,我不仅成功解决了多个技术难题,还积累很多经验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《UNIX网络编程卷1:套接字联网API》第6章 IO复用:select和poll函数

《UNIX网络编程卷1&#xff1a;套接字联网API》第6章 I/O复用&#xff1a;select和poll函数 6.1 I/O复用的核心价值与适用场景 I/O复用是高并发网络编程的基石&#xff0c;允许单个进程/线程同时监控多个文件描述符&#xff08;套接字&#xff09;的状态变化&#xff0c;从而高…

SpringBoot+vue前后端分离整合sa-token(无cookie登录态 详细的登录流程)

SpringBootvue前后端分离整合sa-token&#xff08;无cookie登录态 & 详细的登录流程&#xff09; 1.介绍sa-token1.1 框架定位1.2 核心优势 2.如何整合sa-token3.如何进行无cookie模式登录3.1后端3.1.1 VO层3.1.2 Controller层3.1.3 Service层 3.2前端3.2.1 登录按钮自定义…

MYOJ_1171:(洛谷P1075)[NOIP 2012 普及组] 质因数分解(数学相关,质数与约数基础)

题目描述 已知正整数 n 是两个不同的质数的乘积&#xff0c;试求出两者中较大的那个质数。 1≤n≤210^9 输入 输入一个正整数 n。 输出 输出一个正整数 p&#xff0c;即较大的那个质数。 样例输入输出 输入&#xff1a;21 输出&#xff1a;7 思路: 为了节约时间与…

Python语言的测试用例设计

Python语言的测试用例设计 引言 随着软件开发的不断进步&#xff0c;测试在软件开发生命周期中的重要性日益凸显。测试用例设计是软件测试的核心&#xff0c;它为软件系统的验证和验证提供了实施的基础。在Python语言中&#xff0c;由于其简洁明了的语法和强大的内置库&#…

SpringKafka消息消费:@KafkaListener与消费组配置

文章目录 引言一、Spring Kafka消费者基础配置二、KafkaListener注解使用三、消费组配置与负载均衡四、手动提交偏移量五、错误处理与重试机制总结 引言 Apache Kafka作为高吞吐量的分布式消息系统&#xff0c;在大数据处理和微服务架构中扮演着关键角色。Spring Kafka为Java开…

VMware 虚报化Ubuntu 卡成一B,如何接招?

故事背景 Win10 专业版 安装VMware pro ,虚拟化出一个Window10&#xff0c;另一个是UBuntu.自从使用起来去不去就卡死。开始是以为驱动或者升级造成的&#xff0c;重新安装一段时间问题照旧。更气人的这种现象具有不定期性&#xff0c;说不定什么时候就来这么一出。 直接解决方…

cloud项目批量修改主机号

当clone了一个cloud项目后&#xff0c;要把别人的主机号全部改成自己的&#xff0c;非常麻烦 在项目根目录下&#xff0c;启动 Git Bash。在 Git Bash 终端中使用原始的 Unix 命令&#xff1a; find . -type f -exec sed -i s/127\.0\.0\.1/132.168.190.163/g {} 其中127.0.…

微信小程序使用 Vant Weapp 组件库教程

在微信小程序项目中使用 Vant 组件库&#xff08;Vant Weapp&#xff09;主要包括以下几个步骤&#xff1a; 1. 初始化项目并安装 Vant Weapp 初始化 npm 在项目根目录下运行以下命令&#xff0c;生成 package.json&#xff1a; npm init -y安装 Vant Weapp 执行以下命令安装 V…

FPGA状态机思想实现流水灯及HDLBits学习

目录 第一章 在DE2-115上用状态机思想实现LED流水灯1.1 状态机设计思路1.2 Verilog代码实现1.3. 仿真测试代码1.4 编译代码与仿真 第二章 CPLD和FPGA芯片的主要技术区别是什么&#xff1f;它们各适用于什么场合&#xff1f;2.1 主要技术区别2.2 适用场合 第三章 HDLBits学习3.1…

与总社团联合会合作啦

2025.4.2日&#xff0c;我社团向总社团联合会与暮光社团发起合作研究“浔川代码编辑器v2.0”。至3日&#xff0c;我社团收到回复&#xff1a; 总社团联合会&#xff1a; 总社团联合会已收到浔川社团官方联合会的申请&#xff0c;经考虑&#xff0c;我们同意与浔川社团官方联合…

Shiro学习(三):shiro整合springboot

一、Shiro整合到Springboot步骤 1、准备SpringBoot 环境&#xff0c;这一步省略 2、引入Shiro 依赖 因为是Web 项目&#xff0c;所以需要引入web 相关依赖 shiro-spring-boot-web-starter&#xff0c;如下所示&#xff1a; 3、准备Realm 因为实例化 ShiroFilterFactoryBean 时…

【图形API】片段着色器自动计算LOD

片段着色器中的自动 LOD 计算详解 在图形渲染中&#xff0c;Level of Detail (LOD) 用于优化纹理采样的性能和视觉质量。片段着色器&#xff08;Fragment Shader&#xff09;能够自动计算 LOD&#xff0c;而顶点着色器&#xff08;Vertex Shader&#xff09;则不行。以下是详细…

24、 Python Socket编程:从协议解析到多线程实战

Python Socket编程&#xff1a;从协议解析到多线程实战 一、文章概述 本文深入讲解Python网络编程核心技术&#xff0c;涵盖TCP/UDP协议底层原理、Socket API全流程解析、高并发服务端开发实践&#xff0c;以及网络通信中的典型问题解决方案。通过3个递进式代码案例和协议设计…

LabVIEW 中数字转字符串常用汇总

在 LabVIEW 编程环境里&#xff0c;数字与字符串之间的转换是一项极为基础且重要的操作&#xff0c;广泛应用于数据处理、显示、存储以及设备通信等多个方面。熟练掌握数字转字符串的方法和技巧&#xff0c;对编写高效、稳定的程序起着关键作用。接下来&#xff0c;我们将全面深…

轨迹速度聚类 实战

根据轨迹把速度聚类为3个类别,速度快的那部分不用平滑,速度慢的部分需要平滑。 速度聚类3个类别: kmeans++ import numpy as np import cv2 from sklearn.cluster import KMeans from matplotlib.colors import hsv_to_rgb from scipy.ndimage import gaussian_filter1d# …

vulkanscenegraph显示倾斜模型(5.6)-vsg::RenderGraph的创建

前言 上一章深入分析了vsg::CommandGraph的创建过程及其通过子场景遍历实现Vulkan命令录制的机制。本章将在该基础上&#xff0c;进一步探讨Vulkan命令录制中的核心封装——vsg::RenderGraph。作为渲染流程的关键组件&#xff0c;RenderGraph封装了vkCmdBeginRenderPass和vkCmd…

第二十八章:Python可视化图表扩展-和弦图、旭日图、六边形箱图、桑基图和主题流图

一、引言 在数据可视化领域&#xff0c;除了常见的折线图、柱状图和散点图&#xff0c;还有一些高级图表类型可以帮助我们更直观地展示复杂数据关系。本文将介绍五种扩展图表&#xff1a;和弦图、旭日图、六边形箱图、桑基图和主题流图。这些图表在展示数据关系、层次结构和流量…

大模型-爬虫prompt

爬虫怎么写prompt 以下基于deepseek r1 总结&#xff1a; 以下是为大模型设计的结构化Prompt模板&#xff0c;用于生成专业级网络爬虫Python脚本。此Prompt包含技术约束、反检测策略和数据处理要求&#xff0c;可根据具体需求调整参数&#xff1a; 爬虫脚本生成Prompt模板1 …

Vue中将pdf文件转为图片

平时开发中,我们经常遇到的场景应该是调用后端接口返回给前端pdf格式的文件流,然后我们可以通过URL.createObjectURL的方式转为object url临时路径然后可以通过window.open的方式来打开一个新的浏览器页签来进行预览,效果如下图: 但有时候这样满足不了的需求,它不想这样预…

物联网安全技术:守护智能世界的防线

最近研学过程中发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击链接跳转到网站人工智能及编程语言学习教程。读者们可以通过里面的文章详细了解一下人工智能及其编程等教程和学习方法。下面开始对正文内容的…