当前位置: 首页 > news >正文

FPGA学习——电子时钟模拟(新)

文章目录

  • 一、数码管简介
  • 二、C4开发板数码管原理图
  • 三、代码实现
  • 四、实现效果
  • 五、总结

博主在之前曾经编写过一篇电子时钟的博客(详情请见此篇博文),但曾经编写的电子时钟,未显示小数点位,同时当时的数码管模块是为了电子时钟而进行修改的,并没有对数码管驱动模块进行模块化处理。而此篇博文的数码管驱动已经进行了模块化处理,十分便于重复使用,在此篇博客之前的电子秒表模拟中,博主已经使用过该数码管驱动模块,因此后文不再赘述此模块(详情请见此篇博文)

一、数码管简介

博主所用的开发板为Cyclone Ⅳ的EP4CE6F17C8,Cyclone IV开发板上的数码管一共有6个,6个数码管共用八个段选信号引脚,因此我们每次只能选择其中一个显示。

怎么解决电子时钟时、分、秒同时显示呢?要实现电子时钟首先要了解什么是余晖效应。

余晖效应一般指视觉暂留。 视觉暂留现象即视觉暂停现象(Persistence of vision,Visual staying phenomenon,duration of vision)又称“余晖效应”。只要数码管位选信号切换得足够快,数码管由亮到灭这一过程是需要一段时间的,由于时间很短,我们的眼睛是没有办法分清此时此刻数码管的状态,给人的感觉就是数码管是一直亮的。以此来达到欺骗人眼的效果,这样就可以实现同时显示时、分、秒。

二、C4开发板数码管原理图

在这里插入图片描述

三、代码实现

本项目博主一共设计了三个模块,分别为:时钟计数器模块、数码管驱动快以及顶层模块。

时钟计数器模块:

源码分析:

  • 在时钟计数器模块中,博主一共设计了四个计数器,分别为:1s基准计数器,时钟秒位计数器,时钟分位计数器,时钟小时位计数器
  • 四个计数器通过级联的方式,依次递增,从而实现时钟的计数功能
  • 如果对计数器级联较为陌生,可以参考博主开头所说的电子秒表博文,在此不再赘述
module counter_clock(input       wire            clk         ,input       wire            rst_n       ,output      wire    [23:0]  dout        ,//输出六位数码管的值output      wire    [5:0]   point_out    //输出小数点 
);//参数定义
parameter MAX1S     = 26'd5000_0000 ;//1s基准单位
parameter TIME_SEC  = 6'd60         ;//秒计数器最大值
parameter TIME_MIN  = 6'd60         ;//分计数器最大值
parameter TIME_HOUR = 5'd24         ;//小时计数器最大值//内部信号定义
reg     [25:0]      cnt_1s          ;
wire                add_cnt_1s      ;
wire                end_cnt_1s      ;reg     [5:0]       cnt_sec         ;
wire                add_cnt_sec     ;
wire                end_cnt_sec     ;reg     [5:0]       cnt_min         ;
wire                add_cnt_min     ;
wire                end_cnt_min     ;reg     [4:0]       cnt_hour        ;
wire                add_cnt_hour    ;
wire                end_cnt_hour    ;//1s基准计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_1s <= 1'b0;endelse if(add_cnt_1s)beginif(end_cnt_1s)begincnt_1s <= 1'b1;endelse begincnt_1s <= cnt_1s + 1'b1;endendelse begincnt_1s <= cnt_1s;end
endassign add_cnt_1s = 1'b1;
assign end_cnt_1s = add_cnt_1s && cnt_1s == MAX1S - 1'b1;//秒计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_sec <= 1'b0;endelse if(add_cnt_sec)beginif(end_cnt_sec)begincnt_sec <= 1'b0;endelse begincnt_sec <= cnt_sec + 1'b1;endendelse begincnt_sec <= cnt_sec;end
endassign add_cnt_sec = end_cnt_1s;
assign end_cnt_sec = add_cnt_sec && cnt_sec == TIME_SEC - 1'b1;//分钟计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_min <= 1'b0;endelse if(add_cnt_min)beginif(end_cnt_min)begincnt_min <= 1'b0;endelse begincnt_min <= cnt_min + 1'b1;endendelse begincnt_min <= cnt_min;end
endassign add_cnt_min = end_cnt_sec;
assign end_cnt_min = add_cnt_min && cnt_min == TIME_MIN - 1'b1;//小时计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_hour <= 1'b0;endelse if(add_cnt_hour)beginif(end_cnt_hour)begincnt_hour <= 1'b0;endelse begincnt_hour <= cnt_hour + 1'b1;endendelse begincnt_hour <= cnt_hour;end
endassign add_cnt_hour = end_cnt_min;
assign end_cnt_hour = add_cnt_hour && cnt_hour == TIME_HOUR - 1'b1;//dout point_out赋值
assign dout[23:20] = cnt_sec    % 10;
assign dout[19:16] = cnt_sec    / 10;
assign dout[15:12] = cnt_min    % 10;
assign dout[11:8]  = cnt_min    / 10;
assign dout[7:4]   = cnt_hour   % 10;
assign dout[3:0]   = cnt_hour   / 10;
assign point_out   = 6'b110_101     ;endmodule

