verilog学习笔记- 14)静态数码管显示实验

news2024/11/27 8:44:25

目录

简介:

实验任务:

硬件设计:

程序设计:

下载验证:


简介:

数码管也称半导体数码管,它是将若干发光二极管按一定图形排列并封装在一起的一种数码显示器件。常见的数码管如图这种数码管主要被称为八段数码管或 8 字形数码管,可用来显示小数点、数字 0~9,和英文字母 A~F。

除了常用的八段数码管之外,较常见的还有“±1”数字管、“N”形管、“米”字管以及工业科研领域使用的 14 段管、16 段管、24 段管等。

 

 从该图可以看出,一位数码管的引脚是 10 个,其中 7 个引脚对应连接到组成数码管中间“8”字型的 led,Dp 引脚连接到数码管的小数点显示 led(dp)。最后还有两个公共端,生产商为了封装统一,单个数码管都封装成 10 个引脚,其中 8 和 3 两个公共端引脚(图中为 com)是连接在一起的。公共端又可分为共阳极和共阴极

对共阴极数码管来说,其 8 个发光二极管的阴极在数码管内部全部连接在一起,所以称“共阴”,而阳极独立。对共阳极数码管来说,其 8 个发光二极管的阳极在数码管内部全部连接在一起,所以称“共阳”,而阴极独立。以共阳极数码管为例,当我们想让数码管显示数字“8”,可以给 a、b、c„g 七个引脚送低电平,数码管就显示“8”,显示数字“1”,就给 b、c 引脚低电平,其余引脚(除公共端)给高电平,数码管就显示“1”。

当多位数码管应用于某一系统时,为了减少数码管占用的 I/O 口,将其段选(数码管的 a、b、c 等引脚)连接在一起,而位选(数码管的公共端)独立控制。这样我们可以通过位选信号控制哪几个数码管亮,而且在同一时刻,位选选通的所有数码管上显示的数字始终都是一样的,因为它们的段选是连接在一起的,所以送入所有数码管的段选信号都是相同的,数码管的这种显示方法叫做静态显示。


实验任务:

使用 FPGA 开发板上的 6 位数码管以静态方式依次显示 000000、111111、222222 至FFFFFF,结束后继续从 000000 开始计数,每 0.5s 变化一次。


硬件设计:

为了增加 FPGA 输出信号的驱动能力,我们使用 PNP 型三极管驱动数码管的位选段,所以给三极管基极提供低电平时,位选信号为高电平。

各端口信号的管脚分配如下表所示:

 

 对应的 TCL 约束语句如下:

set_location_assignment PIN_M2 -to sys_clk
set_location_assignment PIN_M1 -to sys_rst_n
set_location_assignment PIN_N16 -to sel[0]
set_location_assignment PIN_N15 -to sel[1]
set_location_assignment PIN_P16 -to sel[2]
set_location_assignment PIN_P15 -to sel[3]
set_location_assignment PIN_R16 -to sel[4]
set_location_assignment PIN_T15 -to sel[5]
set_location_assignment PIN_M11 -to seg_led[0]
set_location_assignment PIN_N12 -to seg_led[1]
set_location_assignment PIN_C9 -to seg_led[2]
set_location_assignment PIN_N13 -to seg_led[3]
set_location_assignment PIN_M10 -to seg_led[4]
set_location_assignment PIN_N11 -to seg_led[5]
set_location_assignment PIN_P11 -to seg_led[6]
set_location_assignment PIN_D9 -to seg_led[7]

程序设计:

系统的控制流程:首先我们需要一个静态数码管显示模块在数码管上显示数据,其次需要一个计时模块每当计时到 0.5s 时改变数码管显示的数值。由此画出系统的功能框图如下所示:

 程序中各模块端口及信号连接如图:

 FPGA 顶层(seg_led_static_top)例化了以下两个模块:计时模块(time_count)和数码管静态显示模块(seg_led_static),实现各模块之间数据的交互。计时模块将计时到 0.5s 时的标志信号 flag 传递给数码管静态显示模块,数码管静态显示模块接收到此信号时显示的数值增加 1。

计时模块(time_count):计时模块对系统时钟进行计数,当计时到给定值(此处指 0.5s)时输出标志信号。

数码管静态显示模块(seg_led_static):数码管静态显示模块在数码管上以静态方式显示数值。

顶层模块的代码如下:

