数码管进阶设计验证

前言

        随着数字电路和嵌入式系统的广泛应用,数码管作为一种常见的显示设备,在各种电子产品中扮演着重要角色。数码管以其结构简单、显示清晰和成本低廉的特点,广泛应用于计数器、时钟、测量仪器等领域。然而,传统的数码管设计通常仅支持基本的数字显示功能,难以满足现代应用对更复杂显示需求的要求。

        近年来,随着FPGA技术的发展和应用,数码管的驱动设计也迎来了新的机遇。FPGA(现场可编程门阵列)作为一种强大的数字逻辑设计平台,具有高度的灵活性和并行处理能力,使得数码管驱动的设计可以实现更复杂的功能,例如显示正负号、小数点等。此外,FPGA支持的逻辑设计验证工具和方法也为设计的可靠性和稳定性提供了保障。

        本项目旨在基于FPGA平台,设计一种支持正负号和小数点显示的数码管驱动系统。该系统不仅能够满足基本的数字显示需求,还能够处理更复杂的显示要求,适应现代电子设备对显示功能的多样化需求。通过对FPGA平台的深入研究和应用,我们将探讨如何在数码管显示中实现这些进阶功能,并验证设计的正确性和有效性。

正文

一、数码管进阶设计验证

        1.项目需求

本项目旨在基于FPGA平台,设计一种支持正负号和小数点显示的数码管驱动系统。

        2.技术介绍

驱动部分请参考简易数字钟

本章节重在介绍如何使数码管显示正负号于小数点:

对于在之前做的数码管驱动模块有很多不足:输入数据为BCD码,并且只能输入BCD码,输入数据如果是二进制数据,数码管显示是错误的。


module seg_driver(input clk,input rst_n,input [23:0] data_in,//接收数字时钟信号output reg [2:0] sel,//位选信号output reg [7:0] seg//段选信号
);

针对不足处,本章节在模块内调用一二进制码转BCD码模块,使得输入数据易产生与传递,在此基础上,增加一小数点位输入用6位独热编码表示当前小数点位置,增加一标志信号输入,表示现在数值是正数还是负数。

