06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档

芯航线——普利斯队长精心奉献

 

实验目的:1.掌握BCD码的原理、分类以及优缺点

         2.设计一个多位的8421码计数器并进行验证

         3.学会基本的错误定位以及修改能力     

实验平台:

实验原理:

    BCD码(Binary-Coded Decimal)又被称为二进码十进数、二-十进制代码是一种十进制的数字编码,用4位二进制数来表示十进制数中的0~9个十个数之一。BCD编码又可以分成有权码和无权码两种,其中有权码如:8421码、2421码以及5421等;无权码如:余3码、格雷码以及余3循环码等。

    BCD码中最常用的是8421码,其四个bit权值分别是8421;同理5421码各位的权依次为54215421码特点是最高位连续50后连续51,故其当计数器采用这种编码时,最高位可产生对称方波输出;余3码是在8421码上加加0011的出来的;码格雷码的特点是任意两个相邻的代码只有一位二进制数不同,编码格式不唯一;3循环具有格雷码的特点还具有编码的首尾可以连接来进行循环,这样可用反馈移位寄存器来实现,硬件实现简单。下面表6-1给出常见的几种编码格式:

十进制数

8421

3

2421

5421

格雷码

3循环码

0

0000

0011

0000

0000

0000

0010

1

0001

0100

0001

0001

0001

0110

2

0010

0101

0010

0010

0011

0111

3

0011

0110

0011

0011

0010

0101

4

0100

0111

0100

0100

0110

0100

5

0101

1000

1011

1000

0111

1100

6

0110

1001

1100

1001

0101

1101

7

0111

1010

1101

1010

0100

1111

8

1000

1011

1110

1011

1100

1110

9

1001

1100

1111

1100

1101

1010

6-1 常见的BCD

在实际使用中如不特指BCD码格式均为代指8421码。通过以上介绍将十进制895转换为BCD码就是1001_1001_0101,同理若将BCD1001_0110_0100转换为十进制数即为964

BCD码的运算规则:BCD码是十进制数,而运算器对数据做加减运算时,都是按二进制运算规则进行处理的。这样,当将BCD码传送给运算器进行运算时,其结果需要修正。修正的规则是:当两个BCD码相加,如果和等于或小于 1001(即十进制数9),不需要修正;如果相加之和在 1010 1111(即十六进制数 0AH0FH)之间,则需加 'd6也就是'b0110进行修正;如果相加时,本位产生了进位,也需加 6 进行修正。下面举例说明:计算5+8,将58转换为8421 BCD码后输入加法器,则运算如下:0 1 0 1 + 1 0 0 0 = 1 1 0 1 结果大于9+ 0 1 1 0 即加 6 修正得出1 0 0 1 1,补充高位为0001_00115+8=13,结论正确。

BCD码的主要应用之一就是数码管,假设我们要将十进制数158显示,一般解决办法是先要除法运算158/100= 1得出百位,再取余158%100 = 58后继续进行除法运算58 / 10 = 5得出十位,再进行一次取余158%10 = 8,得到个位。以上过程可以看出需要除法,但是由于除法运算是比较消耗计算时间导致整体需要的指令周期太久。但是如果我们先将其转换为BCD码,则可大幅度减少运算时间。具体例子会在数码管一讲详细介绍。

实验步骤:

按照02章所讲,建立工程子文件夹后,新建一个以名为BCD_Counter的工程保存在prj下,并在本工程目录的rtl文件夹下新建verilog file文件在此文件下输入以下内容并以BCD_Counter.v保存。

module BCD_Counter(Clk, Cin, Rst_n, Cout, q);

 

input Clk;//计数基准时钟

input Cin; //计数器进位输入

input Rst_n; //系统复位

 

output reg Cout; //计数进位输出

output [3:0]q; //计数值输出

 

reg [3:0]cnt; //定义计数器寄存器

 

//执行计数过程

always@(posedge Clk or negedge Rst_n)