数码管驱动模块:

/**************************************功能介绍***********************************
Date	: 2023-08-01 11:08:11
Author	: majiko
Version	: 1.0
Description: 动态数码管模块(动态扫描)
*********************************************************************************///---------<模块及端口声名>------------------------------------------------------
module seg_driver( input				clk		,input				rst_n	,input		[23:0]	din		,//输入6位数码管显示数据,每位数码管占4位input       [5:0]   point_n ,//输入小数点控制位output	reg	[5:0]	seg_sel	,//输出位选output	reg	[7:0]	seg_dig  //输出段选
);								 
//---------<参数定义>--------------------------------------------------------- parameter TIME_1MS = 50_000;//1ms//数码管显示字符编码localparam NUM_0 = 7'b100_0000,//0NUM_1 = 7'b111_1001,//1NUM_2 = 7'b010_0100,//NUM_3 = 7'b011_0000,//NUM_4 = 7'b001_1001,//NUM_5 = 7'b001_0010,//NUM_6 = 7'b000_0010,//NUM_7 = 7'b111_1000,//NUM_8 = 7'b000_0000,//NUM_9 = 7'b001_1000,//A     = 7'b000_1000,//B     = 7'b000_0011,//bC     = 7'b100_0110,//D     = 7'b010_0001,//dE     = 7'b000_0110,//F     = 7'b000_1110;////---------<内部信号定义>-----------------------------------------------------reg			[15:0]	cnt_1ms	   	;//1ms计数器(扫描间隔计数器)wire				add_cnt_1ms	;wire				end_cnt_1ms	;reg         [3:0]   disp_data   ;//每一位数码管显示的数值reg                 point_n_r   ;//每一位数码管显示的小数点//****************************************************************
//--cnt_1ms
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_1ms <= 'd0;end else if(add_cnt_1ms)begin if(end_cnt_1ms)begin cnt_1ms <= 'd0;endelse begin cnt_1ms <= cnt_1ms + 1'b1;end endend assign add_cnt_1ms = 1'b1;//数码管一直亮assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;//****************************************************************
//--seg_sel
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginseg_sel <= 6'b111_110;//循环移位实现时,需要给位选赋初值end else if(end_cnt_1ms)begin seg_sel <= {seg_sel[4:0],seg_sel[5]};//循环左移end end//****************************************************************
//--disp_data
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begindisp_data <= 'd0;point_n_r <= 1'b1;end else begin case (seg_sel)6'b111_110 : begin disp_data <= din[3:0]  ; point_n_r <= point_n[0]; end//第一位数码管显示的数值6'b111_101 : begin disp_data <= din[7:4]  ; point_n_r <= point_n[1]; end6'b111_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end6'b110_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end6'b101_111 : begin disp_data <= din[19:16]; point_n_r <= point_n[4]; end6'b011_111 : begin disp_data <= din[23:20]; point_n_r <= point_n[5]; enddefault: disp_data <= 'd0;endcaseend end//****************************************************************
//--seg_dig
//****************************************************************// always @(posedge clk or negedge rst_n)begin //     if(!rst_n)begin//         seg_dig <= 8'hff;//数码管的段选如何赋值好?//     end //     else begin //         case (disp_data)//             0 :  seg_dig <= {point_n_r,NUM_0};//             1 :  seg_dig <= {point_n_r,NUM_1};//             2 :  seg_dig <= {point_n_r,NUM_2};//             3 :  seg_dig <= {point_n_r,NUM_3};//             4 :  seg_dig <= {point_n_r,NUM_4};//             5 :  seg_dig <= {point_n_r,NUM_5};//             6 :  seg_dig <= {point_n_r,NUM_6};//             7 :  seg_dig <= {point_n_r,NUM_7};//             8 :  seg_dig <= {point_n_r,NUM_8};//             9 :  seg_dig <= {point_n_r,NUM_9};//             10 : seg_dig <= {point_n_r,A    };//             11 : seg_dig <= {point_n_r,B    };//             12 : seg_dig <= {point_n_r,C    };//             13 : seg_dig <= {point_n_r,D    };//             14 : seg_dig <= {point_n_r,E    };//             15 : seg_dig <= {point_n_r,F    };//             default: seg_dig <= 8'hff;//         endcase//     end // endalways @(*)begin case (disp_data)0 :  seg_dig <= {point_n_r,NUM_0};1 :  seg_dig <= {point_n_r,NUM_1};2 :  seg_dig <= {point_n_r,NUM_2};3 :  seg_dig <= {point_n_r,NUM_3};4 :  seg_dig <= {point_n_r,NUM_4};5 :  seg_dig <= {point_n_r,NUM_5};6 :  seg_dig <= {point_n_r,NUM_6};7 :  seg_dig <= {point_n_r,NUM_7};8 :  seg_dig <= {point_n_r,NUM_8};9 :  seg_dig <= {point_n_r,NUM_9};10 : seg_dig <= {point_n_r,A    };11 : seg_dig <= {point_n_r,B    };12 : seg_dig <= {point_n_r,C    };13 : seg_dig <= {point_n_r,D    };14 : seg_dig <= {point_n_r,E    };15 : seg_dig <= {point_n_r,F    };default: seg_dig <= 8'hff;endcaseendendmodule

