一个问题:六位八段数码管(Verilog)
【基本信息】
需求:verilog程序,显示任意六位字符或数值,包含点号,且能够按需点亮位数。(学习篇)
芯片型号:cyclone Ⅳ EP4CE10F17C8
数码管属性:六位、八段
【最终成果图】

经过多轮测试,最后代码程序满足设计要求,但结合仿真发现了一个问题,仿真和上机不匹配,当然还是要以上机为准。
【模块例化图】

这里就是简单地赋个初始值,来测试digital模块,最终是要seg_led和seg_sel的显示变化。
【verilog程序】
1、digital模块
模块化设计,六个位上的值直接拆开做处理,分析起来清晰。sel_cnt表示目前要显示的位数(从右往左),即sel_cnt = 6代表全亮。dp_cnt表示点号所在位数,若dp_cnt=0则代表没有点号。clk_2khz为数码管的刷新信号。
module digital
(
input sys_clk ,
input sys_rst ,
input clk_2khz ,
input [3:0] num6,
input [3:0] num5,
input [3:0] num4,
input [3:0] num3,
input [3:0] num2,
input [3:0] num1,
input [2:0] sel_cnt ,
input [2:0] dp_cnt ,
output reg[5:0] seg_sel ,
output reg[7:0] seg_led
);
reg[2:0] sel_cnt_tran;
reg[3:0] num;
reg[2:0] tran1;
//endmodule
定义了几个变量,sel_cnt_tran用来根据数码管刷新信号更替数码管的位选,而num用来接引各位上的值,数码管根据num编号段选信号。tran1在过程讨论部分做解释。
always @(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
sel_cnt_tran = 3'd0;
else
if(clk_2khz)begin
if(sel_cnt_tran < sel_cnt)begin
tran1 = sel_cnt_tran;
sel_cnt_tran = sel_cnt_tran + 1'b1;
end
else begin
tran1 = sel_cnt_tran;
sel_cnt_tran = 3'd0;
end
end
end
上述代码就是位选更替,可以直观得到,tran1比sel_cnt_tran要晚上一个数码管刷新周期。
always @(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
seg_sel <= 6'b111_111;
else if(clk_2khz)begin
case(sel_cnt_tran)
3'd1:begin
seg_sel <= 6'b111_110;
num <= num1;
end
3'd2:begin
seg_sel <= 6'b111_101;
num <= num2;
end
3'd3:begin
seg_sel <= 6'b111_011;
num <= num3;
end
3'd4:begin
seg_sel <= 6'b110_111;
num <= num4;
end
3'd5:begin
seg_sel <= 6'b101_111;
num <= num5;
end
3'd6:begin
seg_sel <= 6'b011_111;
num <= num6;
end
default:begin
seg_sel <= 6'b111_111;
end
endcase
end
end
根据原理图,数码管是共阳极,并且位选拉低有效,这里测试是没有问题的。
always @(posedge sys_clk or negedge sys_rst)begin
if (!sys_rst)
seg_led = 8'b0;
else begin
case (num)
4'h0 : seg_led = 8'b1100_0000;
4'h1 : seg_led = 8'b1111_1001;
4'h2 : seg_led = 8'b1010_0100;
4'h3 : seg_led = 8'b1011_0000;
4'h4 : seg_led = 8'b1001_1001;
4'h5 : seg_led = 8'b1001_0010;
4'h6 : seg_led = 8'b1000_0010;
4'h7 : seg_led = 8'b1111_1000;
4'h8 : seg_led = 8'b1000_0000;
4'h9 : seg_led = 8'b1001_0000;
4'ha : seg_led = 8'b1000_1000;
4'hb : seg_led = 8'b1000_0011;
4'hc : seg_led = 8'b1100_0110;
4'hd : seg_led = 8'b1010_0001;
4'he : seg_led = 8'b1000_0110;
4'hf : seg_led = 8'b1000_1110;
default : seg_led = 8'b1100_0000;//多余
endcase
if(dp_cnt == (tran1))begin //确定点号,这里不是sel_cnt_tran
seg_led = seg_led & 8'b0111_1111;
end
end
end
2、clk_2khz模块
module clk_2khz
(
input sys_clk ,
input sys_rst ,
output reg clk_out
);
parameter cnt_2khz_max = 25_000;
reg[14:0] cnt;
clk_2khz时钟产生很简单,cnt_2khz_max = 1/2_000x50_000_000,在这就放下代码。注意两个问题:一个是不要直接posedge clk_2khz方式来读上升沿,另外尽量不要采用取反方式产生分频时钟信号,如果是取反,可以采用wire en;assign en = d1 & d0来读边沿信号。
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
cnt <= 15'd0;
clk_out <= 1'b0;
end
else if(cnt <(cnt_2khz_max-1'b1))begin
cnt <= cnt + 1'b1;
clk_out <= 1'b0;
end
else begin
cnt <= 15'd0;verilog
clk_out <= 1'b1;
end
end
endmodule
3、顶部例化测试
module digital_top (
input sys_clk ,
input sys_rst ,
output [5:0] seg_sel ,
output [7:0] seg_led
);
wire clk_2khz_tran;
reg[3:0] num1 = 4'd2;
reg[3:0] num2 = 4'h1;
reg[3:0] num3 = 4'd5;
reg[2:0] sel_cnt = 3'd6;
reg[2:0] dp_cnt = 3'd6;
digital digital_inst(); //例化省略
clk_2khz clk_generator1();
endmodule
4、Modelsim仿真
`timescale 1ns/1ns
module digital_tb();
parameter T1 =20 ;
parameter T2 =200;
parameter max = 14;
reg sys_clk;
reg clk_2khz;
reg sys_rst;
reg[3:0] num1 = 4'h1;
reg[3:0] num2 = 4'h1;
reg[3:0] num3 = 4'h1;
reg[2:0] sel_cnt = 3'd6;
reg[2:0] dp_cnt = 3'd6;
reg[3:0] cnt;
wire[7:0] seg_led;
wire[5:0] seg_sel;
always # (T1/2) sys_clk <= ~sys_clk;
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)
cnt <= 4'd0;
else begin
if(cnt < max)begin
cnt <= cnt + 1'b1;
clk_2khz <= 1'b0;
end
else begin
cnt <= 4'd0;
clk_2khz <= 1'b1;
end
end
end
initial begin
sys_clk <=1'b0;
sys_rst <=1'b0;
#50 sys_rst <=1'b1;
end
digital digital_inst();//例化省略
endmodule
【过程讨论】
首先由于自己疏忽,数码管位选刷新位置采用的是非阻塞赋值的方法,通过用sel_cnt_tran判断为真的话,通过仿真(下图)观察到,位选和段选不匹配,就是说,点号的位置不正确,现象是位选落后了。

然后想着将赋值方法改为阻塞赋值,还是有问题。强制更改,设定判断条件为if(dp_cnt == (sel_cnt_tran-1’b1))看看,显然,这样虽然有效(图在下面),但只能保证最终的点号位置有限,比如dp_cnt = 6就有问题,因为sel_cnt_tran在6后赋值是0,达不到条件。后面借助变量tran1在sel_cnt_tran刷新处赋值使其落后一个周期,仿真显示不正确,但上机测试有效。

一个问题:六位八段数码管(Verilog)的更多相关文章
- arduino八段数码管使用
一:八段数码管的使用 控制要求:0-9的计时数据 实物连接图: 控制代码: //智慧自动化2018.6.11 ;//定义数字接口7 连接a 段数码管 ;// 定义数字接口6 连接b 段数码管 ;// ...
- Verilog HDL那些事_建模篇笔记(实验七:数码管电路驱动)
1.同步动态扫描 多个数码管的显示采用的是同步动态扫描方法,同步动态扫描指的是:行信号和列信号同步扫描,是一种并行操作. 2.数码管驱动电路实现思路 如果要求数码管显示我们想要的数字,首先需 ...
- [51单片机] 以PWM控制直流电机为例建一个简单的51工程框架
目录 1)功能概述 2)引脚连接 3)框架介绍 4)模块说明 5)复用规则 6)工程链接 1)功能概述 名称:独立按键控制直流电机调速 内容:对应的电机接口需用杜邦线连接到uln2003电机控制端; ...
- AC620教程 第十五节 8位7段数码管驱动设计与验证
本章导读 电子系统中常用的显示设备有数码管.LCD液晶以及VGA显示器等.其中数码管又可分为段式显示(7段.米字型等)以及点阵显示(8*8.16*16等),LCD液晶的应用可以分为字符式液晶(1602 ...
- 【.NET 与树莓派】LED 数码管驱动模块——TM1638
LED 数码管,你可以将它看做是 N 个发光二级管的组合,一个灯负责显示一个段,七个段组合一位数字,再加一个小数点,这么一来,一位数码管就有八段.一般,按照顺时针的方向给每个段编号. 上图中的 h 就 ...
- 音响音箱/恒温壶/电量显示/电子数字时钟等LED数码管显示驱动IC-VK1640B 8段12位/12段8位显示
市面上最常用的数码管为七段/八段显示,八段数码管比七段数码管多一个发光二极管单元(比七段数码管多一个点),又按能显示多少个"8"可分为1位.2位.4位等等.数码管又分为共阳极驱动/ ...
- system verilog的一些总结(从其他博客复制来的)
转载自 http://blog.sina.com.cn/s/blog_e7fec2630101f5t9.html SystemVerilog是一种硬件描述和验证语言(HDVL),它基于IEEE 136 ...
- 单片机C语言开发学习笔记---动态的数码管
在郭天祥的那本书中,有一个通过按键控制数码管的例子,在运行这个例子的时候,我发现当按键按下的时候,第一位数码管会熄掉,这是为什么呢? 后来在网上找到了原因,当我按下按键不松开的时候,接下来要运行的代码 ...
- 对Verilog 初学者比较有用的整理(转自它处)
*作者: Ian11122840 时间: 2010-9-27 09:04 ...
- 我的 FPGA 学习历程(08)—— 实验:点亮单个数码管
数码管是一种常见的用于显示的电子器件,根据数码管大致可以分为共阴极和共阳极两种,下图所示的是一个共阳极的数码管的电路图(摘自金沙滩工作室的 51 开发板电路图),我的 AX301 开发板与这张图的情况 ...
随机推荐
- redis 简单整理——内存的管理[二十六]
前言 redis 是一个内存型数据库,那么就需要重点关注一下内存了. 正文 理解Redis内存,首先需要掌握Redis内存消耗在哪些方面.有些内存消 耗是必不可少的,而有些可以通过参数调整和合理使用来 ...
- coco2017 Dataset EDA
Github仓库:gy-7/coco_EDA (github.com) 对coco数据集的分析,近期忙着写论文,空余时间很少能写博文了. EDA的代码放在结尾了,Github仓库里也有.仓库里还有其他 ...
- Linux 安装 adb环境
一. 查看系统是否安装有adb adb或者adb version 二.通过apt-get安装adb 1. 安装adb sudo apt-get install android-tools-adb 2. ...
- portainer安装,配置,使用
Portainer安装 Portainer是Docker容器管理可视化界面,主要是可以通过可视化界面创建,管理Dockert容器,并且支持多个节点管理(免费版支持五个节点). Portainer官网地 ...
- Koordinator v0.7: 为任务调度领域注入新活力
简介: 在这个版本中着重建设了机器学习.大数据场景需要的任务调度能力,例如 Coscheduling.ElasticQuota 和精细化的 GPU 共享调度能力.并在调度问题诊断分析方面得到了增强,重 ...
- 全方位事件监控管理,阿里云日志服务Kubernetes事件中心正式上线
2020年2月21日,阿里云日志服务Kubernetes事件中心正式上线,为Kubernetes事件提供集中化采集.存储.分析.可视化.告警等能力,帮助Kubernetes使用者快速构建准实时.高可靠 ...
- 进一步释放技术红利,阿里云推出全新内存增强型实例re6,性能提升30%
5月7日,国内最大云计算厂商阿里云宣布推出全新一代内存增强型实例,提供1:14.8超大内存比内存容量,满足内存型数据库如SAP HANA.Redis等应用,充分释放技术红利,帮助线下企业快速上云,完成 ...
- iofsstat:帮你轻松定位 IO 突高,前因后果一目了然 | 龙蜥技术
简介:磁盘被打满到底是真实的业务需求量上来了呢?还是有什么野进程在占用 IO? iofsstat 帮你精准定位. 编者按:sysAK(system analyse kit),是龙蜥社区系统运维 SI ...
- [FE] Canvas 转图片并下载的方式
先获取 canvas 节点,使用 toDataURL 转为 image 数据,最后使用 a 链接下载. // Trans to image const canvas = document.getEle ...
- STM32 USART串口通信
一.介绍 通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换.USART利用分数波特率发生器提供宽范围的波特率选择.它支持同步单向 ...