二进制转换成BCD的原理与verilog实现 --加3左移

二进制转换成BCD的原理与verilog实现 --加3左移

FPGA中的lcd显示、串口收发等应用会涉及到二进制和BCD码之间的转换,常见的有3种方法:除法取模运算、查找表、加3左移。 大位宽下,取模除法运算耗费大量lut资源,查找表也不方便,常用一种加3左移的方法。

加3左移相当于左移后再加6,基本过程有很多人描述过了,可以参考下面的博客,其过程介绍得很清楚。
https://www.cnblogs.com/SummerSunnyDay/p/5013835.html
在这里插入图片描述

我这里着重补充一下为什么通过这种有条件的移位就能转换,其实可以追溯到10进制转换成二进制的原理----除二取余法,二进制转换成BCD可以认为是类似于除二取余的逆运算,即从下往上进行,但要加上BCD中的逢10进6问题,这里需要好好体会一下。
除二取余
逆向运算,按照这种乘2加余,一定可以把一个二进制恢复成10进制数,问题的关键是存放个、十、百位的位置受BCD码规则需要进行变动。

verilog例程:32bit bin – 40bit bcd

//可综合转换代码
module BCD(
    input               clk,
    input               rstn,
    input       [31:0]  data_bin,
    output  reg [39:0]  data_bcd,
    output  reg         valid 
);

reg[71:0] data_shift;
reg[7:0] cnt;

always @(posedge clk ) begin
    if (!rstn) begin
        cnt <= 0;
    end
    else begin
        if(cnt >= 65)
            cnt <= 0;
        else
            cnt <= cnt +1;
    end
end

always @(posedge clk) begin
    if (!rstn) begin
        valid <= 0;
        data_bcd <= 0;
        data_shift <= 0;
    end    
    else begin
        if(cnt==0) begin
            valid <= 0;       
            data_shift <= data_bin;     //0 缓存数值
        end
        else if(cnt <= 64) begin        //1-64 移位转换
            if (cnt[0]) begin           //1 3 5 7 63
                data_shift[71:32] = MoreFourAddThree(data_shift[71:32]);
            end
            else begin
                data_shift = data_shift << 1;
            end
        end
        else if(cnt == 65) begin        //转换结束,输出
            valid <= 1'b1;
            data_bcd <= data_shift[71:32];
        end
    end
end


function [39:0] MoreFourAddThree (input [39:0] a);
begin
    MoreFourAddThree[ 3: 0] = a[ 3: 0]> 4'd4 ? a[ 3: 0]+ 4'd3 : a[ 3: 0];
    MoreFourAddThree[ 7: 4] = a[ 7: 4]> 4'd4 ? a[ 7: 4]+ 4'd3 : a[ 7: 4];
    MoreFourAddThree[11: 8] = a[11: 8]> 4'd4 ? a[11: 8]+ 4'd3 : a[11: 8];
    MoreFourAddThree[15:12] = a[15:12]> 4'd4 ? a[15:12]+ 4'd3 : a[15:12];
    MoreFourAddThree[19:16] = a[19:16]> 4'd4 ? a[19:16]+ 4'd3 : a[19:16];
    MoreFourAddThree[23:20] = a[23:20]> 4'd4 ? a[23:20]+ 4'd3 : a[23:20];
    MoreFourAddThree[27:24] = a[27:24]> 4'd4 ? a[27:24]+ 4'd3 : a[27:24];
    MoreFourAddThree[31:28] = a[31:28]> 4'd4 ? a[31:28]+ 4'd3 : a[31:28];
    MoreFourAddThree[35:32] = a[35:32]> 4'd4 ? a[35:32]+ 4'd3 : a[35:32];
    MoreFourAddThree[39:36] = a[39:36]> 4'd4 ? a[39:36]+ 4'd3 : a[39:36];        
end
endfunction

endmodule

测试testbench:

`timescale 1ns/1ns 

module tb_BCD (

);

reg clk,rstn;
wire valid;
reg[31:0] data_bin;
wire[39:0] data_bcd;

BCD u_BCD(
    .clk        (clk      ),
    .rstn       (rstn     ),
    .data_bin   (data_bin ),
    .data_bcd   (data_bcd ),
    .valid      (valid    )
);

initial begin
    rstn = 0;
    #10
    rstn = 1;
end

initial begin
     clk = 0;
     forever begin
        #1 clk = !clk;
     end
end

initial begin
    data_bin = 0;
    #200    
        data_bin = 32'd1234567890;
    #200    
        data_bin = 32'd1111111111;
    #200    
        data_bin = 32'd1999999999;    

end

endmodule

以及modelsim do脚本:

quit -sim
vlib work
vmap work work
vlog -work work tb_BCD.v
vsim -voptargs=+acc work.tb_BCD

#-decimal
#-hex

add wave  -color Green -height 20 /tb_BCD/clk
add wave  -color Green -height 20 /tb_BCD/rstn

add wave  -color Green -height 20 -Radix decimal  /tb_BCD/u_BCD/cnt
add wave  -color Green -height 20 /tb_BCD/valid

add wave  -color Green -height 20 -Radix decimal  /tb_BCD/data_bin
add wave  -color Green -height 20 -Radix hex  /tb_BCD/data_bcd
add wave  -color Green -height 20 -Radix hex  /tb_BCD/u_BCD/data_shift


run 1000ns

仿真测试结果:
在这里插入图片描述
可以看到:32bit的二进制数(10进制显示),分散到了40bit的hex中,延时65个时钟周期

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值