1 module seg_led_static_top (
2 input sys_clk , // 系统时钟
3 input sys_rst_n, // 系统复位信号(低有效)
4 
5 output [5:0] sel , // 数码管位选
6 output [7:0] seg_led // 数码管段选
7 
8 );
9 
10 //parameter define
11 parameter TIME_SHOW = 25'd25000_000; // 数码管变化的时间间隔 0.5s
12 
13 //wire define
14 wire add_flag; // 数码管变化的通知信号
15 
16 //*****************************************************
17 //** main code
18 //*****************************************************
19 
20 //每隔 0.5s 产生一个时钟周期的脉冲信号
21 time_count #(
22 .MAX_NUM (TIME_SHOW)
23 ) u_time_count(
24 .clk (sys_clk ),
25 .rst_n (sys_rst_n),
26 
27 .flag (add_flag )
28 );
29 
30 //每当脉冲信号到达时,使数码管显示的数值加 1
31 seg_led_static u_seg_led_static (
32 .clk (sys_clk ),
33 .rst_n (sys_rst_n),
34 
35 .add_flag (add_flag ),
36 .sel (sel ),
37 .seg_led (seg_led )
38 );
39 
40 endmodule

顶层模块主要完成对其余模块的例化。代码第 11 行的参数 TIME_SHOW 控制数码管每隔多长时间改变显示的数值,该参数值与代码第32行的clk时钟信号频率有关。由于例化时clk为系统时钟sys_clk(50MHz)所以每隔 0.5 秒改变数码管显示的数值时此参数值为0.5 × 50000000 = 25000000,此功能由计时模块(time_count)实现。

计时模块的代码如下所示:

