二进制转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之间, 是满10进位的, 它只能表示十进制数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,

左移相当于乘2, 那么当二进制数 ≥ 0101b, 即≥5(或> 0100b,  即 >4)的时候,左移以后就 ≥ 1010b , 即 ≥ 10,对应的BCD码就需要表示个位和十位了,那么对于一个 4 位的二进制数,先输入的高3位在 ≥5 (或 > 4 )的时候,要对它们处理一下,使得最低位输入进来后,表示十位的BCD码为0001。

这个处理过程, 称为:

加3移位法

举例说明一下, 先设输入一个4位二进制数, 记作abcd,输出为其对应的8421BCD码.

在最低位输入前,如果高3位的 abc  ≥ 0101(或 abc  > 0100)时, 对其加上3(即0011), 最低位d输入, 使得加过3的高3位整体左移一位.

这相当于(abc + 0011)*2+d,即abc*2 + 6 + d,红字的部分就直接 ≥ 16 了,超过了4位2进制数表示的范围,  向更高位进一位!那么此时表示十位的BCD码为0001。

举两个实例, 更容易理解:

例1:

还是以输入为4位二进制数1110(十进制14)为例:

送入最高位得到0001;

送入第二位得到0011;

送入第三位得到0111 > 0100,在0111基础上进行修正,即0111 + 0011 = 1010;

在修正的结果上送入第四位得到1_0100,即0001_0100即为1110的BCD码(十进制14)。

例2:

再以输入为8位二进制数10100101(十进制165)为例,8位二进制数表示范围为0~255,BCD码需要表示百位、十位、个位, 将10100101b从高位到低位依次送入:

送入最高位1, 得到0001;

送入第二位0, 得到0010;

送入第三位1, 得到0101 ,因为0101 > 0100,修正:0101 + 0011 = 1000;

送入第四位0, 得到0001_0000;

送入第五位0, 得到0010_0000;

送入第六位1, 得到0100_0001;

送入第七位0, 得到1000_0010,1000 > 0100,修正:1000 + 0011 = 1011;

送入第八位1, 得到0001_0110_0101,得到输出结果为0001_0110_0101(十进制165)。

归纳为:  每次当新的一位输入前, 都需要对表示 百位/十位/个位 的连续4bit数据判断大小. 大于4, 则进行加3移位处理.

下面为二进制转BCD码的verilog实现过程:

三、verilog实现

设计一个8位无符号二进制数(取值范围0 ~ 255)到10位BCD码的转换组合逻辑电路。其中10位BCD码定义如下:

数据位

描述

9:8

百位BCD码,取值0 ~ 2

7:4

十位BCD码,取值0 ~ 9

3:0

个位BCD码,取值0 ~ 9

例如:

输入8'b10100101(十进制165),输出10'b01_0110_0101;

输入8'b11110000(十进制240),输出10'b10_0100_0000.

模块输入输出功能定义:

名称

方向

位宽

描述

bin_in

I

8

输入二进制数

bcd_out

O

10

输出BCD编码

要求:

Verilog实现代码可综合,逻辑延迟越小越好,给出仿真结果。

设计代码:

注:此处通过阻塞赋值实现移位寄存器的功能,用阻塞赋值描述移位寄存器是可行的(但这种风格并不好),通过阻塞赋值,只要赋值的顺序正确,就可以通过组合逻辑描述移位寄存器。相较于时序逻辑,可以有更小的逻辑延迟和资源消耗。

参考:夏宇闻《verilog数字系统设计教程》-- 14.5.寄存器模型 -- 例14.6

module binary_bcd(
	input	[7:0]	bin_in,
	output	[9:0]	bcd_out
    );
	
reg [3:0] ones;
reg [3:0] tens;
reg [1:0] hundreds;
integer i;

always @(*) begin
	ones 		= 4'd0;
	tens 		= 4'd0;
	hundreds 	= 2'd0;
	
	for(i = 7; i >= 0; i = i - 1) begin
		if (ones >= 4'd5) 		ones = ones + 4'd3;
		if (tens >= 4'd5) 		tens = tens + 4'd3;
		if (hundreds >= 4'd5)	hundreds = hundreds + 4'd3;
		hundreds = {hundreds[0],tens[3]};
		tens	 = {tens[2:0],ones[3]};
		ones	 = {ones[2:0],bin_in[i]};
	end

end	

assign bcd_out = {hundreds, tens, ones};

endmodule

testbench:

`timescale 1ns / 1ps

module tb_binary_bcd();

reg 	[7:0] bin_in;
wire  	[9:0] bcd_out;

initial begin
	bin_in = 8'b1010_0101; //十进制165
	#100
	bin_in = 8'b1111_0000; //十进制240
	#100
	bin_in = 8'b1111_1111;	//十进制255
end

binary_bcd u_binary_bcd(
	.bin_in (bin_in),
	.bcd_out(bcd_out)
);

endmodule

仿真结果:

 综合结果:

以下是16位二进制BCD码Verilog代码示例: module bin2bcd( input [15:] bin, output [3:] bcd, output [3:] bcd1, output [3:] bcd2, output [3:] bcd3 ); reg [3:] bcd_reg, bcd1_reg, bcd2_reg, bcd3_reg; reg [3:] bcd_next, bcd1_next, bcd2_next, bcd3_next; reg [3:] bin_reg; reg [3:] count; always @ (posedge clk) begin bin_reg <= bin; count <= ; bcd_reg <= ; bcd1_reg <= ; bcd2_reg <= ; bcd3_reg <= ; end always @ (posedge clk) begin if (count < 4) begin bcd_next = bcd_reg; bcd1_next = bcd1_reg; bcd2_next = bcd2_reg; bcd3_next = bcd3_reg; if (bin_reg[3:] > 4) begin bcd_next = bcd_next + 3; end if (bin_reg[7:4] > 4) begin bcd1_next = bcd1_next + 3; end if (bin_reg[11:8] > 4) begin bcd2_next = bcd2_next + 3; end if (bin_reg[15:12] > 4) begin bcd3_next = bcd3_next + 3; end if (bin_reg[3:] > 9) begin bcd_next = bcd_next + 6; end if (bin_reg[7:4] > 9) begin bcd1_next = bcd1_next + 6; end if (bin_reg[11:8] > 9) begin bcd2_next = bcd2_next + 6; end if (bin_reg[15:12] > 9) begin bcd3_next = bcd3_next + 6; end bcd_reg <= bcd_next; bcd1_reg <= bcd1_next; bcd2_reg <= bcd2_next; bcd3_reg <= bcd3_next; count <= count + 1; end end assign bcd = bcd_reg; assign bcd1 = bcd1_reg; assign bcd2 = bcd2_reg; assign bcd3 = bcd3_reg; endmodule 该代码将16位二进制换为4个4位BCD码。在时钟上升沿时,将二进制数存储在寄存器中,并将计数器和BCD码寄存器重置为。然后,对于每个BCD码,将其下一个值设置为当前值,并根据二进制数的每个4位数字进行调整。如果数字大于4,则添加3,如果数字大于9,则添加6。最后,将下一个BCD码值存储回寄存器中。最后,将四个BCD码输出。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bluebub

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值