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,一经查实,立即删除!

相关文章

aix6.1 nfs

1.首先需要启动aix 上的nfs 服务 startsrc -g nfs 或者 smit nfs --> Network File System (NFS)  -->  Configure NFS on This System  -->  Start NFS 停止nfs stopsrc -g nfs 2. 在aix系统上&#xff0c;创建一个共享目录&#xff0c;与普通目录无区别 例…

Flash基本工具练习

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

韦根w34是多少位_韦根接口读卡器说明书

距离读卡器颜色为:银白色 QZ-8600B 与 QZ-8600 蓝牙远距离读卡器颜色为:可乐红、 蓝色、橙色、黄色 读卡最大距离:1-20 米 标签协议:CDMA 接口类型:韦根 26/......支持 RS485 接口和韦根接口读卡器的接入,RS485 接口采用双接口设计,支 持环路断点故障检测和冗余功能;韦根格式支…

GMT与UTC简介

一、简介 许多人都知道两地时间表简称为GMT或UTC&#xff0c;而世界时区表则通称为World Time &#xff0c;那么GMT与UTC的实质原意又是为何&#xff1f;世界时区又是怎么区分的&#xff1f;面盘上密密麻麻的英文单字代表着什么意义与作用呢&#xff1f;这些都是新手在接触两地…

键盘事件的响应

在应用的程序的控制方面&#xff0c;更多的使用的是屏幕上的控件&#xff0c;但是有的时候也需要直接对键盘事件来进行响应。键盘是Android中主要的输入设备&#xff0c;对按键的响应的处理是响应之间在程序中使用键盘的核心内容。本例需要实现的内容是通过键盘来控制屏幕上的一…

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;思路其核…

Apache不记录制定文件类型日志

vim /usr/local/apache2/conf/extra/httpd-vhosts.conf在CustomLog 行上加入如下代码&#xff1a;SetEnvIf Request_URI ".*\.gif$" p_w_picpath-requestSetEnvIf Request_URI ".*\.jpg$" p_w_picpath-requestSetEnvIf Request_URI ".*\.png$" p…

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

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

句子中单词首字母大写转换

//函数将句子中的每个单词的首字母改为大写 string first_letter(string& sentence) {//定义string 指针&#xff0c;并指向string 首地址string::iterator itsentence.begin ();//定义 关键 标志&#xff0c;反映检测到空格字符bool space_flagtrue;//string 指针未到字符…

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;主要讲解用例图相关的知识。 用例图是软件需求分析…

MySQL 按指定字段自定义列表排序

问题描述大家都知道, MySQL 中按某字段升序排列的 SQL 为 (以 id 为例, 下同):SELECT * FROM MyTable WHERE id IN (1, 7, 3, 5) ORDER BY id ASC降序排列的 SQL 为:SELECT * FROM MyTable WHERE id IN (1, 7, 3, 5) ORDER BY id DESC有时以上排序并不能满足我们的需求. 例如, …

WordPress get_allowed_mime_types函数(wp-includes/functions.php)存在跨站脚本漏洞

漏洞版本: WordPress 3.6 漏洞描述: CVE ID:CVE-2013-5738WordPress是一种使用PHP语言开发的博客平台&#xff0c;用户可以在支持PHP和MySQL数据库的服务器上架设自己的网志WordPress get_allowed_mime_types函数(wp-includes/functions.php)存在安全漏洞&#xff0c;由于不正确…

java迪杰斯特拉算法_迪杰斯特拉算法完整代码(Java)

package com.rao.graph;import java.util.*;/*** author Srao* className Dijkstra* date 2019/12/10 22:15* package com.rao.graph* Description 迪杰斯特拉算法*/public class Dijkstra {/*** 图的顶点*/private static class Vertex{String data;Vertex(String data){this.…

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

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

查询表结构

方法一SELECT 序号C.column_id, 列名C.name, 是否主键ISNULL(IDX.PrimaryKey,N), 数据类型T.name, 长度C.max_length, PrecisionC.precision, 小数位C.scale, 允许空CASE WHEN C.is_nullable1 THEN N是ELSE N否 END, 默认值ISNULL(D.definition,N),…

java window linux_java编程在linux下和windows下有什么区别。。。

在windows系统下编程没有点问题&#xff0c;一旦放在linux上就出现以下错误Strutshasdetectedanunhandledexception:Messages:...在windows系统下编程没有点问题&#xff0c;一旦放在linux上就出现以下错误 Struts has detected an unhandled exception: Messages: There is no…