BCD 码(Binary-Coded Decimal
),又称二---
十进制码,使用
4
位二进制数来表示
1
位十进制数中的 0~9
这
10
个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。
BCD码根据权值的有无可分为“有权码”和“无权码”。其中的权字表示的是权值,有权码的四位二进制数中的每一位都有一个固定的权值,而无权码是没有权值的。常见的有权码有8421
码
5421
码和
2421
码,
8421
码它的权值从左到右是
8421
,
5421
码的权值从左到右是5421
,
2421
码的权值是
2421
,其中
8421
码是最为常用的
BCD
编码。常用的无权码有余3
码、余
3
循环码,还有格雷码。各编码方式所对应的十进制数如下图所示。

十进制数对应的BCD码
那么如何用 BCD 码来表示我们的十进制数呢?以本次实验我们使用的 8421BCD 编码为例,比如说十进制数 5,它的 8421BCD 码为 0101,那么我们怎么通过 0101 得到我们的数字 5 呢,这里需要用到一个算法,就是将其每位二进制数乘以它的权值然后相加。十进制 5 的 8421BCD 码为0101,即:1×1 + 0×2 + 1×4+ 0×8 = 5。其它有权码也是这种计算方式,而无权码的计算方式这里就不过多讲解了,感兴趣的读者可自行查找相关资料进行了解。
我们以234为例子,讲解二进制编码如何转化为8421BCD码。
我们先看看 234
的十进制数的二进制表示为:1110_1010
;
234
的
8421BCD
码为:
0010_0011_0100
二进制转BCD码步骤
如上图所示,十进制数 234
其对应的二进制数为
1110_1010
,首先第一步我们在其前面补上若干个 0
,那么这个
0
的数量是如何决定的呢?参与转换的十进制有多少位,就需要多少个相应的 BCD
码,比如
234
,该十进制数是
3
位,而一位十进制数的
BCD
码是四位,所以这里我们就需要 12
位
BCD
码,故我们就在前面补
12
个
0
。其余位数的十进制补0 数量也是这样进行计算。
第二步我们需要进行判断运算移位操作,首先判断每一个 BCD
码其对应的十进制数是否大于 4,如果大于
4
就对
BCD
码做加
3
操作,若小于等于
4
就让其值保持不变。当对每一个 BCD
码进行判断运算后,都需要将运算后的数据像左移
1
位。移完位后我们仍按前面所述进行判断运算,判断运算后需再次移位,以此循环,当我们进行 8
次判断移位后的BCD 吗部分数据就是我们转换的数据,如图
26-6
所示,当第
8
次移位后的
8421BCD 码数
据对应的十进制正是 234
。这里需要注意的是我们输入转换的二进制码有多少位我们就需要进行多少次判断移位操作,这里输入的是 8
位二进制,我们就进行
8
次判断移位操作。
模块框图