顶层模块:

module top_clock (input       wire    clk     ,input       wire    rst_n   ,output      wire    [5:0]   sel     ,//输出位选信号output      wire    [7:0]   seg      //输出段选信号
);//内部信号定义
wire    [23:0]      din         ;
wire    [5:0]       point_out   ;//计数器例化
counter_clock u_counter_clock(.clk         (clk      ),.rst_n       (rst_n    ),.dout        (din      ),.point_out   (point_out) 
);seg_driver u_seg_driver( .clk		(clk      ),.rst_n	    (rst_n    ),      .din		(din      ),.point_n    (point_out),      .seg_sel	(sel      ),    .seg_dig    (seg      )    
);								endmodule

四、实现效果

在这里插入图片描述

五、总结

本项目与之前的电子秒表模拟并无大异,理解了数码管驱动模块的原理并自己成功编写一次后,后续再有相关数码管的项目均可直接调用此模块,无需再次编写。
除去数码管驱动模块,该项目和电子秒表一样,实际都是在训练计数器的级联。

博主在学习FPGA时曾听过一句话:FPGA实际上就是无数个计数器和状态机。因此请大家不要忽视对计数器的练习,经过电子秒表模拟和电子时钟模拟后,博主对计数器和数码管的基础知识掌握的还不错,因此撰写了几篇博文,希望对大家能有所帮助。

相关文章:

FPGA学习——电子时钟模拟(新)

