基础知识:
BCD:BCD码又称为8421码,
意义:之所以有时候需要将binary转换为BCD,一般是用在本科的实验中,为了将binary显示在数码管中,当然还有很多应用,只是目前我还没有用到。
转换算法:左移加3法
移位加3法的具体原理,在网上感觉也没有人能够说的清楚,以后找到书籍再说吧。下面解释下左移加三算法。这里以8bit二进制数FF做例子。

该算法的操作为上图。下面对上图的操作进行详细的解释:
由于8bit的二进制最大为FF,转换为十进制为255。所以需要使用三个BCD码来表示所有的8bit二进制数。上图的hundreds表示百位的BCD,tens表示十位的BCD,Units表示个位的BCD。算法的操作为一直将binary数据左移,移出的数据按顺序存在hundreds,tens,Units。例如上面的shift1,shift2,shift3操作后,Units变为了0111,至于为何在shift3后进行add3操作,是因为在算法中每一次左移,都要对hundreds,tens和Units进行判断,如果hundreds,tens和Units里面的值大于或等于5,就将hundreds,tens和Units自加3.所以shift3后,Units里面为0111,表示为7,此时不能左移,而是对Units加三操作,所以Units的值从0111变为了1010.值得注意的是,只要hundreds,tens和Units中任意一个的值大于或等于5(0101),就要先进行一次自加三的操作,然后才能继续左移,后面的操作同上。
注意2:n位的binary就需要进行n次左移
注意3:最后一次左移不需要进行add3操作
注意4 : 亲自推导16位的,和24位的binary转换,结果正确,所以该算法适用于任意位binary
toBCD,当然这种论断没有足够的理论依据。
verilog代码:
说明:对于8bit及以下的binary,可以使用case语句实现移位加三算法。由于这里说明的是任意位的二进制数,转为BCD,所以我的代码中设计了一个状态机,来控制移位,加三和结束操作。由于代码编写时间仓促,其中或许有些bug。
//name: 二进制转BCD
//data: 2014-04-17 at kb129
//info: as 2**8=255 change to BCD then this need 3 times of “8421”
module b_to_bcd(
clk,
rst_n,
binary,
state_en,
BCD
);
parameter b_length = 8;
parameter bcd_len = 12;
parameter idle = 5'b00001;
parameter shift = 5'b00010;
parameter wait_judge = 5'b00100;
parameter judge = 5'b01000;
parameter add_3 = 5'b10000;
input clk;
input rst_n;
input [b_length-1:0] binary;
inputstate_en;
output reg[bcd_len-1:0] BCD;
reg [b_length-1:0] reg_binary;
reg [3:0] bcd_b, bcd_t, bcd_h;
reg [3:0] shift_time;
reg [5:0] c_state, n_state;
regadd3_en;
regchange_done;
//this is a three section kind of state code style
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
c_state <= idle;
else
c_state <= n_state;
end
//the second section
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
c_state <= idle;
else
case(n_state)
idle:begin
if((binary!=0)&&(state_en==1'b1)&&(change_done==0'b0))
n_state <= shift;
else
n_state <= idle;
end
shift: n_state <= wait_judge;
wait_judge: begin
if(change_done==1'b1)
n_state <= idle;
else
n_state <= judge;
end
judge:begin
if(add3_en)
n_state <= add_3;
else
n_state <= shift;
end
add_3:begin
n_state <= shift;
end
default: n_state <= idle;
endcase
end
//the third section
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
shift_time <= 4'b0;
change_done <= 1'b0;
add3_en<= 1'b0;
end
else
case(n_state)
idle:begin
shift_time <= b_length;
reg_binary <= binary;
bcd_h <= 4'b0;
bcd_t <= 4'b0;
bcd_b <= 4'b0;
end
shift:begin
{bcd_h,bcd_t,bcd_b,reg_binary} <= {bcd_h,bcd_t,bcd_b,reg_binary}<<1;
shift_time <= shift_time-1;
if(shift_time==1) change_done <= 1'b1;
else change_done <= 1'b0;
end
wait_judge:begin
if((bcd_h>=4'd5)||(bcd_t>=4'd5)||(bcd_b>=4'd5))
add3_en <= 1;
else
add3_en <= 0;
if(change_done==1) BCD <= {bcd_h,bcd_t,bcd_b};
end
judge: add3_en <= 0;
add_3: begin
if(bcd_h>=4'd5) bcd_h <= bcd_h + 4'b0011; else bcd_h <= bcd_h;
if(bcd_t>=4'd5) bcd_t <= bcd_t + 4'b0011; else bcd_t <= bcd_t;
if(bcd_b>=4'd5) bcd_b <= bcd_b + 4'b0011; else bcd_b <= bcd_b;
end
default: begin
change_done <= 1'b0;
add3_en<= 1'b0;
end
endcase
end
endmodule
代码的仿真:这里对上面的代码进行了仿真,仿真结果显示上面代码可以实现8bitbinary的BCD转换。
testbench:
module filter_tb;
reg clk;
reg rst_n;
reg state_en;
reg [7:0] binary;
wire [11:0]BCD;
initial
begin
clk=0;
rst_n=0;
state_en = 0;
#100 binary = 8'h3f;
#150 rst_n=1;
#200 state_en =1;
end
always #10 clk=~clk;
b_to_bcd u_b_to_bcd
(
.clk(clk),
.rst_n(rst_n),
.binary(binary),
.state_en(state_en),
.BCD(BCD)
);
endmodule
仿真结果:二进制的3f=十进制的63
