BCD码的英文全称是Binary-Coded Decimal,简称BCD,按字面解释是二进制十进制代码,是一种二进制的数字编码形式。
常见的BCD码有8421BCD码,2421BCD码,5421BCD码,余3码以及格雷码等等。
在本文中,我们所采用的BCD码为8421BCD码。
8421码,即从左到右的二进制位权重分别为8、4、2、1。即
BCD码
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
值
0
1
2
3
4
5
6
7
8
9
数字时钟,需要十进制地显示时分秒;温度显示也需要十进制;次数显示也需要十进制······
module func(i_data, o_data)
input wire [7:0] i_data;
output wire [11:0] o_data;
assign o_data[11:8] = i_data / 100;
assign o_data[7:4] = i_data / 10 % 10;
assign o_data[3:0] = i_data % 10;
endmodule
这是我们在做算法题的时候用到的方法,而且Verilog是支持除法和取余运算的,但是这样会耗费太多资源。对于硬件设计来说,我们需要用适合硬件的方法。
对于4位二进制码,是逢16进位。而8421码是逢10进位。
因此,大于9的二进制码,加6就可以得到8421码。
首先给出步骤:(8位二进制数为例)
总之,在移位的过程中,如果移位出的数值大于等于5,则将数值加3,再进行移位。对于n位二进制数,就进行n次移位。
以二进制数 0111_1101为例,数值为125。
百位
十位
个位
二进制数
开始
4'b0000
4'b0000
4'b0000
8'b0111_1101
左移1
4'b0000
4'b0000
4'b0000
8'b1111_1010
左移2
4'b0000
4'b0000
4'b0001
8'b1111_0100
左移3
4'b0000
4'b0000
4'b0011
8'b1110_1000
左移4
4'b0000
4'b0000
4'b0111
8'b1101_0000
加3
4'b0000
4'b0000
4'b1010
8'b1101_0000
左移5
4'b0000
4'b0001
4'b0101
8'b1010_0000
加3
4'b0000
4'b0001
4'b1000
8'b1010_0000
左移6
4'b0000
4'b0011
4'b0001
8'b0100_0000
左移7
4'b0000
4'b0110
4'b0010
8'b1000_0000
加3
4'b0000
4'b1001
4'b0010
8'b1000_0000
左移8
4'b0001
4'b0010
4'b0101
8'b0000_0000
可以看到,最终结果为 12'b0001_0010_0101。按照8421BCD码解析,即为125。
之前的联系不是说,大于9嘛?其实这只是一个简单的运算前后顺序关系。
BCD码是4位二进制数表示一个十进制数的1位,如果大于等于5,比如5,4'b0101,下一次移位后变成了4’b1010,而BCD码中是没有4’b1010的,所以要加6,向高位进位。(见联系)
所以移位后加6和移位前加3都是可以的。
module shift(i_data, o_data);
input wire [19:0] i_data;
output wire [19:0] o_data;
wire [19:0] shift_data;
assign shift_data[19:16] = i_data[19:16] > 4'd4 ? i_data[19:16] + 4'd3 : i_data[19:16];
assign shift_data[15:12] = i_data[15:12] > 4'd4 ? i_data[15:12] + 4'd3 : i_data[15:12];
assign shift_data[11:8] = i_data[11:8] > 4'd4 ? i_data[11:8] + 4'd3 : i_data[11:8];
assign shift_data[7:0] = i_data[7:0];
assign o_data = shift_data << 1'b1;
endmodule
module bin2bcd(bin, bcd);
input wire [7:0] bin;
output wire [11:0] bcd;
wire [19:0] w_0;
wire [19:0] w_1;
wire [19:0] w_2;
wire [19:0] w_3;
wire [19:0] w_4;
wire [19:0] w_5;
wire [19:0] w_6;
wire [19:0] w_7;
shift shift_ins0 (.i_data({12'd0, bin}), .o_data(w_0));
shift shift_ins1 (.i_data(w_0), .o_data(w_1));
shift shift_ins2 (.i_data(w_1), .o_data(w_2));
shift shift_ins3 (.i_data(w_2), .o_data(w_3));
shift shift_ins4 (.i_data(w_3), .o_data(w_4));
shift shift_ins5 (.i_data(w_4), .o_data(w_5));
shift shift_ins6 (.i_data(w_5), .o_data(w_6));
shift shift_ins7 (.i_data(w_6), .o_data(w_7));
assign bcd = w_7[19:8];
endmodule
module BinaryToBCD(
input wire [16-1:0] inData, //二进制输入
output wire [16+3:0] outData //BCD输出
);
parameter bit_binary = 16; //二进制数据位数
reg [bit_binary-1:0] bin;
reg [bit_binary+3:0] ShiftReg;
always@(inData)
begin
bin = inData;
ShiftReg = 'd0;
repeat (bit_binary - 1)
begin
ShiftReg[0] = bin[bit_binary-1];
//adjust by add 3
if(ShiftReg[19:16] > 4)
ShiftReg[19:16] = ShiftReg[19:16] + 2'd3;
else
ShiftReg[19:16] = ShiftReg[19:16];
if(ShiftReg[15:12] > 4)
ShiftReg[15:12] = ShiftReg[15:12] + 2'd3;
else
ShiftReg[15:12] = ShiftReg[15:12];
if(ShiftReg[11:8] > 4)
ShiftReg[11:8] = ShiftReg[11:8] + 2'd3;
else
ShiftReg[11:8] = ShiftReg[11:8];
if(ShiftReg[7:4] > 4)
ShiftReg[7:4] = ShiftReg[7:4] + 2'd3;
else
ShiftReg[7:4] = ShiftReg[7:4];
if(ShiftReg[3:0] > 4)
ShiftReg[3:0] = ShiftReg[3:0] + 2'd3;
else
ShiftReg[3:0] = ShiftReg[3:0];
ShiftReg = ShiftReg << 1;
bin = bin << 1;
end
ShiftReg[0] = bin[bit_binary-1];
end
assign outData = ShiftReg;
endmodule
[1] https://blog.51cto.com/u_15076212/3816404 "基于FPGA的二进制转BCD设计与实现(移位加3法)"
[2] https://zhuanlan.zhihu.com/p/209083141 "[走近FPGA]之二进制转BCD码"
手机扫一扫
移动阅读更方便
你可能感兴趣的文章