1 module time_count(
2 input clk , // 时钟信号
3 input rst_n , // 复位信号
4 
5 output reg flag // 一个时钟周期的脉冲信号
6 );
7 
8 //parameter define
9 parameter MAX_NUM = 25000_000; // 计数器最大计数值
10 
11 //reg define
12 reg [24:0] cnt; // 时钟分频计数器
13 
14 //*****************************************************
15 //** main code
16 //*****************************************************
17 
18 //计数器对时钟计数,每计时到 0.5s,输出一个时钟周期的脉冲信号
19 always @ (posedge clk or negedge rst_n) begin
20 if (!rst_n) begin
21 flag <= 1'b0;
22 cnt <= 24'b0;
23 end
24 else if(cnt < MAX_NUM - 1'b1) begin
25 cnt <= cnt +1'b1;
26 flag <= 1'b0;
27 end
28 else begin
29 cnt <= 24'b0;
30 flag <= 1'b1;
31 end
32 end
33 
34 endmodule

代码中第 9 行的参数 MAX_NUM 为计数的最大计数值,由于是对时钟计数,相当于计时,第 19 行的always 语句块表示的是当计数器 cnt 计数值小于 MAX_NUM - 1'b1 时,标志(flag)为0,否则标志为1,并且计数器 cnt 清零。通过 SignalTapII 抓到的波形图如下图所示:

 数码管静态显示模块的代码如下:

1 module seg_led_static (
2 input clk , // 时钟信号
3 input rst_n , // 复位信号(低有效)
4 
5 input add_flag, // 数码管变化的通知信号
6 output reg [5:0] sel , // 数码管位选
7 output reg [7:0] seg_led // 数码管段选
8 );
9 
10 //reg define
11 reg [3:0] num; // 数码管显示的十六进制数
12 
13 //*****************************************************
14 //** main code
15 //*****************************************************
16 
17 //控制数码管位选信号(低电平有效),选中所有的数码管
18 always @ (posedge clk or negedge rst_n) begin
19 if (!rst_n)
20 sel <= 6'b111111;
21 else
22 sel <= 6'b000000;
23 end
24 
25 //每次通知信号到达时,数码管显示的十六进制数值加 1
26 always @ (posedge clk or negedge rst_n) begin
27 if (!rst_n)
28 num <= 4'h0;
29 else if(add_flag) begin
30 if (num < 4'hf)
31 num <= num + 1'b1;
32 else
33 num <= 4'h0;
34 end
35 else
36 num <= num;
37 end
38 
39 //根据数码管显示的数值,控制段选信号
40 always @ (posedge clk or negedge rst_n) begin
41 if (!rst_n)
42 seg_led <= 8'b0;
43 else begin
44 case (num)
45 4'h0 : seg_led <= 8'b1100_0000;
46 4'h1 : seg_led <= 8'b1111_1001;
47 4'h2 : seg_led <= 8'b1010_0100;
48 4'h3 : seg_led <= 8'b1011_0000;
49 4'h4 : seg_led <= 8'b1001_1001;
50 4'h5 : seg_led <= 8'b1001_0010;
51 4'h6 : seg_led <= 8'b1000_0010;
52 4'h7 : seg_led <= 8'b1111_1000;
53 4'h8 : seg_led <= 8'b1000_0000;
54 4'h9 : seg_led <= 8'b1001_0000;
55 4'ha : seg_led <= 8'b1000_1000;
56 4'hb : seg_led <= 8'b1000_0011;
57 4'hc : seg_led <= 8'b1100_0110;
58 4'hd : seg_led <= 8'b1010_0001;
59 4'he : seg_led <= 8'b1000_0110;
60 4'hf : seg_led <= 8'b1000_1110;
61 default : seg_led <= 8'b1100_0000;
62 endcase
63 end
64 end
65 
66 endmodule

代码第 11 行的 num 信号为数码管显示的数值,由代码第 30 行的 if 语句块可知,其能显示的数值为0~f。由于开发板上的数码管为共阳数码管,所以不显示小数点时该位值为―1‖,因而 seg_led 信号的最高位为―1‖。下图为该模块运行时 SignalTapII 抓取到的波形图:

由该波形图可知,当 add_flag 信号拉高时,数值信号 num 加 1,输出对应的段选数据由 F8h 变为 80h


下载验证:

功能正常 

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

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

相关文章

【Linux 基础】

【Linux 基础】 一、 Linux 概述 1. Linux 介绍 UNIX 是一个强大的多用户、多任务操作系统&#xff0c;于1969年在贝尔实验室开发&#xff0c;UNIX 的商标权有国际开放组织&#xff08;The Open Group&#xff09;所拥有&#xff0c;UNIX 操作系统是商业版&#xff0c;需要收…

【OpenGL学习】Shader和Shader类的抽象

Shader 本节学习OpenGL中Shader的使用并将其抽象为类&#xff0c;简要介绍OpenGL所使用的着色器语言GLSL。 一、什么是Shader&#xff1f; 参考维基百科中对Shader的定义&#xff1a;着色器 - 维基百科&#xff0c;自由的百科全书 (wikipedia.org) 计算机图形学领域中&…

SpringBoot处理跨域总结

解决跨域的五种方法1、CorsFilter新建一个类Configuration public class CorsConfig {Beanpublic CorsFilter corsFilter() {//1. 添加 CORS配置信息CorsConfiguration config new CorsConfiguration();//放行哪些原始域//springboot版本为2.4.0以前写法config.addAllowedOrig…

kaggle竞赛 | Instant Gratification

kaggle比赛链接&#xff1a; https://www.kaggle.com/competitions/instant-gratification/data 目录普通方案优胜方案1. 用方差筛选特征2.QDA二次判别分析3.数据分组&#xff08;伪标签&#xff09;4.查看结果赛题总结普通方案 # 数据集路径 INPUT_PATH ../input/import num…

python学习笔记---进程和线程【廖雪峰】

进程和线程 现在&#xff0c;多核CPU已经非常普及了&#xff0c;但是&#xff0c;即使过去的单核CPU&#xff0c;也可以执行多任务。由于CPU执行代码都是顺序执行的&#xff0c;那么&#xff0c;单核CPU是怎么执行多任务的呢&#xff1f; 答案就是操作系统轮流让各个任务交替…

ESP-IDF:企业链表例程,实现初始化,插入,打印等功能。

例程&#xff1a; 简单地写一下企业链表&#xff0c;实现初始化&#xff0c;插入&#xff0c;打印等功能。 /企业链表/ typedef struct LINKNODE09 { // 定义节点 LINKNODE09 *next; } linknode09; // 定义表头 typedef struct LINKLIST09 { // 定义表头 linknode09 head; in…

【胖虎的逆向之路】03——Android一代壳脱壳办法罗列实操

【胖虎的逆向之路】03——Android脱壳办法罗列&脱壳原理详解 【胖虎的逆向之路】01——动态加载和类加载机制详解 【胖虎的逆向之路】02——Android整体加壳原理详解&实现 文章目录【胖虎的逆向之路】03——Android脱壳办法罗列&脱壳原理详解前言一、主流脱壳方法…

uefi和legacy的区别对比

legacy&#xff1a;[ˈleɡəsi]&#xff0c;遗产、遗留。 uefi&#xff1a;Unified Extensible Firmware Interface&#xff0c;统一可扩展固件接口。 当我们自己重装或安装操作系统的时候&#xff0c;可能会遇到硬盘的uefi和legacy两种&#xff0c;不过大多数人并不知道uefi和…

低代码开发前景如何?大家都真的看好低代码开发吗?

栖低代码开发前景如何&#xff0c;大家都真的看好低代码开发吗&#xff1f;之前有些过很多关于低代码的内容&#xff0c;这篇就来梳理下国内外低代码开发平台发展现状及前景。 关于低代码解读看这篇>> 什么是低代码&#xff08;Low-Code&#xff09;&#xff1f; 关于低…

SpreadJS.Release.16.0.2 Crack by Xacker

SpreadJS拥有 500 多个 Excel 函数的世界销量第一的 JavaScript 电子表格 快速提供真正类似 Excel 的电子表格体验 - 对 Excel 零依赖。创建财务应用程序&#xff0c;仪表板,图表,数据透视表,性能基准,科学实验室笔记本&#xff0c;以及其他类似的 JavaScript 电子表格应用程序…

77. 语言模型以及代码实现

1. 语言模型 给定文本序列 x1,…,xT,语言模型的目标是估计联合概率p&#xff08;x1,…,xT&#xff09;它的应用包括 做预训练模型&#xff08;eg BERT&#xff0c;GPT-3&#xff09;生成文本&#xff0c;给定前面几个词&#xff0c;不断使用xt~p(x1,…,xt-1) 来生成后续文本判…

CSS选择器整理学习(上)

在前端项目开发中&#xff0c;有时候需要对特殊的元素进行特殊的处理&#xff0c;但有时候元素的位置不确定、层级不确定、数量不确定等问题&#xff0c;导致我们没办法进行元素的选择&#xff0c;这个时候我们就需要用到元素选择器了。 一、CSS选择器 1、.class 选择器例子…

图像处理解决流程--外观检测

一、图像外观检测和面积计算 1、获取标准图像&#xff0c;提取要测定的区域&#xff08;截取成多个ROI&#xff09; 2、将目标图像的位置进行平移和旋转&#xff08;将目标图像和标准图像进行重叠&#xff09; 3、根据标准图像的区域进行以此计算目标图像的信息 4、判断统计 二…

Ajax基础

Ajax 是 Asynchronous JavaScript and XML&#xff08;异步 JavaScript 和 XML&#xff09;的简写 Ajax 中的异步&#xff1a;可以异步地向服务器发送请求&#xff0c;在等待响应的过程中&#xff0c;不会阻塞当前页面&#xff0c;浏览器可以做自己的事情。直到成功获取响应后…

Maven高级进阶

文章目录1&#xff0c;分模块开发1.1 分模块开发设计1.2 分模块开发实现1.2.1 环境准备1.2.2 抽取domain层步骤1:创建新模块步骤2:项目中创建domain包步骤3:删除原项目中的domain包步骤4:建立依赖关系步骤5:编译maven_02_ssm项目步骤6:将项目安装本地仓库1.2.3 抽取Dao层步骤1:…

iOS vue devtools工具的手把手安装,及Vue.js not detected的解决

使用vue插件Vue.js devtools 一.通过谷歌商店直接下载&#xff08;要翻墙&#xff09; 二.不翻墙的方法&#xff1a; 1.官网下载 git地址&#xff1a;https://github.com/vuejs/devtools git clone https://github.com/vuejs/devtools2.完成后命令行里切到该目录下&#x…

AppScan绕过登录验证码深入扫描

系列文章 AppScan介绍和安装 AppScan 扫描web应用程序 AppScan被动手动探索扫描 第四节-绕过登录验证码深入扫描 我们工作中最长碰到的工作场景是网站采用https协议&#xff0c;这时我们要用appScan进行扫描时&#xff0c;就需要先安装证书 1.证书安装 1.新建一个文件&…

渗透测试— —扫描与爆破账号

渗透测试— —扫描与爆破靶机账号 1 扫描与爆破账号流程 注意&#xff1a;仅用于教学与实验&#xff0c;不能用于攻击&#xff0c;否则后果自负 扫描&#xff1a;主机探测与端口扫描。&#xff08;主机探测&#xff1a;目标主机是存活&#xff0c;端口扫描&#xff1a;在线主…

总结 62 种在深度学习中的数据增强方式

数据增强 数据增强通常是依赖从现有数据生成新的数据样本来人为地增加数据量的过程 这包括对数据进行不同方向的扰动处理 或使用深度学习模型在原始数据的潜在空间(latent space)中生成新数据点从而人为的扩充新的数据集 这里我们需要区分两个概念&#xff0c;即增强数据和…

SpringBoot的filter过滤器

SpringBoot的filter过滤器 目录SpringBoot的filter过滤器一、过滤器的作用和概述1.1 简述1.2 使用场景二、自定义过滤的两种方式2.1 第一种方式2.1.1 启动类增加注解ServletComponentScan2.1.2 定义一个filter类2.1.3. 测试2.2 第二种方式2.2.1 自定义fitler类2.2.4 在启动类中…