数码管电子时钟

2023-11-19


前言

一、回顾数码管

  Cyclone IV开发板上的数码管一共有6个,我们每次只能选择其中一个显示,怎么解决电子时钟时、分、秒同时显示呢?要实现电子时钟首先要了解什么是余晖效应。
  余晖效应一般指视觉暂留。 视觉暂留现象即视觉暂停现象(Persistence of vision,Visual staying phenomenon,duration of vision)又称“余晖效应”。只要数码管位选信号切换得足够快,数码管由亮到灭这一过程是需要一段时间的,由于时间很短,我们的眼睛是没有办法分清此时此刻数码管的状态,给人的感觉就是数码管是一直亮的。以此来达到欺骗人眼的效果,这样就可以实现同时显示时、分、秒。

在这里插入图片描述

图1. 数码管动态显示

二、任务描述

  使用数码管设计电子时钟,计数器部分有3种实现方法:

  1. 采用1个计数器,模为24x60x60;
  2. 采用3个计数器,模分别为24、60、60;
  3. 采用6个计数器分别计数时、分、秒的个位、十位;
  • 方法1:计数器个数少,设计简单,但是后面数码管译码时,需要对计数值取余、取整,分离出时、分、秒的个位和十位,比较耗费组合逻辑资源;
  • 方法2:3个计数器,后面数码管译码时,需要对时、分、秒计数值取余、取整,分离出时、分、秒的个位和十位,比较耗费组合逻辑资源;
  • 方法3:6个计数器,相对复杂一点,但是计数值直接就是时、分、秒的个位和十位值,不需要除法器进行取余、取整操作,使用的触发器资源略多,但节省组合逻辑资源。
      本实验使用方法1,其他方法同学们可以自行尝试。

在这里插入图片描述

图2. 电子时钟

  我们最后实现的效果如图2所示,由于开发板上的数码管没有冒号(:),所以我们直接忽略冒号。


三、系统框图

  • 计数器模块:产生时、分、秒计数值;
  • 数码管驱动模块:对时、分、秒计数值进行译码,产生驱动数码管动态显示数字的位选信号和段选信号。

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

图3. 系统框图

四、模块调用

在这里插入图片描述

图4. 模块关系示意图

五、模块原理图

在这里插入图片描述

图5. 模块原理图

六、工程源码

6.2 时钟计数模块代码

module counter(
	input wire 		  clk  ,//时钟
	input wire 		  rst_n,//复位信号
	
	output reg [4:0] hour  ,//小时
	output reg [5:0] min   ,//分钟
	output reg [5:0] sec//秒
	
);

parameter MAX_NUM = 26'd49_999_999;//1s
parameter TOTAL_SEC = 17'd86399   ;//24x60x60s
reg [25:0] cnt_sec ;//秒计数器
reg [16:0] cnt_time;//计时器

//计时1s秒钟模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_sec <= 26'd0;
	end 
	else if(cnt_sec == MAX_NUM)begin
		cnt_sec <= 26'd0;
	end 
	else begin
		cnt_sec <= cnt_sec + 1'd1;
	end 
end 

//时间模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_time <= 17'd0;
	end 
	else if(cnt_time == TOTAL_SEC && cnt_sec == MAX_NUM)begin
		cnt_time <= 17'd0;
	end 
	else if(cnt_sec == MAX_NUM)begin
		cnt_time <= cnt_time + 1'd1;
	end 
	else begin
		cnt_time <= cnt_time;
	end 
end 