if(Rst_n == 1'b0)

cnt <= 4'd0;

else if(Cin == 1'b1)begin

if(cnt == 4'd9)

cnt <= 4'd0;

else

cnt <= cnt + 1'b1;

end

else

cnt <= cnt;

 

//产生进位输出信号

always@(posedge Clk or negedge Rst_n)

if (!Rst_n)

Cout <= 1'b0;

else if(Cin == 1'b1 && cnt ==4'd9)

Cout <= 1'b1;

else

Cout <= 1'b0;

 

assign q = cnt;

 

endmodule

 

进行分析和综合直至没有错误以及警告。

    为了测试仿真编写测试激励文件,新建BCD_Counter_tb.v文件保存到testbench文件夹下,输入以下内容再次进行分析和综合直至没有错误以及警告。本激励文件除产生正常的时钟以及复位信号外,还生成了重复30次的占空比为15周期为120nscin信号。

`timescale 1ns/1ns

 

`define clock_period 20

 

module BCD_Counter_tb;

 

reg Clk;

reg Cin;

reg Rst_n;

 

wire Cout;

wire [3:0]q;

 

BCD_Counter BCD_Counter0(

.Clk(Clk),

.Cin(Cin),

.Rst_n(Rst_n),

.Cout(Cout),

.q(q)

);

 

initial Clk = 1'b1;

always#(`clock_period/2) Clk = ~Clk;

 

initial begin

Rst_n = 1'b0;

Cin = 1'b0;

#(`clock_period*200);

Rst_n = 1'b1;

#(`clock_period*20);

repeat(30)begin

Cin = 1'b1;

#`clock_period;

Cin = 1'b0;

#(`clock_period*5);

end

#(`clock_period*20);

$stop;

end

 

endmodule

 

设置好仿真脚本后进行功能仿真,可以看到如图6-1所示的波形文件,可以看出在复位信号置高后,每当进位输入信号cin为高时计数值输出q完成一次自加,直到计数值为9后清零重新计数并产生进位信号。

6-1 功能仿真波形图

现在以上面的BCD计数器为基础设计级联的多位BCD计数器,这里我们将计数器位数设置为12,即3BCD计数器级联既可以实现。新建verilog file文件在此文件下输入以下内容并以BCD_Counter_top.v保存至rtl文件夹下。本文件实现了例化与调用BCD_counter.v文件并将进位信号根据需要连接。

module BCD_Counter_top(Clk, Cin, Rst_n, Cout, q);

 

input Clk;//计数基准时钟

input Cin; //计数器进位输入

input Rst_n; //系统复位

 

output Cout; //计数进位输出

output [11:0]q; //计数值输出

 

wire Cout0,Cout1;

wire [3:0]q0,q1,q2;

 

assign q = {q2,q1,q0};

 

BCD_Counter BCD_Counter0(

.Clk(Clk),

.Cin(Cin),

.Rst_n(Rst_n),

.Cout(Cout0),

.q(q0)

);

 

BCD_Counter BCD_Counter1(

.Clk(Clk),

.Cin(Cout0),

.Rst_n(Rst_n),

.Cout(Cout1),

.q(q1)

);

 

BCD_Counter BCD_Counter2(

.Clk(Clk),

.Cin(Cout1),

.Rst_n(Rst_n),

.Cout(Cout),

.q(q2)

);

 

endmodule

将上述的文件设置为顶层,并再次进行分析和综合直至没有错误以及警告。点击RTL viewer,可以看到图6-2的模块结构,可以看出符合预期目的。

6-2多级BCD计数器RTL视图

为了测试仿真编写测试激励文件,新建BCD_Counter_top_tb.v文件保存到testbench文件夹下,输入以下内容再次进行分析和综合直至没有错误以及警告。本激励文件为了简化分析,复位后将cin一直置高,并延迟一定的时间。由于现在为三级BCD计数器,计数器满值为十六进制的999,特将仿真时间进行了延长至5000个时钟周期。

`timescale 1ns/1ns

 

`define clock_period 20

 

module BCD_Counter_top_tb;

 

reg Clk;

reg Cin;

reg Rst_n;

 

wire Cout;

wire [11:0]q;

 

BCD_Counter_top BCD_Counter_top0(

.Clk(Clk),

.Cin(Cin),

.Rst_n(Rst_n),

.Cout(Cout),

.q(q)

);

 

initial Clk = 1'b1;

always#(`clock_period/2) Clk = ~Clk;

 

initial begin

Rst_n = 1'b0;

Cin = 1'b0;

#(`clock_period*200);

Rst_n = 1'b1;

#(`clock_period*20);

Cin = 1'b1;

#(`clock_period*5000);

$stop;

end

 

endmodule

    设置好仿真脚本后进行功能仿真,可以看到如图6-3所示的波形文件,可以看到进位输出信号cout在计数值q变为十六进制999后延迟了两个系统周期才有输出,不符合既定设计,即设计存在错误。

6-3 多级BCD计数器初次功能仿真

    为了定位错误,将子模块的相关信号加入到wave栏,并再次仿真查看内部数据的信息进行分析解决。

    Modelsim找到Inatance窗口找到顶层文件,如图6-4-1所示点击加号后可以看到本顶层设计调用的模块。如图6-4-2所示单击不同的模块在Object栏可以看到其端口列表,选中需要的右键Add Wave,即可将内部信号加入到波形窗口。这里我门将每个模块的计数值输出信号q以及进位输出信号cout加入到波形窗口中。

6-4-1 添加内部信号到wave窗口

6-4-2 添加内部信号到wave窗口

单击工具栏中的Restart来复位仿真,在弹出对话框中全选后点击OK,点击Run-All来重启仿真。

6-5-1 复位仿真

6-5-2 复位仿真

6-6 重启仿真

可以看到仿真后加入内部信号的波形较乱没有层次,这里介绍一个分组操作,我们首先ctrl+A选中所有wave窗口中的波形,后ctrl+G进行分组。分组后如图6-7所示,放大局部信号可以看到照成这个原因是由于每一级的BCD计数器的进位输出信号均延迟了一个时钟周期,从而导致顶层文件进位输出cout信号输出延迟了三个时钟周期的问题,此时的计数器值已经变为了十六进制的002,而不再是999

图6-7 加入内部信号的功能仿真波形

这样我们就定位了错误,只需将修改进位输出信号cout修改为与计数值信号q计数到9时同时输出。将进位产生信号的逻辑修改为如下,且将Cout的类型改为普通wire型。

assign Cout = (Cin == 1'b1 && cnt == 4'd9);

再次仿真后可以看到在图6-8-1中十六进制的999时输出进位信号,符合了原定的要求,我们可以再将显示格式修改为二进制数,如图6-8-2中在计数值q1001_1001_1001产生进位信号,通过前面所讲的BCD码原理将其转换为BCD码的格式也是999

6-8-1 修改后的BCD计数器波形图

6-8-2 修改后的BCD计数器波形图

至此,就完成了一个BCD计数器的设计,并且学会了基本的调试修改能力。具体BCD计数器的板级验证,可以参考后续文档关于芯航线数码管的驱动设计。

 

备注:在修改设计后如果进行单独的功能仿真,会发现在图6-9中进位信号存在毛刺(glitch),这里的解决办法很多,其中之一就是在后续设计中通过预估正常信号与毛刺信号的时间宽度来进行筛选,也可以通过相关约束来解决;硬件方面可以外接滤波电容来消除其影响。

图6-9 毛刺信号

转载于:https://www.cnblogs.com/xiaomeige/p/5500950.html

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

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

相关文章

Flash基本工具练习

练习一、按钮 练习二、卡通脸 练习三、图标 转载于:https://www.cnblogs.com/staceydesign/p/3313229.html

mysql_query 资源标识符_借助PHP的mysql_query()函数来创建MySQL数据库的教程

以mysql_query()函数作为教程的基础前提&#xff0c;我们先来看一下mysql_query()的用法&#xff1a;mysql_query()函数PHP MySQL 函数库中&#xff0c;mysql_query() 函数用于向 MySQL 发送并执行 SQL 语句。对于没有数据返回结果集的 SQL &#xff0c;如 UPDATE、DELETE 等在…

ios PNG Crush error (PNG图片错误)

我是这么解决的&#xff1a; I had the same problem. How to fix : Open up image with Preview -> File > Export > Format change to PNG and you are done 其他被采纳的方法&#xff1a; 12 Answers activeoldestvotes up vote41down voteaccepted Did you check …

设计模式之十(外观模式)

前言 外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一系统更加容易使用. 结构图 SubSystem Class 子系统类集合 实现子系统的功能&#xff0c;处理Facade对象指派的任务&#xff0c;注意子类中没有Facade的任何信息&#xff0c;即…

sunday java_Sunday算法:最快的字符串匹配算法

之前被KMP的next数组搞的头昏脑胀说不上也是比较烦人的&#xff0c;今天看到还有这么有趣而且高效的算法(比KMP还快)&#xff0c;看来有必要做一点笔记了Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配算法&#xff0c;其简单、快速的特点非常好&#xff01;思路其核…

小波分析实验: 实验1 连续小波变换

实验目的&#xff1a; 在理解连续小波变换原理的基础上&#xff0c;通过编程实现对一维信号进行连续小波变换&#xff0c;&#xff08;实验中采用的是墨西哥帽小波&#xff09;&#xff0c;从而对连续小波变换增加了理性和感性的认识&#xff0c;并能提高编程能力&#xff0c;为…

java axmlprinter_安卓xml配置文件解析工具-AXMLPrinter2.jar(androidmanifest.xml 反编译)下载官方最新版-西西软件下载...

AXMLPrinter2.jar apk分析APK文件&#xff0c;取得APK文件中的 包名、版本号及图标&#xff0c;很强大的工具&#xff0c;再一次感受到了批处理的牛逼。可以将android安卓编译过的二进制XML文件(binary xml file)反编译明文输出保存。是apk反编译修改的必备工具之一。例如需要查…

UML用例图说明

转自&#xff1a;http://www.360doc.com/content/10/1206/23/3123_75672033.shtml 前些时间参加了潘加宇老师的技术讲座&#xff0c;UML建模技术受益匪浅。我也把平时的一些积累和上次的收获总结在这篇文章中&#xff0c;主要讲解用例图相关的知识。 用例图是软件需求分析…

Android 布局学习之——Layout(布局)详解一

layout&#xff08;布局&#xff09;定义了用户界面的可视化结构&#xff08;visual structure&#xff09;,如Activity的UI,应用窗口的UI。 有两种方式声明layout: 1.在xml文件中声明UI组件。 2.在运行时&#xff0c;实例化布局元素。我们可以以编码的方式创建View或ViewGroup…

Week1 Team Homework #2 Introduction of team member with photos

小组成员介绍 组长&#xff1a;黄剑锟 11061164 组员&#xff1a;顾泽鹏 11061160 组员&#xff1a;周辰光 11061154 组员&#xff1a;龚少波 11061167 组员&#xff1a;赵骞 11061155 组员&#xff1a;孙时 11061146 组员&am…

inttostr java_Delphi和Java实现webservice架构

Webservice现在已经不是什么新技术了&#xff0c;用java建立webservice是快捷的&#xff0c;但是用java在制作客户端的感觉上总是不如 Delphi的(个人感觉&#xff0c;java高手们不要笑话我)&#xff0c;那我们就用java实现webservice的服务端程序&#xff0c;delphi制作客户端。…

CentOS系列启动流程和内核原理(5系列,6系列,7系列)

前言&#xff0c;本来让我写博客我是拒绝的然而看见大家都在写&#xff0c;还能不能一起友好的玩耍了&#xff1f; 我要是不写怎能和同大神们一起ZB呢&#xff1f;遂开博客&#xff01; 一、Linux启动内核文件 1.Linux系统组成 动态视角&#xff1a;内核根文件系统 静态视…

LSTM和GRU vs 循环神经网络RNN

1、考虑下列三种情况下&#xff0c;对比一下普通RNN的表现和LSTM和GRU表现&#xff1a; &#xff08;1&#xff09;早期观测值对预测未来观测者具有非常重要的意义。 考虑一个极端情况&#xff0c;其中第一个观测值包含一个校验和&#xff0c; 目标是在序列的末尾辨别校验和是…

java ora-12505_Oracle SQL Developer连接报错(ORA-12505)的解决方案(两种)

用oracle数据库新建连接时遇到ora-12505&#xff0c;此问题解决后又出现ora-12519错误&#xff0c;郁闷的半天&#xff0c;经过一番折腾问题解决&#xff0c;下面小编把我的两种解决方案分享给大家&#xff0c;仅供参考。解决方案一&#xff1a;今天工作时在新建连接的时候遇到…

【Silverlight】解决DataTemplate绑定附加属性

本文 Silverlight 版本&#xff1a;4.0。 首先定义数据类型&#xff0c;此文始终使用此定义类型。public class SimpleData : ViewModelBase{private string _text;private int _column, _row;public string Text { get { return _text; } set { _text value; OnPropertyChang…

N个三角形分割平面个数(数学)

一个三角形的时候&#xff0c;再加一个三角形&#xff0c;每一条变会与第一个三角形的两条边相交&#xff0c;这样增加2个小三角形&#xff0c;即两个面。f(2)3*2f(1)&#xff0c;再加一个三角形&#xff0c;每一条边会与前两个三角形的四条边相交&#xff0c;形成四个小三角形…

2011年9月19日 面试重点:asp.net运行原理和生命周期

面试重点&#xff1a;asp.net运行原理和生命周期1、ispostback回调机制isPostBackfalse !IsPostBackture 当前页面是第一次加载IsPostBack 由于用户交互(page.submit())提交页面而产生的加载,二次加载html客户端代码将ispostback值存放在viewstate隐藏字段中<input type&quo…

redis——集群

2019独角兽企业重金招聘Python工程师标准>>> 现实中redis需要若干台redis服务器的支持&#xff1a; &#xff08;1&#xff09;从结构上&#xff0c;单个Redis服务器会产生单点故障&#xff0c;同时一台服务器需要承受所有的请求负载。这就需要为数据生成多个副本并…

POJ 2409 Let it Bead (Polya定理)

题意 用k种颜色对n个珠子构成的环上色&#xff0c;旋转翻转后相同的只算一种&#xff0c;求不等价的着色方案数。 思路 Polya定理 X是对象集合{1, 2, ……, n}&#xff0c; 设G是X上的置换群&#xff0c;用M种颜色染N种对象&#xff0c;则不同的染色方案数为&#xff1a; λ(g)…

java10支持mybatis_写了10年的代码,我最怕写Mybatis这些配置,现在有详解了

作者 | 阿进的写字台链接 | www.cnblogs.com/homejim/p/9782403.html在使用 mybatis 过程中&#xff0c; 当手写 JavaBean和XML 写的越来越多的时候&#xff0c; 就越来越同意出错。这种重复性的工作&#xff0c; 我们当然不希望做那么多。还好&#xff0c; mybatis 为我们提供…