代码的输入输出信号描述
输入信号中的时钟复位这里就不过多讲解了,首先是 data
信号,该信号是输入的需要
转换的二进制表示的十进制数,该信号由数据生成模块传来。
cnt_shift:移位判断计数器,前面我们说到我们输入转换的二进制码有多少位我们就需要进行多少次判断移位操作,这里我们 data
数据的位宽为
20
位,所以这里我们声明移位判断计数器对移位 20
次进行判断控制。
data_shift:移位判断数据寄存器,该寄存器用于存储移位判断操作过程中的数据,这里我们输入的二进制位宽为 20
位,待转换成的
BCD
码位宽为
24
位,所以这里我们声明该寄存器的位宽为 44
位。根据波形图可知,这里我们设计当移位计数器等于
0
时寄存器的低20 位即为待转换数据,而由于还没开始进行转换,高
24
位的
BCD
码我们补
0
即可。
shift_flag:移位判断操作标志信号。前面说到我们需要对数据进行移位和判断,判断在前移位在后,所以这里我们声明一个标志信号,用于控制判断和移位的先后顺序,当shift_flag 为低时对数据进行判断,当 shift_flag
为高时对数据进行移位。需要注意的是无论 是移位操作和判断操作都是在单个系统时钟下完成的,故我们判断 20
次移位
20
次在
40
个系统时钟内就能完成。
//16进制转8421模块
module bcd_8421
(
input wire sys_clk, //系统时钟
input wire sys_rst_n, //复位信号
input wire [19:0] data, //输入需要转换的数据
output reg [3:0] unit, //个位BCD码
output reg [3:0] ten, //十位BCD码
output reg [3:0] hun, //百位BCD码
output reg [3:0] tho, //千位BCD码
output reg [3:0] t_tho, //万位BCD码
output reg [3:0] h_hun //十万位BCD码
);
reg [4:0] cnt_shift; //移位判断计数器
reg [43:0] data_shift; //移位判断数据寄存器
reg shift_flag; //移位判断标志信号
//cnt_shift:从0~21循环计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_shift <= 5'd0;
else if((cnt_shift == 5'd21) && (shift_flag == 1'b1))
cnt_shift <= 1'b0;
else if(shift_flag == 1'b1)
cnt_shift <= cnt_shift + 1'b1;
else
cnt_shift <= cnt_shift;
//data_shift:计数器为 0 时赋初值,计数器为 1~20 时进行移位判断操作
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_shift <= 44'b0;
else if(cnt_shift == 5'd0)
data_shift <= {24'b0,data};
else if((cnt_shift <= 20) && (shift_flag == 1'b0))
begin
data_shift[23:20] <= (data_shift[23:20] > 4) ?
(data_shift[23:20] + 2'd3) : (data_shift[23:20]);
data_shift[27:24] <= (data_shift[27:24] > 4) ?
(data_shift[27:24] + 2'd3) : (data_shift[27:24]);
data_shift[31:28] <= (data_shift[31:28] > 4) ?
(data_shift[31:28] + 2'd3) : (data_shift[31:28]);
data_shift[35:32] <= (data_shift[35:32] > 4) ?
(data_shift[35:32] + 2'd3) : (data_shift[35:32]);
data_shift[39:36] <= (data_shift[39:36] > 4) ?
(data_shift[39:36] + 2'd3) : (data_shift[39:36]);
data_shift[43:40] <= (data_shift[43:40] > 4) ?
(data_shift[43:40] + 2'd3) : (data_shift[43:40]);
end
else if((cnt_shift <= 20) && (shift_flag == 1'b1))
data_shift <= data_shift << 1;
else
data_shift <= data_shift;
//shift_flag:移位判断标志信号,用于控制移位判断的先后顺序
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
shift_flag <= 1'b0;
else
shift_flag <= ~shift_flag;
//当计数器等于 20 时,移位判断操作完成,对各个位数的 BCD 码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
unit <= 4'b0;
ten <= 4'b0;
hun <= 4'b0;
tho <= 4'b0;
t_tho <= 4'b0;
h_hun <= 4'b0;
end
else if(cnt_shift == 5'd21)
begin
unit <= data_shift[23:20];
ten <= data_shift[27:24];
hun <= data_shift[31:28];
tho <= data_shift[35:32];
t_tho <= data_shift[39:36];
h_hun <= data_shift[43:40];
end
endmodule
unit、
ten
、
hum
、
tho
、
t_tho
、
h_hun
:六路
BCD
码,前面我们说到我们开发板上有六位数码管,故可以显示的最大值是六位十进制数,随意这里我们声明了六路 BCD
码,一个BCD 码代表十进制的一个位数,其中
unit
代表个位、
ten
代表十位、
hun
代表百位、
tho
代表千位、t_tho
代表万位、
h_hun
代表十万位。当我们的移位判断计数器等于
21
是说明
20位二进制转 BCD
码的移位判断操作已经完成,此时
data_shift
里寄存的数据就是转换的的
寄存数据,该数据的高 24
位即转换完成后的
BCD
码。所以当
cnt_shift
等于
20
是就将寄存的 BCD
码值赋值为相对应的各个位数。