二进制数转换为BCD码的方法都有哪些?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二进制数转换为BCD码的方法都有哪些?相关的知识,希望对你有一定的参考价值。
BCD码使用4位二进制数来表示十进制中0~9这10个数的数码。例如,十进制的237,其BCD码就是 0010_0011_0111 ,但是其二进制是 1110_1101 。
我们先来研究两个4位的BCD码相加的情况。设这两个BCD码对应的十进制是a,b,其中a,b∈0,1,2,...,9。此时只有3种情况:
也就是说:
第一种情况显然不需要再修正。
第二种情况,例如,5+8=13,我们希望得到BCD码是 0001_0011 ,但是运算结果 1101 ,因此如果我们加上了6,就可以得到正确结果: 1101 + 0110 = 0001_0011 。这是因为,十进制是逢十进一,但是4位BCD加法,在看作是二进制数做加法时,是逢十六进一。因此,如果结果是10≤a+b≤15,加上6以后就是16+0≤a+b+6≤16+5,此时因为逢十六进一的原因,就得到了结果 1_0≤[a+b+6]≤1_5 ,这个结果就是对的。
第三种情况,因为16≤a+b≤18,逢十六进一后,我们得到了 1_0≤[a+b]≤1_2 ,为了使结果正确,如果我们加上一个修正值6,就得到 1_6≤[a+b+6]≤1_8 ,从而结果也变得正确。
综上所述,如果两个BCD码相加:
考虑一个例子,比如 35+99=134。35和99的BCD码分别是 0011_0101 和 1001_1001 。先计算低4位: 0101 + 1001 = 1110 ,因为这个值大于9,因此加上6作为修正: 1110 + 0110 = 1_0100 。现在计算高四位,同时注意到还有一个进位: 0011 + 1001 + 0001 = 1101 ,这个值还是大于9,加上6,得到 1101 + 0110 = 1_0011 。因此最终结果是 1_0011_0100 ,这刚好就是134的BCD码。
我们之所以能够安全地加上进位,是因为BCD加法比照的就是十进制的加法,只不过前者是4位为一个单位,而后者是以1位数字作为一个单位。加上修正值后,BCD加法的进位就相当于十进制加法的进位。图示如下:
给定一个二进制数,要转BCD码。一个常用算法就是不断将该数除以10,以此依次分解出个位、十位、百位……上的数字,这些数字的4位二进制数就是对应的BCD。但是这样的算法需要不断做除法操作十分的麻烦。我们可以使用名为 加三左移法 来完成。
这个算法基于以下的事实:
一个n位二进制数 ,其展开是 如果使用秦九韶算法的嵌套形式写法,可以写成: 或者若令 则 如果使用这种形式,我们先计算的是 ,然后是 ,然后是 ,……,最后是 。
注意到 就是把 左移1位,这样就会在最右边空出一个位,之后再加 就是用 填充这个最低位,从而我们得到了 。不断左移,最终就能得到 ,现在我们来设计一个算法使得左移结束后能得到对应的BCD码。
设 是一个无限长的、初始状态为所有位都是0的理想寄存器, 是欲转换的数。我们使用下面的 归纳法 来构造证明我们通过不断左移最终能够得到存储在 中的 对应的BCD码:
由数学归纳原理,移动 len(h) 次后,我们最终可以得到 的BCD码。
作为一个例子,考虑使用该算法将 的二进制 1000_0110 转为BCD码:
现在, 已经全部移入,此时 的值就是 0001_0011_0100 ,它就是 的BCD码。
C语言的算法如下:
参考技术A二进制数转换为BCD码的方法有哪些?
首先,要把二进制数,转换为十进制数。
十进制数的 BCD 码,有许多种,你自己选一个吧:
基础项目(10)BCD转二进制程序设计讲解
写在前面的话
在前面小节的学习中,我们已经掌握了将二进制数转换成BCD码的方法。那么现在我们就反过来思考一下,设计一个什么样的电路,才可以将BCD码转换成二进制数呢?
基本概念
在数学中,我们都知道随便一个十进制数如5468 ,那么它的计算过程可以转换为:5468= 5*1000+4*100+6*10+8,因此BCD码转成二进制数的算法就是:
abcd = a*1000 + b*100 + c*10 +d
这种算法是最常规的一种算法,里面需要用到乘法器以及加法器,这种实现方式比较耗费资源,下面梦翼师兄会介绍一种算法,这种算法需要用到加法和移位来完成BCD转二进制数的功能,从而尽可能的节约逻辑资源。
移位算法原理
在介绍这种算法之前,梦翼师兄先来解释一个小小的问题:二进制码左移一位等于未左移的二进制码*2,例如有二进制码101001,转成十进制等于41,左移一位得到1010010,转成十进制等于82。
也就是说二进制码左移1位加上左移3位可以等效于二进制码乘以10,那么我们是否可以利用移位来代替乘法的运算呢?下面我们就来设计一个电路将输入的3位bcd码转换成二进制码,来实现BCD码转二进制数的功能。
顶层框图
顶层模块端口介绍
端口名 |
端口说明 |
clk |
系统50MHz时钟输入 |
rst_n |
系统低电平复位 |
bw |
BCD码百位输入 |
shiw |
BCD码十位输入 |
gew |
BCD码个位输入 |
binary |
输出转换后的二进制数 |
代码实现
/**************************************************** * Engineer : 梦翼师兄 * QQ : 761664056 * The module function: BCD码转二进制数模块 *****************************************************/ 01 module bcd_to_bin( 02 clk, //系统50Mhz时钟 03 rst_n, //系统低电平复位 04 bw, //输入的BCD码的百位 05 shiw, //输入的BCD码的十位 06 gew, //输入的BCD码的个位 07 binary //输出的二进制数 08 ); 09 10 input clk; 11 input rst_n; 12 input [3:0] bw; //百位 13 input [3:0] shiw; //十位 14 input [3:0] gew; //个位 15 16 output [9:0] binary; //转换结果 17 18 reg [9:0] bwValue1; //百位BCD码转换寄存器1 19 reg [9:0] bwValue2; //百位BCD码转换寄存器2 20 reg [9:0] bwValue3; //百位BCD码转换寄存器3 21 reg [9:0] shiwValue1; //十位BCD码转换寄存器1 22 reg [9:0] shiwValue2; //十位BCD码转换寄存器2 23 reg [9:0] gewValue; //个位BCD码转换寄存器 24 25 /***********转换操作*******************/ 26 always @(posedge clk or negedge rst_n) 27 if (!rst_n) 28 begin //寄存器赋初值 29 bwValue1 <= 0; 30 bwValue2 <= 0; 31 bwValue3 <= 0; 32 shiwValue1 <= 0; 33 shiwValue2 <= 0; 34 gewValue <= 0; 35 end 36 else 37 begin 38 //由我们得出的规律可知:a*100=a*(64+32+4)=a*64+a*32+a*4 39 //=a000000+a00000+a00,即a左移6位加上左移5位加上a左移2位 40 bwValue1 <= bw<<6; 41 bwValue2 <= bw<<5; 42 bwValue3 <= bw<<2; 43 //由我们得出的规律可知:a*10=a*(8+2)=a*8+a*2 =a000+a0, 44 //即a左移3位加上左移1位 45 shiwValue1 <= shiw<<3; 46 shiwValue2 <= shiw<<1; 47 gewValue <= gew; //个位数据不变 48 end 49 //将所有的各个位的转换结果相加就是转换后的二进制数 50 assign binary = bwValue1 + bwValue2 + bwValue3 + shiwValue1 51 + shiwValue2 + gewValue; 52 53 endmodule |
第18~23行我们定义了BCD码转换需要用到的寄存器,因为我们从算法原理这一部分中总结的规律是:百位的BCD码转换需要(a*100=a*(64+32+4)=a*64+a*32+a*4=a000000+a00000+a00,即a左移6位加上左移5位加上a左移2位)三部分组成,所以需要三组寄存器,同理十位和个位也分别需要两组和一组寄存器;37~48行测试执行移位操作,50~51行将移位的结果输出。
测试代码如下:
/**************************************************** * Engineer : 梦翼师兄 * QQ : 761664056 * The module function: BCD码转二进制数测试模块 *****************************************************/ 01 `timescale 1ns/1ps 02 03 module bcd_to_bin_tb; 04 05 reg clk; 06 reg rst_n; 07 reg [3:0] bw; //百位 08 reg [3:0] shiw; //十位 09 reg [3:0] gew; //个位 10 11 wire [9:0] binary; 12 13 initial begin 14 clk = 0; 15 rst_n = 0; 16 bw = 4‘d0; shiw = 4‘d0; gew = 4‘d0; 17 #1000 rst_n = 1; 18 19 #100 bw = 4‘d1; shiw = 4‘d2; gew = 4‘d0; //120 20 #100 bw = 4‘d3; shiw = 4‘d2; gew = 4‘d9; //329 21 #100 bw = 4‘d7; shiw = 4‘d0; gew = 4‘d3; //703 22 #100 bw = 4‘d0; shiw = 4‘d2; gew = 4‘d7; //027 23 #100 bw = 4‘d2; shiw = 4‘d9; gew = 4‘d0; //290 24 25 end 26 27 always #10 clk = ~clk; 28 29 bcd_to_bin bcd_to_bin( 30 .clk(clk), //系统50Mhz时钟 31 .rst_n(rst_n), //系统低电平复位 32 .bw(bw), //输入的BCD码的百位 33 .shiw(shiw), //输入的BCD码的十位 34 .gew(gew), //输入的BCD码的个位 35 .binary(binary) //输出的二进制数 36 ); 37 38 endmodule |
我们在测试代码中写入了5组BCD码来检测输出是否正确
仿真分析
从仿真图可以看出,分别输入5组BCD码:120、329、703、27、290,观察输出可知转换之后的二进制数是正确的,成功的把BCD码转换成了二进制码。所以本次设计是成功的。
以上是关于二进制数转换为BCD码的方法都有哪些?的主要内容,如果未能解决你的问题,请参考以下文章