二进制转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

  

posted @ 2022-09-15 14:29  xiaoberber  阅读(1386)  评论(0编辑  收藏  举报