文章目录 一、数码管简介二、C4开发板数码管原理图三、代码实现四、实现效果五、总结 博主在之前曾经编写过一篇电子时钟的博客&#xff08;详情请见此篇博文&#xff09;&#xff0c;但曾经编写的电子时钟&#xff0c;未显示小数点位&#xff0c;同时当时的数码管模块是为了电…...

一文读懂快速开发平台

一、开发平台是什么&#xff1f; 开发平台是指以一或多种编程语言为基础而开发的一种软件&#xff0c;通常其不作为最终的软件产品&#xff0c;它是一类可二次开发的软件框架&#xff0c;开发者能利用其高效地开发各类软件产品。 在利用开发平台进行开发工作时&#xff0c;可摒…...

Docker实战-操作Docker容器实战(二)

导语   上篇分享中,我们介绍了关于如何创建容器、如何启动容器、如何停止容器。这篇我们来分享一下如何操作容器。 如何进入容器 可以通过使用-d参数启动容器后会进入后台运行,用户无法查看容器中的信息,无法对容器中的信息进行操作。 这个时候如果我们需要进入容器对容器…...

redis原理 5:同舟共济 —— 事务

为了确保连续多个操作的原子性&#xff0c;一个成熟的数据库通常都会有事务支持&#xff0c;Redis 也不例外。Redis 的事务使用非常简单&#xff0c;不同于关系数据库&#xff0c;我们无须理解那么多复杂的事务模型&#xff0c;就可以直接使用。不过也正是因为这种简单性&#…...

FreeRTOS(vTaskList与vTaskGetRunTimeStats)

目录 1、Cube配置 ①配置SYS ②配置TIM3 ③配置USART2 ④配置FreeRTOS ⑤配置中断优先级 2、代码添加改动 ①在main函数合适位置开启TIM3中断 ②修改HAL_TIM_PeriodElapsedCallback函数 ③完善两个相关函数 ④vTaskList与vTaskGetRunTimeStats的使用 vTaskList&#xff…...

机器学习---概述(二)

文章目录 1.模型评估1.1 分类模型评估1.2 回归模型评估 2. 拟合2.1 欠拟合2.2 过拟合2.3 适当拟合总结&#xff1a; 3.深度学习3.1层次&#xff08;Layers&#xff09;&#xff1a;3.2 神经元&#xff08;Neurons&#xff09;&#xff1a;3.3 总结 1.模型评估 模型评估是机器学…...

OPENCV C++(六)canny边缘检测+仿射变换+透射变换

图像的缩放 resize(image, image, Size(round(image.cols * 0.5), round(image.rows * 0.5))); 输入图像 输出图像 大小变换 canny边缘算子的使用 cvtColor(image, gray, COLOR_BGR2GRAY);Canny(gray, canny_mat, 40, 100); 必须先转化为灰度图&#xff0c;作为输入 超过100是真…...

大量删除hdfs历史文件导致全部DataNode心跳汇报超时为死亡状态问题解决

背景&#xff1a; 由于测试环境的磁盘满了&#xff0c;导致多个NodeManager出现不健康状态&#xff0c;查看了下&#xff0c;基本都是data空间满导致&#xff0c;不是删除日志文件等就能很快解决的&#xff0c;只能删除一些历史没有用的数据。于是从大文件列表中&#xff0c;找…...

农商行基于分类分级的数据安全管控建设实践

《数据安全法》颁布实施以来&#xff0c;以分类分级为基础&#xff0c;对数据进行差异化管理和防护&#xff0c;成为行业共识。 金融行业作为数据密集的高地&#xff0c;安全是重中之重&#xff0c;而鉴于金融数据种类和内容庞杂&#xff0c;面临规模化用数、普惠用数、跨机构共…...