//取出时分秒模块
always@(*)begin
	hour = cnt_time / 12'd3600          ;//小时
	min  = (cnt_time % 12'd3600) / 6'd60;//分钟
	sec  = (cnt_time % 12'd3600) % 6'd60;//秒
end 
endmodule 

6.2 数码管驱动模块代码

module seg_driver(
	input wire 			clk	 ,//时钟
	input wire 			rst_n,//复位信号
	input wire [4:0] 	hour ,//小时
	input wire [5:0] 	min	 ,//分钟
	input wire [5:0] 	sec	 ,//秒
	
	output reg [5:0]	seg_sel,
	output reg [7:0] 	seg_ment
);

parameter CNT_20US = 10'd999;//20微秒
wire [3:0] 	sec_low  ;//秒的低位
wire [2:0] 	sec_high ;//秒的高位
wire [3:0] 	min_low  ;//分钟的低位
wire [2:0] 	min_high ;//分钟的高位
wire [1:0] 	hour_low ;//小时的低位
wire [1:0] 	hour_high;//小时的高位
reg  [9:0]	cnt		 ;//计数器,计20us时间
reg  [3:0] 	number	 ;//显示时分秒寄存器

//计时模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 10'd0; 	
	end 
	else if(cnt == CNT_20US)begin
		cnt <= 10'd0;
	end 
	else begin
		cnt <= cnt + 1'd1;
	end 
end 

//位选信号切换模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		seg_sel <= 6'b011111;//初始化第一个数码管亮
	end 
	else if(cnt == CNT_20US)begin
		seg_sel <= {seg_sel[0],seg_sel[5:1]};//每隔20us进行位移操作
	end 
	else begin
		seg_sel <= seg_sel;//其他时间保持不变
	end 
end 

//位选信号译码模块
always@(*)begin
	case(seg_sel)
		6'b011111: number = sec_low  ;//秒的低位给第一个数码管显示
		6'b101111: number = sec_high ;//秒的高位给第二个数码管显示
		6'b110111: number = min_low  ;//分钟的低位给第三个数码管显示
		6'b111011: number = min_high ;//分钟的高位给第四个数码管显示
		6'b111101: number = hour_low ;//小时的低位给第五个数码管显示
		6'b111110: number = hour_high;//小时的高位给第六个数码管显示
		default:   number = sec_low  ;
	endcase 
end 

//段选信号译码模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		seg_ment <= 8'b1100_0000;//初始化显示0
	end
	else begin
		case(number)
			4'd0:		seg_ment <= 8'b1100_0000;//数码管显示0
			4'd1:		seg_ment <= 8'b1111_1001;//数码管显示1
			4'd2: 		seg_ment <= 8'b1010_0100;//数码管显示2
			4'd3: 		seg_ment <= 8'b1011_0000;//数码管显示3
			4'd4: 		seg_ment <= 8'b1001_1001;//数码管显示4
			4'd5: 		seg_ment <= 8'b1001_0010;//数码管显示5
			4'd6: 		seg_ment <= 8'b1000_0010;//数码管显示6
			4'd7: 		seg_ment <= 8'b1111_1000;//数码管显示7
			4'd8: 		seg_ment <= 8'b1000_0000;//数码管显示8
			4'd9:    	seg_ment <= 8'b1001_0000;//数码管显示9
			default:	seg_ment <= 8'b1100_0000;//数码管显示0
		endcase 
	end 
end 

assign sec_low   = sec % 4'd10 ;//秒的低位如59秒--->9
assign sec_high  = sec / 4'd10 ;//秒的高位如59秒--->5
assign min_low   = min % 4'd10 ;//分钟的低位如59--->9
assign min_high  = min / 4'd10 ;//分钟的高位如59--->5
assign hour_low  = hour % 4'd10;//小时的低位如23--->3
assign hour_high = hour / 4'd10;//小时的高位如23--->2
endmodule 

6.3 顶层模块代码

module digital_clock(
	input wire 			clk  ,//时钟
	input wire 			rst_n,//复位信号
	
	output wire [5:0] seg_sel,//数码管位选信号
	output wire [7:0] seg_ment//数码管段选信号

);
parameter MAX_NUM = 26'd49_999_999;//1s
parameter TOTAL_SEC = 17'd86399   ;//60x24x24s
parameter CNT_20US = 10'd999     ;//20us
wire [4:0] 	hour;//小时
wire [5:0] 	min ;//分钟
wire [5:0] 	sec ;//秒	

//实例化计数器模块
counter#(.MAX_NUM(MAX_NUM),
		.TOTAL_SEC(TOTAL_SEC)) u_counter(
.clk  	(clk)  ,
.rst_n	(rst_n),
          
.hour 	(hour) ,
.min	(min)  ,
.sec	(sec)
	
);

//实例化数码管驱动模块
seg_driver#(.CNT_20US(CNT_20US)) u_seg_driver(
.clk	 	(clk)    ,
.rst_n		(rst_n)  ,
.hour	 	(hour)   ,
.min	 	(min)    ,
.sec	 	(sec)    ,
          
.seg_sel	(seg_sel),
.seg_ment	(seg_ment)
);

