FPGA系统性学习笔记连载_Day14【BCD转二进制、二进制转BCD】 【原理及verilog仿真】

2021-04-07 11:48:33 浏览数 (1)

FPGA系统性学习笔记连载_Day14【BCD转二进制、二进制转BCD】 【原理及verilog仿真】

本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。

连载《叁芯智能fpga设计与研发-第14天》 【BCD转二进制、二进制转BCD】 【原理及verilog仿真】

原创作者:紫枫术河 转载请联系群主授权,否则追究责任

本篇文章,记录BCD转二进制、二进制转BCD的原理,及verilog代码仿真

一、BCD转二进制

BCD码:俗称8421码,意思是用4bit来表示一个10进制数,注意这个4bit表示的数据范围是 0-9;

我做一个表格,来展示,10进制数和BCD码之间的关系

从图中可以看出来,一个十进制数,是用4bit 二进制数来表示的,且每个十进制数 A = 2^3 2^2 2^1 2^0来计算。

1.1、如果我们要将一个189,表示为BCD码就是 0001_1000_1001,可以看出189占据12bit,每个数占4bit

1.2、将BCD189,用二进制表示只需要8bit,2^8 = 256

1.3、所以我们定义BCD为12bit,这样就可以做0-255之间的BCD转二进制实验了。

1.4、下面我做了一个图来表示BCD189 转换为二进制的过程

1.5、verilog代码实现

代码语言:javascript复制
module bcd_to_bin(
    input   [11:0]      bcd,
    output  [7:0]           bin
);
 
    wire    [3:0]       a;
    wire    [3:0]       b;
    wire    [3:0]       c;
     
    wire  [9:0]     a_r;
    wire  [6:0]     b_r;   
 
    wire  [9:0]     bin_temp;      
     
    assign a = bcd[11:8];
    assign b = bcd[7:4];
    assign c = bcd[3:0];   
     
    //百位=1*100=1*(64 32 4)
    assign a_r = (a <<6)   (a <<5)   (a<<2);
    //十位=1*10=1*(8 2)
    assign b_r = (b<<3)   (b<<1);
     
    assign bin_temp = a_r b_r c;
    assign bin       = bin_temp[7:0];
     
endmodule

1.6、仿真文件

代码语言:javascript复制
`timescale 1ns/1ps
 
module bcd_to_bin_tb;
 
    reg     [11:0]      bcd;
    wire    [7:0]           bin;
 
    reg clk;
     
    reg [3:0]   a;
    reg [3:0]   b;
    reg [3:0]   c;
     
    initial begin
        repeat(20000)begin
            a = {$random}%3;
            b = {$random};
            c = {$random};  
             
            if((a*100 b*10 c)>255)begin
                b = 5;
                c = 5;
            end
            bcd = {a,b,c};
            #50;
        end
    end
     
    bcd_to_bin bcd_to_bin_inst(
        .bcd    (bcd),
        .bin    (bin)
    );
 
endmodule

1.7、仿真效果

仿真结果正确。

二、2进制转BCD

2进制转BCD:因为在FPGA中,我们使用除法器和乘法器会非常占资源,为了节省PFGA的逻辑资源,我们需要

设计一个算法来实现2进制到BCD的高效转换,这个算法就是大四加三算法。

1.1、大四加三算法过程,这里展示二进制178(1011_0010)转换为BCD178(0001_0111_1000)码的过程

从图中可以看出来,二进制转BCD码大四加三算法,需要进行8次判断当前BCD码是否大于4,如果大于4,进行加3,

然后才能左移,注意:左移一定要在判断之后,否则转换错误

1.2、verilog代码实现

这个代码我分为bin_to_bcd.v、cmp.v、left_shift.v

1.3、bin_to_bcd.v

代码语言:javascript复制
module bin_to_bcd(
        input   [7:0]   data,
        output  [11:0]  bcd
);
 
    wire    [19:0] data_temp1;
    wire    [19:0] data_temp2;
    wire    [19:0] data_temp3;
    wire    [19:0] data_temp4;
    wire    [19:0] data_temp5;
    wire    [19:0] data_temp6;
    wire    [19:0] data_temp7;
    wire    [19:0] data_temp8; 
    wire    [19:0] data_temp9; 
     
    assign data_temp1 = {12'd0,data};
     
     
    left_shift  left_shift_inst_1(
        .data_in        (data_temp1),
        .data_out   (data_temp2)
    );
     
    left_shift  left_shift_inst_2(
        .data_in        (data_temp2),
        .data_out   (data_temp3)
    );
     
    left_shift  left_shift_inst_3(
        .data_in        (data_temp3),
        .data_out   (data_temp4)
    );
     
    left_shift  left_shift_inst_4(
        .data_in        (data_temp4),
        .data_out   (data_temp5)
    );
     
    left_shift  left_shift_inst_5(
        .data_in        (data_temp5),
        .data_out   (data_temp6)
    );
     
    left_shift  left_shift_inst_6(
        .data_in        (data_temp6),
        .data_out   (data_temp7)
    );
     
    left_shift  left_shift_inst_7(
        .data_in        (data_temp7),
        .data_out   (data_temp8)
    );
     
    left_shift  left_shift_inst_8(
        .data_in        (data_temp8),
        .data_out   (data_temp9)
    );
 
    assign bcd = data_temp9[19:8];
     
endmodule

1.4、cmp.v

代码语言:javascript复制
module cmp(
        input   [3:0]   data_in,
        output  [3:0]       data_out
);
 
    assign data_out = (data_in > 4'd4) ?(data_in   3'd3):data_in;
 
endmodule

1.5、left_shift.v

代码语言:javascript复制
module left_shift(
        input   [19:0]  data_in,
        output  [19:0]  data_out
);
 
    wire [3:0]  a;
    wire [3:0]  b;
    wire [3:0]  c;
     
    cmp cmp_inst1(
        .data_in        (data_in[19:16]),
        .data_out   (a)
    );
     
    cmp cmp_inst2(
        .data_in        (data_in[15:12]),
        .data_out   (b)
    );
         
    cmp cmp_inst3(
        .data_in        (data_in[11:8]),
        .data_out   (c)
    );
     
    assign data_out = {a[2:0],b,c,data_in[7:0],1'b0};
 
endmodule

1.6、仿真脚本

代码语言:javascript复制
`timescale 1ns/1ps
 
module bin_to_bcd_tb;
 
    reg                     clk;
    reg     [7:0]       data;
    wire    [11:0]      bcd;
 
    initial begin
        clk = 0;
        repeat(20)begin
            data={$random}%6;
            #20;
        end
    end
 
    bin_to_bcd bin_to_bcd_inst(
        .data       (data),
        .bcd        (bcd)
    );
 
    always #10 clk = ~clk;
     
endmodule

1.7、仿真结果

仿真结果正确。

【QQ交流群】

群号:173560979,进群暗语:FPGA技术江湖粉丝。

多年的FPGA企业开发经验,各种通俗易懂的学习资料以及学习方法,浓厚的交流学习氛围,QQ群目前已有1000多名志同道合的小伙伴,无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有。

【微信交流群】

现微信交流群已建立09群,人数已达数千人,欢迎关注“FPGA技术江湖”微信公众号,可获取进群方式。

后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!

0 人点赞