二进制转BCD码原理及verilog实现
一、BCD码概念
BCD码(Binary-Coded Decimal),利用四个2进制位储存一个10进制的数,如下表所示。本文所讨论的问题均以8421BCD码为例,十进制的0~9分别用0000~1001来表示。
十进制数23,可表示为0010_0011,十进制数129,可表示为0001_0010_1001。
即分别对个位、十位、百位求对应的BCD码。
二、二进制数到BCD码的转换
先根据输入不同位数的二进制数,求对应的BCD码
假设输入1位二进制数1,则对应的BCD码为0001,对应十进制1;
若输入2位二进制数11,则BCD码为0011,对应十进制3;
若输入3位二进制数111,则BCD码为0111,对应十进制7;
若输入4位二进制数1110,那么问题来了,BCD码范围在0000~1001之间,只能表示十进制数0~9,而1110对应的十进制数为14!理应转换为0001_0100才对!那怎么才能转换成0001_0100呢?
先看看以下的分析:
1110(十进制14,BCD码需要表示十位和个位)是111(十进制7)左移一位的结果,其大小等于二倍的111,同理:
1100(十进制12,BCD码需要表示十位和个位)是110(十进制6)左移一位的结果,其大小等于二倍的110,
1010(十进制10,BCD码需要表示十位和个位)是101(十进制5)左移一位的结果,其大小等于二倍的101,
1000(十进制8,BCD码只需要表示个位)是100(十进制4)左移一位的结果,其大小等于二倍的100,
可见当二进制数 ≥5 (或 > 4 )的时候,左移以后就 ≥ 10,对应的BCD码就需要表示个位和十位了,那么对于一个四位的二进制数,先输入的高3位在 ≥5 (或 > 4 )的时候,要对它们处理一下,使得最低位输入进来后,表示十位的BCD码为0001。
加3移位法
例1:
依然设输入的二进制数为4位,表示为abcd,
在最低位输入前,如果高3位的 abc ≥ 5 (或 abc > 4 ),则对其加上3(即011),最低位d输入后,加过3的高3位就左移了一位.
这相当于(abc + 011)*2+d,即abc*2 + 6 + d,红字的部分就直接 ≥ 16 了,进一位!此时表示十位的BCD码为0001。
还是以输入为4位二进制数1110为例:
送入最高位得到1,
送入第二位得到11
送入第三位得到111 > 100,在111基础上进行修正,即111 + 011 = 1010,
在修正的结果上送入第四位得到10100,即0001_0100即为1110的BCD码(十进制14)。
例2:
再以输入为8位二进制数10100101(十进制165)为例,8位二进制数表示范围为0~255,BCD码需要表示百位、十位、个位:
送入最高位1;
送入第二位0得到10;
送入第三位1得到101 ,因为101 > 100,修正:101 + 011 = 1000;
送入第四位0得到1_0000;
送入第五位0得到10_0000;
送入第六位1得到100_0001;
送入第七位0得到1000_0010,1000 > 100,修正:1000 + 011 = 1011;
送入第八位1得到1_0110_0101,得到输出结果为0001_0110_0101(十进制165)。
module bin_to_bcd ( input rst_n, //系统复位,低有效 input [15:0] bin_code, //需要进行BCD转码的二进制数据 output reg [19:0] bcd_code //转码后的BCD码型数据输出 ); reg [35:0] shift_reg; always@(bin_code or rst_n)begin shift_reg = {20'h0,bin_code}; if(!rst_n) bcd_code = 0; else begin repeat(16) begin //循环16次 //BCD码各位数据作满5加3操作, if (shift_reg[19:16] >= 5) shift_reg[19:16] = shift_reg[19:16] + 2'b11; if (shift_reg[23:20] >= 5) shift_reg[23:20] = shift_reg[23:20] + 2'b11; if (shift_reg[27:24] >= 5) shift_reg[27:24] = shift_reg[27:24] + 2'b11; if (shift_reg[31:28] >= 5) shift_reg[31:28] = shift_reg[31:28] + 2'b11; if (shift_reg[35:32] >= 5) shift_reg[35:32] = shift_reg[35:32] + 2'b11; shift_reg = shift_reg << 1; end bcd_code = shift_reg[35:16]; end end endmodule