17 ABCD数码管显示与动态扫描原理

2024-02-14 01:44

本文主要是介绍17 ABCD数码管显示与动态扫描原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 驱动八位数码管循环点亮

1.1 数码管结构图

数码管有两种结构,共阴极和共阳极,ACX720板上的是共阳极数码管,低电平点亮。

1.2 三位数码管等效电路图

为了节约I/O接口,各个数码管的各段发光管被连在一起,通过sel端口选择要发光的数码管。

1.3 单个数码管发光的LUT(look up table)

2.  数码管显示与动态扫描逻辑建模

3. 数码管显示与动态扫描的Verilog实现

3.1 不完善的设计代码版本

1. 设计代码

该设计代码有两个地方需要修改

  1. 分频时钟的使用不合理,在fpga设计中,一定要避免使用计数器(寄存器)分频得到的信号来作为时钟再去驱动其他的寄存器;推荐使用使能时钟,不要使用门控时钟。
  2. 在fpga设计中,推荐多使用时序逻辑而非组合逻辑。对于case语句,我们要将其放在always语句块中,在每个时钟沿下发生数据的变换。
module hex8(clk,rstn,disp_data,sel,led
);parameter times = 25000; // 0.5msinput clk;input rstn;input [31:0]disp_data;output reg [7:0] sel;output reg [7:0] led;reg [15:0]div_cnt;always@(posedge clk or negedge rstn)if(!rstn)div_cnt <= 0;else if(div_cnt >= times - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;//分频时钟//用一个寄存器来模拟一个时钟去驱动其他寄存器会存在许多问题reg clk_lk;always@(posedge clk or negedge rstn)if(!rstn)clk_lk <= 0;else if(div_cnt == times - 1)clk_lk <= ~clk_lk;//cnt累加器reg [2:0] num_cnt;    always@(posedge clk_lk or negedge rstn)if(!rstn)num_cnt <= 0;elsenum_cnt <= num_cnt + 1'd1;//三八译码器    always@(posedge clk_lk or negedge rstn)if(!rstn)sel <= 0;else case(num_cnt)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//八选一多路器reg [3:0]disp_tmp;always@(*)case(num_cnt)0:disp_tmp = disp_data[3:0];1:disp_tmp = disp_data[7:4];2:disp_tmp = disp_data[11:8];3:disp_tmp = disp_data[15:12];4:disp_tmp = disp_data[19:16];5:disp_tmp = disp_data[23:20];6:disp_tmp = disp_data[27:24];7:disp_tmp = disp_data[31:28];endcase//四十六译码器 always@(*)case(disp_tmp)0:led = 8'hc0;1:led = 8'hf9;2:led = 8'ha4;3:led = 8'hb0;4:led = 8'h99;5:led = 8'h92;6:led = 8'h82;7:led = 8'hf8;8:led = 8'h80;9:led = 8'h90;4'ha:led = 8'h88;4'hb:led = 8'h83;4'hc:led = 8'hc6;4'hd:led = 8'ha1;4'he:led = 8'h86;4'hf:led = 8'h8e;  default:led = 8'hc0;endcaseendmodule

2. 仿真波形

3.1 修改分频时钟和case语句后的设计代码

1. 设计代码

module hex8_2(clk,rstn,disp_data,sel,led
);parameter times = 50000; // 1msinput clk;input rstn;input [31:0]disp_data;output reg [7:0] sel;output reg [7:0] led;reg [15:0]div_cnt;always@(posedge clk or negedge rstn)if(!rstn)div_cnt <= 0;else if(div_cnt >= times - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;//使能时钟  reg clk_lk;always@(posedge clk or negedge rstn)if(!rstn)clk_lk <= 0;else if(div_cnt == times - 1)clk_lk <= 1'd1;elseclk_lk <= 0;//cnt累加器reg [2:0] num_cnt;    always@(posedge clk_lk or negedge rstn)if(!rstn)num_cnt <= 0;else if(clk_lk == 1)num_cnt <= num_cnt + 1'd1;//三八译码器    always@(posedge clk or negedge rstn)if(!rstn)sel <= 0;else case(num_cnt)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//八选一多路器reg [3:0]disp_tmp;always@(posedge clk)case(num_cnt)0:disp_tmp = disp_data[3:0];1:disp_tmp = disp_data[7:4];2:disp_tmp = disp_data[11:8];3:disp_tmp = disp_data[15:12];4:disp_tmp = disp_data[19:16];5:disp_tmp = disp_data[23:20];6:disp_tmp = disp_data[27:24];7:disp_tmp = disp_data[31:28];endcase//四十六译码器 always@(posedge clk)case(disp_tmp)0:led = 8'hc0;1:led = 8'hf9;2:led = 8'ha4;3:led = 8'hb0;4:led = 8'h99;5:led = 8'h92;6:led = 8'h82;7:led = 8'hf8;8:led = 8'h80;9:led = 8'h90;4'ha:led = 8'h88;4'hb:led = 8'h83;4'hc:led = 8'hc6;4'hd:led = 8'ha1;4'he:led = 8'h86;4'hf:led = 8'h8e;  default:led = 8'hc0;endcaseendmodule

