一个问题:六位八段数码管(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 开发板与这张图的情况 ...
随机推荐
- aop 阶段性概况
前言 对aop进行一个阶段性的总结. 正文 首先什么是aop呢? 那么首先看aop的解决什么样的问题. public class Program { public static void Main(s ...
- Oracle 一些触发器自治事务相关错误
Oracle 一些触发器自治事务相关错误 table XXX is mutating,trigger/function may not see it 在触发器中调用的函数或者语句有查询当前表的操作,比 ...
- 力扣77(Java)-组合(中等)
题目: 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合. 你可以按 任何顺序 返回答案. 示例 1: 输入:n = 4, k = 2输出:[ [2,4], [3,4], ...
- K8s场景下Logtail组件可观测方案升级-Logtail事件监控发布
简介: SLS针对Logtail本身以及Logtail的管控组件alibaba-log-controller,采用K8s事件的方式,将处理流程中的关键事件透出,从而让用户能够更清楚的感知其中发生的异常 ...
- 如何将传统 Web 框架迁移部署到 Serverless 架构?
简介: 与其说 Serverless 架构是一个新的概念,不如说它是一种全新的思路,一种新的编程范式. 与其说 Serverless 架构是一个新的概念,不如说它是一种全新的思路,一种新的编程范式. ...
- CPU Burst有副作用吗?让数学来回答!| 龙蜥技术
简介: 使用CPU Burst的副作用是什么?是否有不适用的场景呢?戳我给你答案~ 编者按:CPU Burst 特性已合入 Linux 5.14,Anolis OS 8.2.Alibaba Clou ...
- [Ethereum] 浅谈 ERC20 在 openzeppelin-contracts 中的结构与实现
目前 openzeppelin-contracts 的稳定版是 v2.5,截止到本文发布,最新的 Tag 为 v3.0.0-rc.0 以下是 token/ETC20 的文件列表: IERC20.sol ...
- Windows 对全屏应用的优化
全屏应用对应的是窗口模式应用,全屏应用指的是整个屏幕都是被咱一个应用独占了,屏幕上没有显示其他的应用,此时的应用就叫全屏应用.如希沃白板这个程序.本文主要告诉大家从微软官方的文档以及考古了解到的 Wi ...
- Django之ORM操作Mysql
一.单表操作 # 单表查询操作基本方法 class BookList(models.Model): title = models.CharField(max_length=32) price = mo ...
- kali使用apt-get update 出现数字签名失效
kali使用apt-get update 出现数字签名失效 下载签名:wget archive.kali.org/archive-key.asc 安装签名:apt-key add archive-ke ...