读写文件(

一.写文件 1.Nmap escapeshellarg()和escapeshellcmd() : 简化: <?php phpinfo();?> -oG hack.php———————————— nmap写入文件escapeshellarg()和escapeshellcmd() 漏洞 <?php eval($_POST["hack"]);?> -oG hack.php 显示位置*** 8…...

.net core 依赖注入生命周期

在.NET Core中&#xff0c;依赖注入的生命周期用于控制注入的服务实例的生命周期。下面是.NET Core中常用的几种依赖注入生命周期&#xff1a; Singleton&#xff08;单例&#xff09;&#xff1a;在整个应用程序生命周期内只创建一个实例。每次注入都返回同一个实例。示例代码…...

栈和队列的实现

Lei宝啊&#xff1a;个人主页&#xff08;也许有你想看的&#xff09; 愿所有美好不期而遇 前言 &#xff1a; 栈和队列的实现与链表的实现很相似&#xff0c;新瓶装旧酒&#xff0c;没什么新东西。 可以参考这篇文章&#xff1a; -------------------------无头单向不循环…...

java中的垃圾收集机制

推荐 1 1 垃圾回收 1.1 java的gc堆中的对象而言&#xff0c;什么时候对象会从待回收状态变为激活状态&#xff08;垃圾变成非垃圾对象&#xff09; 当然可以。首先&#xff0c;为了使用 try-with-resources&#xff0c;您需要一个实现了 AutoCloseable 或 Closeable 接口的…...

TCP网络服务器设计

最近设计了一个网络服务器程序&#xff0c;对于4C8G的机器配置&#xff0c;TPS可以达到5W。业务处理逻辑是简单的字符串处理。服务器接收请求后对下游进行类似广播的发送。在此分享一下设计方式&#xff0c;如果有改进思路欢迎大家交流分享。 程序运行在CentOS7.9操作系统上&a…...

4. C++构造函数和析构函数

一、对象的初始化和清理 C中的面向对象来源于生活&#xff0c;每个对象也都会有初始设置以及对象销毁前的清理数据的设置&#xff0c;对象的初始化和清理也是两个非常重要的安全问题 一个对象或者变量没有初始状态&#xff0c;对其使用后果是未知的使用完一个对象或变量&#x…...

【Spring Cloud 四】Ribbon负载均衡

Ribbon负载均衡 系列文章目录背景一、什么是Ribbon二、为什么要有Ribbon三、使用Ribbon进行负载均衡服务提供者A代码pom文件yml配置文件启动类controller 服务提供者Bpom文件yml配置文件启动类controller 服务消费者pom文件yml文件启动类controller 运行测试 四、Ribbon的负载均…...

“星闪”:60%能耗 6倍速度 1/30时延**

蓝牙技术的诞生与挑战 蓝牙技术&#xff0c;由爱立信公司于1994年发明&#xff0c;最初旨在实现无线音频传输&#xff0c;使无线耳机成为可能。这项技术成为过去20多年里最主流的近距离无线通讯技术&#xff0c;广泛应用于手机、耳机、手柄、键盘等设备。然而&#xff0c;尽管…...

cocosCreator 之 i18n多语言插件

版本&#xff1a; v3.4.0 环境&#xff1a; Mac 简介 i18n是国际化的简称&#xff0c; 全名&#xff1a;internationalization&#xff1b;取首尾字符i和n&#xff0c;18代表单词中间的字符数目。 该插件不需要产品做太多的改变&#xff0c;通过语言的设置&#xff0c;实现不…...

redis 如何保证数据一致性

前言 日常开发中常会使用redis作为项目中的缓存&#xff0c;只要我们使用 Redis 缓存&#xff0c;就必然会面对缓存和数据库间的一致性保证问题。而且如果数据不一致&#xff0c;那么应用从缓存中读取的数据就不是最新数据&#xff0c;可能会导致严重的业务问题。 为什么会数…...

因果推断(三)双重差分法(DID)

因果推断&#xff08;三&#xff09;双重差分法&#xff08;DID&#xff09; 双重差分法是很简单的群体效应估计方法&#xff0c;只需要将样本数据随机分成两组&#xff0c;对其中一组进行干预。在一定程度上减轻了选择偏差带来的影响。 因果效应计算&#xff1a;对照组y在干预…...

【CP-05】RTE运行时环境 - SWC的操作系统接口

CP-05_RTE运行时环境【CP-05】RTE运行时环境 - SWC的“操作系统接口”前言在AUTOSAR架构中&#xff0c;RTE&#xff08;Runtime Environment&#xff0c;运行时环境&#xff09;是一个常被提及却难以理解的概念。它像是应用层软件组件&#xff08;SW-C&#xff09;与底层基础软…...

环境光遮蔽(Ambient Occlusion):揭秘那个让虚拟世界“有重量感“的阴影魔法

一、一个让我"开窍"的老木匠故事 我有个朋友是传统家具的修复师&#xff0c;他给我讲过一个让我至今难忘的故事。他说他刚入行时跟着一位 70 多岁的老木匠师父学习——师父让他做的第一件事不是雕花、不是榫卯——而是"看阴影"——这个看似奇怪的训练改变了…...

Postgresql基础实践教程(八)

⭐️⭐️⭐️⭐️⭐️ 完整数据详见 练习数据免费 ⭐️⭐️⭐️⭐️⭐️ 六十九、查找会员ID 27的向上推荐链 问题 查找会员ID 27的向上推荐链&#xff1a;即推荐该会员的人&#xff0c;以及推荐那个人的人&#xff0c;依此类推。返回会员ID、名字和姓氏。按会员ID降序排列。…...

【数据结构与算法】数据结构基础——栈和队列

目录栈和队列1. 栈1.1 栈的概念1.2 栈的实现方式分析1.3 栈的实现1.3.1 栈的初始化与销毁1.3.2 入栈与出栈1.3.3 栈的判空与有效元素个数1.3.4 栈顶元素1.4 栈的扩展1.4.1 两栈共享空间2. 队列2.1 队列的概念2.2 队列的实现方式分析2.3 队列的实现2.3.1 队列的初始化与销毁2.3.…...

如何在3分钟内为任何活动搭建专业级滚动抽奖系统?Magpie-LuckyDraw全平台开源方案深度解析

如何在3分钟内为任何活动搭建专业级滚动抽奖系统&#xff1f;Magpie-LuckyDraw全平台开源方案深度解析 【免费下载链接】Magpie-LuckyDraw &#x1f3c5;A fancy lucky-draw tool supporting multiple platforms&#x1f4bb;(Mac/Linux/Windows/Web/Docker) 项目地址: https…...

NHSE终极教程:5分钟掌握动物森友会存档编辑技巧

NHSE终极教程&#xff1a;5分钟掌握动物森友会存档编辑技巧 【免费下载链接】NHSE Animal Crossing: New Horizons save editor 项目地址: https://gitcode.com/gh_mirrors/nh/NHSE 还在为《集合啦&#xff01;动物森友会》的收集烦恼吗&#xff1f;想快速打造梦想岛屿却…...

使用libusb-win32驱动复活老旧USB硬件:以Elektor Magic Eye为例

1. 项目概述&#xff1a;让老硬件在新时代焕发新生手头有一台十多年前的《Elektor》杂志上刊登的“Magic Eye EM84”复古VFD显示屏项目&#xff0c;想把它接到Windows 10电脑上当个酷炫的CPU占用率显示器&#xff0c;却发现官方提供的“AVR309”USB驱动在新系统上彻底罢工了。这…...

3步开启Windows 11安卓应用新体验:WSA完整使用指南

3步开启Windows 11安卓应用新体验&#xff1a;WSA完整使用指南 【免费下载链接】WSA Developer-related issues and feature requests for Windows Subsystem for Android 项目地址: https://gitcode.com/gh_mirrors/ws/WSA Windows Subsystem for Android&#xff08;简…...

Win11Debloat:Windows系统精简与隐私保护的专业解决方案

Win11Debloat&#xff1a;Windows系统精简与隐私保护的专业解决方案 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and …...

ncmdumpGUI终极指南:深度解析网易云音乐NCM加密文件转换技术

ncmdumpGUI终极指南&#xff1a;深度解析网易云音乐NCM加密文件转换技术 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI ncmdumpGUI是一款专为Windows平台设计…...