2.仿真代码

module hex8_2(clk,rstn,disp_data,sel,led
);parameter times = 50000; // 1msinput clk;input rstn;input [31:0]disp_data;output reg [7:0] sel;output reg [7:0] led;reg [15:0]div_cnt;always@(posedge clk or negedge rstn)if(!rstn)div_cnt <= 0;else if(div_cnt >= times - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;//使能时钟  reg clk_lk;always@(posedge clk or negedge rstn)if(!rstn)clk_lk <= 0;else if(div_cnt == times - 1)clk_lk <= 1'd1;elseclk_lk <= 0;//cnt累加器reg [2:0] num_cnt;    always@(posedge clk_lk or negedge rstn)if(!rstn)num_cnt <= 0;else if(clk_lk == 1)num_cnt <= num_cnt + 1'd1;//三八译码器    always@(posedge clk or negedge rstn)if(!rstn)sel <= 0;else case(num_cnt)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//八选一多路器reg [3:0]disp_tmp;always@(posedge clk)case(num_cnt)0:disp_tmp = disp_data[3:0];1:disp_tmp = disp_data[7:4];2:disp_tmp = disp_data[11:8];3:disp_tmp = disp_data[15:12];4:disp_tmp = disp_data[19:16];5:disp_tmp = disp_data[23:20];6:disp_tmp = disp_data[27:24];7:disp_tmp = disp_data[31:28];endcase//四十六译码器 always@(posedge clk)case(disp_tmp)0:led = 8'hc0;1:led = 8'hf9;2:led = 8'ha4;3:led = 8'hb0;4:led = 8'h99;5:led = 8'h92;6:led = 8'h82;7:led = 8'hf8;8:led = 8'h80;9:led = 8'h90;4'ha:led = 8'h88;4'hb:led = 8'h83;4'hc:led = 8'hc6;4'hd:led = 8'ha1;4'he:led = 8'h86;4'hf:led = 8'h8e;  default:led = 8'hc0;endcaseendmodule

3.仿真波形

 4. 使能时钟与门控时钟的原理和差异

1. 使能时钟和门控时钟

  • 使用门控时钟时:将一个D触发器的输出作为其他D触发器的时钟输入,忽略ENA。

  • 使用使能时钟时:D触发器的工作时钟仍为高质量的全局时钟,利用使能时钟使能D触发器。

2. 使用全局时钟的原因

  • 全局时钟是一条“高速公路”,时钟信号到达各个寄存器的时间受连线距离影响比较小,而用寄存器产生的门控时钟,走的是内部连线,随着距离的延长,延迟增加明显,从而破环寄存器的建立保持时间。
  • 使用寄存器传输时钟信号时,随着寄存器一级一级的传递,信号会出现波动,时钟信号的波形会越来越差(毛刺,波动等)
  • 全局时钟有专门的晶体管来提高时钟的驱动能力,而寄存器产生的时钟会随着寄存器的传递,驱动能力越来越弱。

这篇关于17 ABCD数码管显示与动态扫描原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/707192

相关文章

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配

Vue3中的动态组件详解

《Vue3中的动态组件详解》本文介绍了Vue3中的动态组件,通过`component:is=动态组件名或组件对象/component`来实现根据条件动态渲染不同的组件,此外,还提到了使用`markRa... 目录vue3动态组件动态组件的基本使用第一种写法第二种写法性能优化解决方法总结Vue3动态组件动态

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Java使用POI-TL和JFreeChart动态生成Word报告

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码... 目录前言一、需求背景二、方案分析三、 POI-TL + JFreeChart 实现3.1 Maven

MySQL中的MVCC底层原理解读

《MySQL中的MVCC底层原理解读》本文详细介绍了MySQL中的多版本并发控制(MVCC)机制,包括版本链、ReadView以及在不同事务隔离级别下MVCC的工作原理,通过一个具体的示例演示了在可重... 目录简介ReadView版本链演示过程总结简介MVCC(Multi-Version Concurr

Java导出Excel动态表头的示例详解

《Java导出Excel动态表头的示例详解》这篇文章主要为大家详细介绍了Java导出Excel动态表头的相关知识,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录前言一、效果展示二、代码实现1.固定头实体类2.动态头实现3.导出动态头前言本文只记录大致思路以及做法,代码不进

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

如何设置vim永久显示行号

《如何设置vim永久显示行号》在Linux环境下,vim默认不显示行号,这在程序编译出错时定位错误语句非常不便,通过修改vim配置文件vimrc,可以在每次打开vim时永久显示行号... 目录设置vim永久显示行号1.临时显示行号2.永www.chinasem.cn久显示行号总结设置vim永久显示行号在li