06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档
Posted 小梅哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档相关的知识,希望对你有一定的参考价值。
芯航线——普利斯队长精心奉献
实验目的:1.掌握BCD码的原理、分类以及优缺点
2.设计一个多位的8421码计数器并进行验证
3.学会基本的错误定位以及修改能力
实验平台:无
实验原理:
BCD码(Binary-Coded Decimal)又被称为二进码十进数、二-十进制代码是一种十进制的数字编码,用4位二进制数来表示十进制数中的0~9个十个数之一。BCD编码又可以分成有权码和无权码两种,其中有权码如:8421码、2421码以及5421等;无权码如:余3码、格雷码以及余3循环码等。
BCD码中最常用的是8421码,其四个bit权值分别是8,4,2,1;同理5421码各位的权依次为5,4,2,1,5421码特点是最高位连续5个0后连续5个1,故其当计数器采用这种编码时,最高位可产生对称方波输出;余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,同理若将BCD码1001_0110_0100转换为十进制数即为964。
BCD码的运算规则:BCD码是十进制数,而运算器对数据做加减运算时,都是按二进制运算规则进行处理的。这样,当将BCD码传送给运算器进行运算时,其结果需要修正。修正的规则是:当两个BCD码相加,如果和等于或小于 1001(即十进制数9),不需要修正;如果相加之和在 1010 到1111(即十六进制数 0AH~0FH)之间,则需加 \'d6也就是\'b0110进行修正;如果相加时,本位产生了进位,也需加 6 进行修正。下面举例说明:计算5+8,将5和8转换为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_0011。5+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次的占空比为1:5周期为120ns的cin信号。
`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所示的波形文件,可以看出在复位信号置高后,每当进位输入信号cin09B-独立按键消抖实验02——小梅哥FPGA设计思想与验证方法视频教程配套文档
02-FPGA设计流程介绍——小梅哥FPGA设计思想与验证方法视频教程配套文档
09A-独立按键消抖实验01——小梅哥FPGA设计思想与验证方法视频教程配套文档
07-阻塞赋值与非阻塞赋值原理分析——小梅哥FPGA设计思想与验证方法视频教程配套文档