FPGA学习(10)-数码管
前3节视频目的是实现显示0~F的数码管仿真,后3节是用驱动芯片驱动数码管。
目录
1.数码管显示原理
2.代码过程
2.1仿真结果
3.串行移位寄存器原理
3.1原理
编辑 3.2 数据手册
3.3 先行设计思路
4.程序
4.1确定SRCLK的频率
4.2序列计数器
4.3 不同counter值干不同事
4.4仿真
5.实验结果
1.数码管显示原理
分为共阳极与共阴极驱动,共阴极:发光二极管负极都接地,a~dp接入端口引脚,输出高电平就点亮,共阳极与之相反。
不同位的高低电平可以组成不同的数字符号,后面查找表的值就看这张图。
在驱动多个数码管场景中,往往a~dg与每个数码管对应的二极管是互联的,而sel端的电压可以控制三极管是否导通,以此可以单独让某个数码管亮灭。
根据以上分析可以画出电路图:
1.首先SEL决定了点亮哪个数码管,需要用到38译码器进行选择,而38译码器的输出选择需要用到一个3位的状态计数切换器。
2.如何让状态切换,即加入一个计数器记到1ms,当大于1ms时,让状态加1,且计数器本身清0。
3.SEG决定了数码管哪段亮,在没有规律的情况下可以用查表法,把这些状态一一列出来,例如这里有16个状态,那么需要一个4位的变量来表示对应的索引号。
4.将状态计数切换器值传到8选1数据选择器,分别代表8个数码管对应的通道值,作为索引。
2.代码过程
1.实现1ms的计数器;
2.位切换逻辑,计数器每满一次,状态位切换+1;
3.38译码器实现连接哪个数码管;
4.位选择控制逻辑。
(1)查找表case,完成SEG的配置。
(2)位切换逻辑将8个数码管对应的值当作索引传进去。这里数组顺序错了。
代码:
module Shuma_guan(input clk,input reset,input[31:0] Dis_data,output reg[7:0] SEL,output reg[7:0] SEG);
reg[29:0] counter_1ms;
reg[2:0] which_sel;
reg[3:0] data_temp; //存放索引值
//数码管亮的时间
parameter Base_freq = 50_000_000;
parameter goal_freq = 1000;
parameter cworth = Base_freq/goal_freq-1;//计数器
always@(posedge clk or negedge reset)
beginif(!reset)counter_1ms <= 1'd0;else if(counter_1ms == cworth)counter_1ms <= 1'd0;elsecounter_1ms <= counter_1ms+1'd1;
end//数码管状态切换
always@(posedge clk or negedge reset)
beginif(reset)which_sel <= 1'd0;else if(counter_1ms == cworth)which_sel <= which_sel+1'd1;elsewhich_sel <= which_sel;
end//38译码器确定哪个数码管亮
always@(posedge clk)
begincase(which_sel)0:SEL <= 8'b0000_0001;1:SEL <= 8'b0000_0010;2:SEL <= 8'b0000_0100;3:SEL <= 8'b0000_1000;4:SEL <= 8'b0001_0000;5:SEL <= 8'b0010_0000;6:SEL <= 8'b0100_0000;7:SEL <= 8'b1000_0000;endcase
end//建立查找表,共阳
always@(posedge clk)
begincase(data_temp)0:SEG <= 8'b1100_0000;1:SEG <= 8'b1111_1001;2:SEG <= 8'b1010_0100;3:SEG <= 8'b1011_0000;4:SEG <= 8'b1001_1001;5:SEG <= 8'b1001_0010;6:SEG <= 8'b1000_0010;7:SEG <= 8'b1111_1000;8:SEG <= 8'b1000_0000;9:SEG <= 8'b1001_0000;10:SEG <= 8'b1000_1000;11:SEG <= 8'b1000_0011;12:SEG <= 8'b1100_0110;13:SEG <= 8'b1010_0001;14:SEG <= 8'b1000_0110;15:SEG <= 8'b1000_1110;endcase
end//将状态值传给索引
always@(*)
begincase(which_sel)0:data_temp <= Dis_data[3:0];1:data_temp <= Dis_data[7:4];2:data_temp <= Dis_data[11:8];3:data_temp <= Dis_data[15:12];4:data_temp <= Dis_data[19:16];5:data_temp <= Dis_data[23:20];6:data_temp <= Dis_data[27:24];7:data_temp <= Dis_data[31:28];endcase
endendmodule
仿真:
`timescale 1ns / 1nsmodule Shuma_guan_tb();
reg clk;
reg reset;
reg[31:0] Dis_data;
wire[7:0] SEL;
wire[7:0] SEG;Shuma_guan Shuma_guan_inst0(.clk(clk),.reset(reset),.Dis_data(Dis_data),.SEL(SEL),.SEG(SEG)
); initial clk = 1;
always #10 clk=~clk;initial beginreset = 0;Dis_data = 32'h12345678;#201;reset = 1;#20_000_000;Dis_data = 32'h9abcdef0;#20_000_000;$stop;
end
endmodule
2.1仿真结果
切换状态计数没有随着计数器增加到49999而加1,原因是在切换状态的时序逻辑中,复位没有取反,直接if(reset),相当于复位信号为1时,状态计数就会为0,所以一直不会增加。
修改后正确:
3.串行移位寄存器原理
3.1原理
为了节省IO口引脚,一般会使用驱动芯片74HC595驱动数码管,芯片的原理是基于串行移位寄存器。将上节输出的SEG与SEL传输到74HC595。
基本原理为,顺次连接4个D触发器,每经过一个时钟,就依次将DATA存储的值传送到下一个D触发器,例如,经过5个时钟周期后, 此时DFF3~DFF0存储的值为:1001。如果想在这个时刻把每个D触发器存储的值取出来,就在每个D触发器的输出端再接入一个D触发器,加的这4个D触发器单独用一个时钟进行控制,然后将输出分别接至各自端口。
当要移位8位,16位时,直接加更多的D触发器就行。
74HC595能够驱动8位移位寄存器,SER是数据传输口,SRCLK是第一路串联触发器的时钟,SRCLR非应该是复位信号,RCLK是是每个单独加入的触发器的时钟,OE非是输出的使能信号。第1个74HC595的输出串联到了第2个74HC595的输入,以此构成16位移位寄存器输出。
左边的74HC连接的是选择使能哪个数码管,右边的74HC是决定数码管哪段亮。DIO是数据输入,SRCLK是第一路串联触发器的时钟,RCLK是加入单个D触发器的时钟。
3.2 数据手册
从时序图可以看出,RCLK有方波时,才有输出。
移位寄存器时钟为上升沿时,其实也就是让移位寄存器存前一阶段的数据。RCLK为上升沿时,移位寄存器的数据存储在存储寄存器中。
时钟频率最低为5MHz,其中,SRCLK/RCLK的高低电平时间至少为时钟周期的一半,电平为2V时,SER在SRCLK上升沿前125ns必须稳定,SRCLK的上升沿必须RCLK上升沿之前的94ns。
3.3 先行设计思路
4.程序
4.1确定SRCLK的频率
取50MHz的乘除整数倍,取SRCLK的频率为12.5MHz,定义一个分频计数器,在SRCLK下降沿将数据传到DIO,上升沿DIO将数据传给驱动芯片的寄存器。计数器计数两次为1个SRCLK周期,可根据counter找到SRCLK的上升沿和下降沿。
4.2序列计数器
根据时序图与原理图,先传的SEG,后传的SEL。1ms切换了一次,人眼看不出来,实际上应该是闪烁的数字循环跳变。共32个状态,需要拉低拉高。
4.3 不同counter值干不同事
counter=0,拉低SRCLK,将SEG[7]的值传给DIO,将RCLK拉高。
counter=1,拉高SRCLK(驱动芯片自动会将DIO的数据传给寄存器),RCLK拉低。
......
counter=31,拉高SRCLK
4.4仿真
仿真的RCLK刚开始就拉高了,这是因为if后面没有跟else,直接按照每个时钟沿开始执行程序了。
正确的仿真波形:
此时代码:
module tube_active(input clk,input reset,input[7:0] SEL,input[7:0] SEG,output reg SRCLK,output reg RCLK,output reg DIO);reg[29:0] divi_counter;
reg[4:0] state_counter; //序列计数器
//确定SRCLK的频率为12.5MHz
parameter base_frequence = 50_000_000;
parameter goal_frequence = 12500_000;
parameter goal_counter = base_frequence/(goal_frequence*2)-1;//分频计数器
always@(posedge clk or negedge reset)
beginif(!reset)divi_counter <= 1'd0;else if(divi_counter == goal_counter)divi_counter <= 1'd0;elsedivi_counter <= divi_counter +1'd1;
end//序列计数器
always@(posedge clk or negedge reset)
beginif(!reset)state_counter <= 1'd0;else if(divi_counter == goal_counter)state_counter <= state_counter+1'd1;elsestate_counter <= state_counter;
end//不同counter值做不同事,下降沿将值传给DIO,上升沿将DIO的值送给驱动芯片
always@(posedge clk or negedge reset)
beginif(!reset)beginSRCLK <= 1'd0;RCLK <= 1'd0;DIO <= 1'd0;endelse begincase(state_counter)0:begin DIO <= SEG[7]; SRCLK <= 1'd0; RCLK <= 1'd1; end1:begin SRCLK <= 1'd1; RCLK <= 1'd0; end2:begin DIO <= SEG[6]; SRCLK <= 1'd0;end3:begin SRCLK <= 1'd1; end4:begin DIO <= SEG[5]; SRCLK <= 1'd0;end 5:begin SRCLK <= 1'd1; end6:begin DIO <= SEG[4]; SRCLK <= 1'd0;end7:begin SRCLK <= 1'd1; end8:begin DIO <= SEG[3]; SRCLK <= 1'd0;end 9:begin SRCLK <= 1'd1; end10:begin DIO <= SEG[2]; SRCLK <= 1'd0;end11:begin SRCLK <= 1'd1; end12:begin DIO <= SEG[1]; SRCLK <= 1'd0;end13:begin SRCLK <= 1'd1; end14:begin DIO <= SEG[0]; SRCLK <= 1'd0;end15:begin SRCLK <= 1'd1; end16:begin DIO <= SEL[7]; SRCLK <= 1'd0;end17:begin SRCLK <= 1'd1; end18:begin DIO <= SEL[6]; SRCLK <= 1'd0;end19:begin SRCLK <= 1'd1; end20:begin DIO <= SEL[5]; SRCLK <= 1'd0;end 21:begin SRCLK <= 1'd1; end22:begin DIO <= SEL[4]; SRCLK <= 1'd0;end23:begin SRCLK <= 1'd1; end24:begin DIO <= SEL[3]; SRCLK <= 1'd0;end 25:begin SRCLK <= 1'd1; end26:begin DIO <= SEL[2]; SRCLK <= 1'd0;end27:begin SRCLK <= 1'd1; end28:begin DIO <= SEL[1]; SRCLK <= 1'd0;end29:begin SRCLK <= 1'd1; end30:begin DIO <= SEL[0]; SRCLK <= 1'd0;end31:begin SRCLK <= 1'd1; endendcaseend
end
endmodule
仿真代码:
`timescale 1ns / 1nsmodule tube_active_tb();reg clk;reg reset;reg [7:0]SEL;reg [7:0]SEG;wire SRCLK;wire RCLK;wire DIO;tube_active tube_active_inst0(.clk(clk), .reset(reset), .SEL(SEL),.SEG(SEG),.SRCLK(SRCLK),.RCLK(RCLK), .DIO(DIO)
);initial clk = 1;
always #10 clk = ~clk;initial beginreset = 0;SEL = 8'b0000_0001;SEG = 8'b0101_0101;#201;reset = 1;#5000;SEL = 8'b0000_0010;SEG = 8'b1010_1010; #5000;SEL = 8'b1010_0101;SEG = 8'b0000_1101; #5000;$stop;
end
endmodule
在现有模块添加新的源文件,必须点击这里的+,左上角的会出错。新源文件调用了上面的两个模块,让这两个模块连在一起,然后引出三根线与驱动芯片连接。
module tube_shuma_test(input clk,input reset,output SRCLK,output RCLK,output DIO,input [1:0] SW
);wire[7:0] SEL,SEG; //将两个例化的端口连接起来
reg[31:0] Dis_data; //调用的并转串模块
tube_active tube_active_inst0(.clk(clk), .reset(reset), .SEL(SEL),.SEG(SEG),.SRCLK(SRCLK),.RCLK(RCLK), .DIO(DIO)
);//调用的hex8模块
Shuma_guan Shuma_guan_inst0(.clk(clk),.reset(reset),.Dis_data(Dis_data),.SEL(SEL),.SEG(SEG)
); always@(*)
begincase(SW)0:Dis_data <= 32'h01234567;1:Dis_data <= 32'h89abcdef;2:Dis_data <= 32'haaaabbbb;3:Dis_data <= 32'h66666666;endcase
endendmodule
5.实验结果
根据拨码开关的开关情况,数码管显示不同的数字。
相关文章:

FPGA学习(10)-数码管
前3节视频目的是实现显示0~F的数码管仿真,后3节是用驱动芯片驱动数码管。 目录 1.数码管显示原理 2.代码过程 2.1仿真结果 3.串行移位寄存器原理 3.1原理 编辑 3.2 数据手册 3.3 先行设计思路 4.程序 4.1确定SRCLK的频率 4.2序列计数器 4.3 不同coun…...

C++(继承)
继承的语法 继承的好处:减少重复代码 语法: class 子类 : 继承方法 父类 子类 也称为 派生类 父类 也成为 基类 继承方式 公共继承 保护继承 私有继承 结论:父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后…...
华为OD机试 - RSA加密算法(Java 2024 E卷 100分)
long n (long) Math.sqrt(num); 与long n (long) Math.floor(Math.sqrt(num)); 这两行代码的目的都是计算 num 的平方根,并将结果转换为 long 类型的整数。然而,它们在处理方式上有一些微小的差别。 long n (long) Math.sqrt(num);long n (long) M…...

分组校验在Spring中的应用详解
目录 前言1. 什么是分组校验2. 分组校验的基本原理3. 分组校验的实现步骤3.1 定义分组接口3.2 在校验项中指定分组3.3 校验时指定要校验的分组3.4 默认分组和分组的继承 4. 分组校验的优势和适用场景4.1 优势4.2 适用场景 5. 常见问题与解决方案5.1 校验未生效5.2 无法识别默认…...
torch.nn.**和torch.nn.functional.**的区别
torch.nn.** torch.nn.**是一个继承了torch.nn.Module的类,使用前必须先构造对象,然后再调用。如果直接使用则会报错 例如 a torch.randn(3,4) print(a) sigmoid torch.nn.Sigmoid() a sigmoid(a) print(a) a torch.nn.Sigmoid(a)tensor([[ 0.2462…...

Air780E基于LuatOS编程开发
Air780E基于LuatOS编程开发 Air780E开发板下载固件版本开发板刷机开发调试源码编译下载源码编译工具编译工具链 Air780E开发板 合宙通信推出的 LTE Cat.1 bis通信模块,采用移芯EC618平台,支持4G全网通, 包括的模组有: Air780E – 4G Cat.1Air780EG – …...

贪心算法-汽车加油
这道题目描述了一个汽车旅行场景,需要设计一个有效的算法来决定在哪几个加油站停车加油,以便最小化加油次数。题目给出了汽车加满油后的行驶距离n公里,以及沿途若干个加油站的位置。我们需要找出一个方案,使得汽车能够完成整个旅程…...

Qt信号和槽-->day04
Qt信号和槽 标准的信号和槽函数Qt中的槽函数Qt中的信号 connect案例 自定义信号和槽案例分析 信号槽的拓展信号连接信号案例 信号槽的两种连接方式Qt5中的处理方式Qt4中的处理方式Qt5处理信号槽重载问题案例 lambda表达式简单案例Qt中的应用 补充知识点 标准的信号和槽函数 QW…...

【Linux】为终端命令自定义快件键并弹窗提醒 设置快捷键切换网络代理(Network Proxy)Disabled/Manual 并弹窗提醒
【Linux】为终端命令自定义快件键并弹窗提醒 设置快捷键切换网络代理(Network Proxy)Disabled/Manual 并弹窗提醒 可以自定义快捷键执行终端命令,执行完毕会有弹窗提醒。下面给一个例子,设置快捷键切换网络代理(Netwo…...
十六:Spring Boot依赖 (1)-- spring-boot-starter 依赖详解
1. 简介: spring-boot-starter 是 Spring Boot 项目中的基础启动器依赖,它为开发者提供了 Spring Boot 应用所需的核心功能和自动配置 spring-boot-starter 不是一个具体的功能模块,而是一个基础的启动器。 Spring Boot 提供了一系列的 sta…...

讲讲关于SNMP与智能PDU插座
什么是SNMP 简单网络管理协议 (SNMP) 是一种应用层协议,主要用于网络管理中的设备监控和控制。通过 SNMP,网络管理员可以从管理站远程访问网络中的设备,获取设备的状态信息、配置参数,甚至控制设备的行为。SNMP 被广泛应用于 TCP/…...
在CentOS下安装RabbitMQ
在CentOS下安装RabbitMQ 在CentOS下安装RabbitMQ可以按照以下步骤进行:步骤 1: 更新系统步骤 2: 安装Erlang步骤 3: 添加RabbitMQ仓库步骤 4: 安装RabbitMQ步骤 5: 启动RabbitMQ服务步骤 6: 检查RabbitMQ状态步骤 7: 启用RabbitMQ管理插件(可选ÿ…...

前端使用Canvas实现网页电子签名(兼容移动端和PC端)
实现效果: 要使用Canvas实现移动端网页电子签名,可以按照以下步骤: 在HTML文件中创建一个Canvas元素,并设置其宽度和高度,以适配移动设备的屏幕大小。 // 创建一个canvas元素 let canvas document.createElement(&q…...
什么是OSTRPT报文?
OSTRPT(Order Status Report)是一种 EDI(电子数据交换)报文,用于在供应链管理中向采购商报告订单状态。这种报文通常由供应商发送给采购商,目的是告知订单的当前处理状态、预期交货时间、订单中的变化等信息…...

PICO+Unity MR空间锚点
官方链接:空间锚点 | PICO 开发者平台 注意:该功能只能打包成APK在PICO 4 Ultra上真机运行,无法通过串流或PICO developer center在PC上运行。使用之前要开启视频透视。 在 Inspector 窗口中的 PXR_Manager (Script) 面板上,勾选…...
electron 中 contextBridge 作用
1. 安全地实现渲染进程和主进程之间的通信 在 Electron 应用中,主进程和渲染进程是相互隔离的,这是为了安全和稳定性考虑。 然而,在很多情况下,渲染进程需要访问主进程中的某些功能,例如系统级别的操作或者一些应用级…...
15分钟学 Go 第 42 天:RESTful API设计
第42天:RESTful API设计 目标:理解RESTful API的设计原则 在现代Web开发中,RESTful API(Representational State Transfer)已经成为了标准的架构风格,用于实现客户端与服务器之间的通信。通过遵循REST的设…...

如何安全的中断一个运行中的线程?
文心快码进入3.0时代, 最新发布的代码问答、编码、Debug、单测、安全智能体, 分别在开发的设计、编码、构建、测试验证全流程通过AI赋能,让效率更高、效果更好。可以通过自然语言对话,独立为你完成一项编码任务。 👉点…...
【121. 买卖股票的最佳时机】——贪心算法/动态规划
121. 买卖股票的最佳时机 一、题目难度 简单 三、题目描述 给定一个数组 prices,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择某一天买入这只股票,并选择在未来的某一个不同的日子卖出该股票。设计一个算法来计算你所能获…...
LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略
LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略 导读:在基于大语言模型(LLM)技术实现数字计算能力的背景下,文本内容的理解和计算过程涉及多个领域的交叉技术,包括自然语言处理(NLP)、机器学习、以及数值计算。…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...

Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...