module shu_ma_g_MAX(input 				clk		,input					rst_n		,input	[19:0]		data		,//数据2进制input [ 5:0]		point		,//小数点位input					signe		,//正负号位input					seg_en	,//数码管使能output reg[2:0]	sel		,output reg[7:0]	seg 		);

        3.顶层架构

        4.端口描述

clk时钟
rst_n复位信号
data[19:0]输入数据(2进制数据)
point[5:0]小数点位
signe正负号位
seg_en数码管使能
sel[2:0]位选信号
seg[7:0]段选信号

二、代码验证

数码管驱动模块

module shu_ma_g_MAX(input 				clk		,input					rst_n		,input	[19:0]		data		,//数据2进制input [ 5:0]		point		,//小数点位input					signe		,//正负号位input					seg_en	,//数码管使能output reg[2:0]	sel		,output reg[7:0]	seg 		);parameter cnt_1ms_max = 16'd49999;wire[3:0] data1				;//数码管数据
wire[3:0] data2				;//数码管数据
wire[3:0] data3				;//数码管数据
wire[3:0] data4				;//数码管数据
wire[3:0] data5				;//数码管数据
wire[3:0] data6				;//数码管数据reg[23:0]data_reg			;//寄存显示数据reg[15:0]cnt_1ms			;//1ms计数器
reg		cnt_1ms_flag	;
reg[2:0]	cnt_sel			;//扫描周期计数器
reg[3:0] data_zhan		;//数码管显示暂存数据
reg 		point_flag		;//小数点使能信号
reg[2:0] sel_reg			;//暂存输出always@(posedge clk,negedge rst_n)//判断符号位
beginif(rst_n == 0)data_reg <= 24'b0;elseif((data6)||(point[5]))data_reg <= {data6,data5,data4,data3,data2,data1};elseif(((data5)||(point[4]))&&(signe == 1'b1))//最高位为符号位011-111data_reg <= {4'd10,data5,data4,data3,data2,data1};elseif(((data5)||(point[4]))&&(signe == 1'b0))data_reg <= {4'd11,data5,data4,data3,data2,data1};elseif(((data4)||(point[3]))&&(signe == 1'b1))//次高位为符号位001-111data_reg <= {4'd11,4'd10,data4,data3,data2,data1};elseif(((data4)||(point[3]))&&(signe == 1'b0))data_reg <= {4'd11,4'd11,data4,data3,data2,data1};elseif(((data3)||(point[2]))&&(signe == 1'b1))//次次高位为符号位000-111data_reg <= {4'd11,4'd11,4'd10,data3,data2,data1};elseif(((data3)||(point[2]))&&(signe == 1'b0))data_reg <= {4'd11,4'd11,4'd11,data3,data2,data1};elseif(((data2)||(point[1]))&&(signe == 1'b1))//次次次高位为符号位000-011data_reg <= {4'd11,4'd11,4'd11,4'd10,data2,data1};elseif(((data2)||(point[1]))&&(signe == 1'b0))data_reg <= {4'd11,4'd11,4'd11,4'd11,data2,data1};elseif(((data1)||(point[0]))&&(signe == 1'b1))//次次次次高位为符号位000-001data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd10,data1};elsedata_reg <= {4'd11,4'd11,4'd11,4'd11,4'd11,data1};endalways@(posedge clk,negedge rst_n)	//计数器驱动模块
beginif(rst_n == 0)cnt_1ms <= 16'd0;elseif(cnt_1ms == cnt_1ms_max)cnt_1ms <= 16'd0;elsecnt_1ms <= cnt_1ms + 16'd1;endalways@(posedge clk,negedge rst_n)//1ms标志信号
beginif(rst_n == 0)cnt_1ms_flag <= 1'b0;elseif(cnt_1ms == cnt_1ms_max)cnt_1ms_flag <= 1'b1;elsecnt_1ms_flag <= 1'b0;
endalways@(posedge clk,negedge rst_n)//扫描周期计数器使能
beginif(rst_n == 0)cnt_sel <= 3'd0;elseif((cnt_sel == 3'd5)&&(cnt_1ms_flag <= 1'b1))cnt_sel <= 3'd0;elseif(cnt_1ms_flag <= 1'b1)cnt_sel <= cnt_sel + 3'd1;elsecnt_sel <= cnt_sel;
endalways@(posedge clk,negedge rst_n)//暂存输出
beginif(rst_n == 0)sel_reg <= 3'd0;elseif((cnt_sel == 3'd0)&&(cnt_1ms_flag <= 1'b1))sel_reg <= 3'd0;elseif(cnt_1ms_flag <= 1'b1)sel_reg <= sel_reg + 1'd1;elsesel_reg <= sel_reg;
endalways@(posedge clk,negedge rst_n)//段码数据传递
beginif(rst_n == 0)data_zhan <= 4'd0;elseif((seg_en == 1'b1)&&(cnt_1ms_flag <= 1'b1))case(cnt_sel)3'd0 : data_zhan <= data_reg[3:0];3'd1 : data_zhan <= data_reg[7:4];3'd2 : data_zhan <= data_reg[11:8];3'd3 : data_zhan <= data_reg[15:12];3'd4 : data_zhan <= data_reg[19:16];3'd5 : data_zhan <= data_reg[23:20];default : data_zhan <= 4'd0;endcaseelsedata_zhan <= data_zhan;
endalways@(posedge clk,negedge rst_n)//小数点点亮
beginif(rst_n == 0)point_flag <= 1'b0;elseif(cnt_1ms_flag <= 1'b1)point_flag <= ~point[cnt_sel];elsepoint_flag <= point_flag;
endalways@(posedge clk,negedge rst_n)//段码数值判断并输出
beginif(rst_n == 0)		seg <= 8'b1111_1111;//0elsecase(data_zhan)4'd0 : seg <= {point_flag,7'd100_0000};//04'd1 : seg <= {point_flag,7'd100_0000};//14'd2 : seg <= {point_flag,7'd100_0000};//24'd3 : seg <= {point_flag,7'd100_0000};//34'd4 : seg <= {point_flag,7'd100_0000};//44'd5 : seg <= {point_flag,7'd100_0000};//54'd6 : seg <= {point_flag,7'd100_0000};//64'd7 : seg <= {point_flag,7'd100_0000};//74'd8 : seg <= {point_flag,7'd100_0000};//84'd9 : seg <= {point_flag,7'd100_0000};//94'd10: seg <= 8'b1011_1111;//-4'd11: seg <= 8'b1111_1111;//熄灭
/*			4'd10: seg <= {point_flag,7'd100_0000};//A4'd11: seg <= {point_flag,7'd100_0000};//b4'd12 : seg <= {point_flag,7'd100_0000};//C4'd13 : seg <= {point_flag,7'd100_0000};//d4'd14 : seg <= {point_flag,7'd100_0000};//E4'd15 : seg <= {point_flag,7'd100_0000};//F
*/default : seg <= 8'd1100_0000;endcase
endalways@(posedge clk,negedge rst_n)
beginif(rst_n == 0)		sel <= 3'd0;//0			elsesel <= sel_reg;
ender_bcd er_bcd_inst(.clk	(clk	),.rst_n(rst_n),.data	(data	),//数据10进制.data1(data1),.data2(data2),.data3(data3),.data4(data4), .data5(data5),.data6(data6) 		 	);	endmodule

数据解析模块

module er_bcd(input 				clk		,input					rst_n		,input	[19:0]		data		,//数据10进制output reg[3:0]	data1		,//bcd码output reg[3:0]	data2		,//bcd码output reg[3:0]	data3		,//bcd码output reg[3:0]	data4		,//bcd码 output reg[3:0]	data5		,//bcd码output reg[3:0]	data6		 //bcd码	);reg [4 :0]cnt_shift	;
reg [43:0]data_shift	;//暂存转换后的BCD码
reg 		 shift_flag	;always@(posedge clk, negedge rst_n)//记时钟21次后清零,大约20ns*20=400ns进行一次数据转码并输出
beginif(rst_n == 0)cnt_shift <= 5'd0;elseif((cnt_shift == 5'd21)&&(shift_flag == 1'b1))//计数清零cnt_shift <= 5'd0;elseif(shift_flag == 1'b1)cnt_shift <= cnt_shift + 5'd1;elsecnt_shift <= cnt_shift;
endalways@(posedge clk, negedge rst_n)
beginif(rst_n == 0)data_shift <= 43'd0;elseif(cnt_shift == 5'd0)data_shift <= {24'd0,data};elseif((cnt_shift <= 20)&&(shift_flag ==  1'b0))begindata_shift[23:20] <= (data_shift[23:20] > 4)?(data_shift[23:20] + 2'd3):(data_shift[23:20]);//大四加三data_shift[27:24] <= (data_shift[27:24] > 4)?(data_shift[27:24] + 2'd3):(data_shift[27:24]);//大四加三data_shift[31:28] <= (data_shift[31:28] > 4)?(data_shift[31:28] + 2'd3):(data_shift[31:28]);//大四加三data_shift[35:32] <= (data_shift[35:32] > 4)?(data_shift[35:32] + 2'd3):(data_shift[35:32]);//大四加三data_shift[39:36] <= (data_shift[39:36] > 4)?(data_shift[39:36] + 2'd3):(data_shift[39:36]);//大四加三data_shift[43:40] <= (data_shift[43:40] > 4)?(data_shift[43:40] + 2'd3):(data_shift[43:40]);//大四加三endelseif((cnt_shift <= 20)&&(shift_flag ==  1'b1))data_shift <= data_shift << 1;elsedata_shift <= data_shift;
endalways@(posedge clk, negedge rst_n)//相对于时钟信号,0时数据计算,1时进行数据移位
beginif(rst_n == 0)shift_flag <= 1'b0;elseshift_flag = ~shift_flag;
endalways@(posedge clk, negedge rst_n)
beginif(rst_n == 0)begindata1   <=  4'b0;data2   <=  4'b0;data3   <=  4'b0;data4   <=  4'b0;data5   <=  4'b0;data6   <=  4'b0;endelse	if(cnt_shift == 5'd21)begindata1   <=  data_shift[23:20];//分段传递data2   <=  data_shift[27:24];//分段传递data3   <=  data_shift[31:28];//分段传递data4   <=  data_shift[35:32];//分段传递data5   <=  data_shift[39:36];//分段传递data6   <=  data_shift[43:40];//分段传递end
endendmodule

仿真代码

`timescale 1ns/1ps
module shu_ma_g_MAX_tb;reg 			clk	;reg 			rst_n	;reg[19:0]	data	;//数据10进制reg[ 5:0]	point	;//小数点位reg			signe	;//正负号位reg			seg_en	;//数码管使能wire [7:0]	seg	;wire [2:0]	sel	;shu_ma_g_MAX shu_ma_g_MAX(.clk		(clk		),.rst_n	(rst_n	),.data		(data		),//数据10进制.point	(point	),//小数点位.signe	(signe	),//正负号位.seg_en	(seg_en	),//数码管使能.sel		(sel		),.seg 		(seg 		));initial clk =1;
always #10 clk = ~clk;initial beginrst_n = 0;#20rst_n = 1;seg_en = 1'b1;#100data = 0;#490data = 20'd98789;point = 6'b001000;signe = 1'b1;	//-98.789#20000data = 20'd1111;point = 6'b000100;#20000$stop;
endendmodule

三、仿真验证

运行仿真,直接调出中间数据进行分析

这里可以看出,在数据未完全解析时,数码管每个位的数据为高阻态,在解析完成后同时赋值给数码管对应段。

下面对其数据显示正确性进行检测:截出一段数据进行分析。

10,9,8,7,8,9对应数据-98789,输入数据应为-98.789。789三位输出相同(懒得改)前面三位分别是-,9,8.,8于8.不同在于最高位的1与0,即01000000表示8.,-为b1011_1111,由于数据的位扫描是按照低位到高位:11000000(9)11000000(8)11000000(7)01000000(8.)11000000(9)1011_1111(-),对应输出显示正确。

参考资料

数码管显示进阶

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

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

相关文章

DBeaver安装使用

文章目录 简介支持的数据库支持的系统 下载安装DBeaver使用修改Maven下载jar地址窗口->首选项连接->驱动->Maven配置仓库地址 选择需要连接的数据库进行连接 简介 DBeaver 是一个通用的数据库管理工具和 SQL 客户端&#xff0c;支持 MySQL, PostgreSQL, Oracle, DB2,…

运维学习————nginx2-配置详解及负载均衡

目录 一、配置文件详解 1.1、结构 1.2、重要配置解释 1.3、详细配置 全局配置 Events HTTP 服务器配置 server虚拟主机配置 location URL匹配配置 1.4、完整配置 二、负载均衡 2.1、概念 2.2、集群规划及实现 2.3、具体实现 2.3.1、克隆 2.3.2、修改tomcat1配…

Python | Leetcode Python题解之第372题超级次方

题目&#xff1a; 题解&#xff1a; class Solution:def superPow(self, a: int, b: List[int]) -> int:MOD 1337ans 1for e in b:ans pow(ans, 10, MOD) * pow(a, e, MOD) % MODreturn ans

C#高效异步文件监控与日志记录工具

优势 异步处理&#xff1a;提高了文件变化处理的效率&#xff0c;避免了阻塞主线程。线程安全&#xff1a;使用了线程安全的队列来避免多线程环境下的竞态条件。日志记录&#xff1a;异步日志记录减少了对主线程的干扰&#xff0c;并且能够处理大量事件。灵活配置&#xff1a;…

【MySQL、Hive】分区表

SQL 本身并不直接支持多线程处理&#xff0c;因为 SQL 是一种声明式语言&#xff0c;主要用于定义和操作数据库中的数据。多线程通常是在应用程序层面实现的。然而&#xff0c;有一些方法可以在 SQL 环境中优化并发处理和提高性能&#xff0c;这些方法在某种程度上可以被视为&q…

How to stream video in a loop via RTP using ffmpeg?

ffmpeg -re -fflags genpts -stream_loop -1 -i conf2-2.mp4 -vcodec copy -an -f rtp rtp://192.168.31.152:2000 vlc 应该可以播放出来的。 这里有一篇文章&#xff0c;有兴趣的可以试试&#xff1a; https://www.wowza.com/docs/how-to-configure-vlc-media-player-for…

MySQL 学习笔记之事务操作

文章目录 MySQL 事务操作事务概述1. 事务操作的基本用法1.1 创建表和插入数据1.2 设置手动提交1.3 正常的转账操作1.4 异常情况处理1.5 使用 START TRANSACTION 2. 事务隔离级别2.1 查看当前事务隔离级别2.2 设置事务隔离级别 完整代码 MySQL 事务操作 事务概述 事务是数据库管…

go+gin+vue入门

后端框架 1、安装go、goland 2、创建空项目 3、下载要用的包&#xff1a;命令行输入go get -u github.com/xxxx 4、安装mysql数据库&#xff0c;使用navicat创建数据库。 5、按照项目框架搭建目录、文件、代码&#xff1a;如router、model… 6、运行测试&#xff0c;go run ma…

云原生之全链路分布式跟踪系统 Zipkin和SkyWalking

贪多嚼不烂 Pinpoint 就不对比了 参考 APM系统简单对比(zipkin,pinpoint和skywalking) springcloud 看云 Zipkin和SkyWalking都是流行的分布式跟踪系统&#xff0c;但它们的设计和实现有明显的不同。 以下是它们之间的一些对比&#xff1a; 数据存储&#xff1a; Zipk…

RedisDistributedLock 分布式锁

设计一个简单的 RedisDistributedLock 类&#xff0c;实现单例模式&#xff0c;并包含基本的锁定机制。这个类将使用 Redis 来管理锁&#xff0c;确保在分布式系统中资源的同步访问 import redis.clients.jedis.Jedis;public class RedisDistributedLock {private static Redi…

nginxlvshaproxy负载均衡的区别

lvs 优势:抗负载能力很强、工作稳定、不占什么流量、pv 超过 1000 万可用 1s nginx:nginx工作第7层,支持 btkp 应用本身分流&#xff0c;s,没有这个功能 nginz 对网络依赖很小&#xff0c;nginx 安装简单也稳定,流量日p<1000 万 nginx 足以能撑住, 一般不是特别大的公司都达…

OpenCV(开源计算机视觉库)

OpenCV&#xff08;开源计算机视觉库&#xff09;是一个专注于实时计算机视觉的全面库&#xff0c;包含了丰富的工具和功能。以下是 OpenCV 中一些关键知识点的详细列表&#xff1a; 核心功能 基本结构&#xff1a;Mat、Scalar、Point、Size、Rect 等。 图像 I/O&#xff1a;读…

# 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群

利刃出鞘_Tomcat 核心原理解析&#xff08;八&#xff09;-- Tomcat 集群 一、Tomcat专题 - Tomcat集群 - 介绍及准备工作 1、Tomcat集群 简介 由于单台Tomcat的承载能力是有限的&#xff0c;当我们的业务系统用户量比较大&#xff0c;请求压力比较大时&#xff0c;单台Tomc…

macOS安装搭建python环境

安装Homebrew apt-get是一个常见于Debian和Ubuntu等基于Linux的操作系统中的包管理工具&#xff0c;用于安装、更新和移除软件包。然而&#xff0c;macOS使用的是Homebrew或者MacPorts等其他的包管理工具&#xff0c;并不使用apt-get。 如果你想在macOS上使用类似apt-get的功…

Python版《超级玛丽+源码》-Python制作超级玛丽游戏

小时候最喜欢玩的小游戏就是超级玛丽了&#xff0c;有刺激有又技巧&#xff0c;通关真的很难&#xff0c;救下小公主还被抓走了&#xff0c;唉&#xff0c;心累&#xff0c;最后还是硬着头皮继续闯&#xff0c;终于要通关了&#xff0c;之后再玩还是没有那么容易&#xff0c;哈…

<C++> 二叉搜索树

目录 二叉搜索树 1. 概念 2. 二叉搜索树操作 2.1 基础结构 2.2 非递归版 1. 查找 2. 插入 3. 删除 2.3 递归版 1. 查找 2. 插入 3. 删除 2.4 拷贝构造函数 2.5 赋值运算符重载 2.6 析构函数 2.7 完整代码 3. 二叉搜索树的应用 4. 二叉搜索树的性能 二叉搜索树 1. 概念 二叉搜索…

Debug-023-Document.createElement()的使用

Document.createElement() document.createElement()是在对象中创建一个对象&#xff0c;要与appendChild() 或 insertBefore()方法联合使用。 appendChild() 方法在节点的子节点列表末添加新的子节点。 insertBefore() 方法在节点的子节点列表任意位置插入新的节点。 用途举…

笔记整理—uboot启动过程(3)栈的二次设置以及常用名词解析,BL1部分完

前文说到了uboot的lowlevel_init都干了些什么&#xff0c;也就是经过了这项初期的低级启动&#xff0c;使得我们能在串口监视器上看见机器打印出的第一句话“OK”。当lowlevel_init结束后&#xff0c;uboot去做了另一件事情&#xff0c;那就是栈的再次设置。 第一次栈设置发生在…

Prompt-Tuning 和 LoRA大模型微调方法区别

Prompt-Tuning 和 LoRA(Low-Rank Adaptation)都是在预训练语言模型基础上进行微调的方法,它们有以下一些区别: 一、调整方式 Prompt-Tuning: 主要是通过优化特定任务的提示(prompt)来实现微调。通常在输入层引入可学习的连续提示向量,这些提示向量与原始输入进行拼接或…

解决Qt多线程中fromRawData函数生成的QByteArray数据不一致问题

解决Qt多线程中fromRawData函数生成的QByteArray数据不一致问题 目录 &#x1f514; 问题背景&#x1f4c4; 问题代码❓ 问题描述&#x1fa7a; 问题分析✔ 解决方案 &#x1f514; 问题背景 在开发一个使用Qt框架的多线程应用程序时&#xff0c;我们遇到了一个棘手的问题&…