endmodule 

七、仿真测试

7.1 测试代码

`timescale 1ns/1ns
module digital_clock_tb();

parameter MAX_NUM   = 26'd5  ;//100ns
parameter TOTAL_SEC = 17'd100;//100x5x100ns
parameter CNT_20US  = 11'd1  ;//20ns,位选信号切换间隔
parameter CYCLE     = 20     ;//20ns,模拟时钟
reg clk  ;//时钟寄存器
reg rst_n;//复位寄存器

wire [5:0] seg_sel ;//位选信号
wire [7:0] seg_ment;//段选信号

always#(CYCLE/2) clk = ~clk;//模拟时钟信号
//初始化
initial begin
	clk   = 1'b0				  ;//时钟初始化为0
	rst_n = 1'b0				  ;//复位信号初始化为0
	#(CYCLE)    				  ;//延迟一个周期
	rst_n = 1'b1				  ;//复位信号置1
	#(MAX_NUM * TOTAL_SEC * CYCLE);//延迟一段时间
	$stop						  ;//停止
end 

//实例化数字时钟顶层模块
digital_clock#(.MAX_NUM(MAX_NUM)    ,
			   .TOTAL_SEC(TOTAL_SEC),
			   .CNT_20US(CNT_20US))	
u_digital_clock(
.clk    	(clk)    ,//时钟
.rst_n  	(rst_n)  ,//复位信号
		    		
.seg_sel	(seg_sel),//数码管位选信号
.seg_ment(seg_ment)//数码管段选信号

);
endmodule 

7.2 仿真结果

在这里插入图片描述

图6. 仿真结果

八、管脚信息

元件 管脚
SEL0 A4
SEL1 B4
SEL2 A3
SEL3 B3
SEL4 A2
SEL5 B1
DIG0 B7
DIG1 A8
DIG2 A6
DIG3 B5
DIG4 B6
DIG5 A7
DIG6 B8
DIG7 A5
CLOCK(时钟) E1
KEY1 E15
表1. 管脚信息表

九、运行效果

数码管电子时钟


总结

  电子时钟是在数码管动态显示实验基础上开发的项目,只要你熟悉数码管动态显示项目流程,在开发电子时钟的时候也会游刃有余。以上就是数码管电子时钟的全部内容,后期将推出什么是ip课程。敬请期待,谢谢你的观看!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数码管电子时钟 的相关文章

随机推荐

  • C++之模板实例化

    模板可以分为类模板与函数模板 它们的声明形式分别为 template
  • Docker下使用jstat查看jvm的GC信息

    Jstat指令 jstat命令命令格式 jstat Options vmid interval count 参数说明 Options 选项 我们一般使用 gcutil 查看gc情况 vmid VM的进程号 即当前运行的java进程号 int
  • read和write函数

    read ssize t read int fd void buf size t count fd 文件描述符 通过open获得 buf 需要读取的数据的存放位置 数组的地址 count 指定数组的大小 返回值 成功 gt 0 返回实际读取
  • 深入理解 Flutter 图片加载原理

    前言 随着Flutter稳定版本逐步迭代更新 京东APP内部的Flutter业务也日益增多 Flutter开发为我们提供了高效的开发环境 优秀的跨平台适配 丰富的功能组件及动画 接近原生的交互体验 但随之也带来了一些OOM问题 通过线上监控
  • 如何用视频制作gif动图?4种制作教学方法

    GIF动图以循环播放的形式呈现 相比于完整的视频内容 它可以将重要的瞬间或关键帧提取出来 从而简化和精简内容 所以说 动图比我们原本的视频文件呈现的内容更为活泼 生动 通过视频制作GIF动图 我们还可以运用编辑工具对视频中的场景进行裁剪 缩
  • 使用Python绘制粽子消消乐,素描图(优化版,正常/漫画/写实风格),词云图,字符画图及提取轮廓

    使用Python绘制粽子消消乐 素描图 优化版 正常 漫画 写实风格 词云图 字符画图及提取轮廓 1 效果图 2 源码 2 1 素描图源码 2 2 优化版 制作不同风格的素描图 正常 漫画 写实风格 https blog csdn net
  • 关于制作rpm包的patch的方法

    原文链接 http blkart blog 51cto com 1142352 1542533 1 准备工作 安装rpm build软件包 2 生成rpmbuild目录 以root用户登陆 执行命令 rpmbuild ba abc spec
  • 详解接口加密了怎么测?

    1 定义加密需求 确定哪些数据需要进行加密 这可以是用户敏感信息 密码 身份验证令牌等 确定使用的加密算法 如对称加密 如AES 或非对称加密 如RSA 2 生成密钥 对称加密 生成一个密钥 确保密钥的安全性和随机性 可以使用密钥生成库或算
  • Vue自定义InputNumber 计数器组件

    1 为什么要自己封装一个InputNumber 计数器组件 因为原始的el element的el input number组件有问题 原生组件能输入英文 不能限制只能输入数值 原始组件能通过键盘上的删除按钮 将数据全部删除 若提交表单的话
  • Vue3.0的新特性(8)Suspense

    Suspense是Vue3推出的一个内置组件 它允许我们的程序在等待异步组件时渲染一些后备的内容 可以让我们创建一个平滑的用户体验 Vue中加载异步组件其实在Vue2 x中已经有了 我们用的vue router中加载的路由组件其实也是一个异
  • 风口之上,为什么说区块链能改变世界?

    近几年 区块链被炒得热火朝天 各大媒体都能看见区块链的身影 其中很多甚至开设了区块链或比特币频道 你甚至很难找到一个科技或垂直网站 在标题中没有至少一篇意为 区块链改变世界 的文章 它们想传达的是 比特币和其他加密货币底层的区块链技术是如何
  • Idea 报Error:java:无效的源发行版13

    首先打开自己的项目 点击File gt Settings进入界面找到如图位置 并将相信应位置设置成自己的安装版本号 本人使用 1 8版本 别忘了点击OK 下一步 点击File选择Project Structure 进入 还是看自己的安装版本
  • java如何查询并显示一个表,如何从表中获取数据并将其显示在Java的另一个表中?...

    将数据从一个表复制到另一个表的Netbean项目 希望这可以帮助 import javax swing table DefaultTableModel To change this license header choose License
  • 概率论【离散型二维变量与连续性二维变量(下)】--猴博士爱讲课

    6 连续型二维变量 下 1 7 求边缘分布函数 边缘概率密度 边缘概率密度 2 7 求边缘密度函数 边缘概率密度 3 7 判断连续型二维变量的独立性 F x y Fx X Fy Y 那么X Y互相独立 f x y fx X fy Y 那么X
  • 【论文阅读 08】Adaptive Anomaly Detection within Near-regular Milling Textures

    2013年 太老了 先不看 比较老的一篇论文 近规则铣削纹理中的自适应异常检测 1 Abstract 在钢质量控制中的应用 我们提出了图像处理算法 用于无监督地检测隐藏在全局铣削模式内的异常 因此 我们考虑了基于全局傅里叶的方法和局部剪切波
  • php判断2个多维数组是否相同,PHP如何判断一个数组是一维还是多维

    什么叫多维数组呢 多维数组 本质上是以数组作为数组元素的数组 二维数组又称为矩阵 一个数组的元素如果是一维数组 那么我们就称这个数组是二维数组 怎么判断一个数组是否是一维数组呢 通过count 函数 int count mixed var
  • 【FPGA】:频率测量

    转载 1 FPGA频率测量的三种方法 直接测量法 间接测量法 等精度测量法
  • Go中sync 包的 Once 使用

    文章目录 背景 One 简介 示例 注意 源码解读 背景 在系统初始化的时候 某些代码只想被执行一次 这时应该怎么做呢 没有学习 Once 前 大家可能想到 声明一个标识 表示是否初始化过 然后初始化这个标识加锁 更新这个标识 但是学会了
  • .net IOC之Spring.Net

    一 开发环境 编译器 VS2013 Net版本 net framework4 5 二 涉及程序集 Spring Core dll 1 3 Common Logging 三 开发过程 1 项目结构 2 添加Person cs namespac
  • 数码管电子时钟

    文章目录 前言 一 回顾数码管 二 任务描述 三 系统框图 四 模块调用 五 模块原理图 六 工程源码 6 2 时钟计数模块代码 6 2 数码管驱动模块代码 6 3 顶层模块代码 七 仿真测试 7 1 测试代码 7 2 仿真结果 八 管脚信