zoukankan      html  css  js  c++  java
  • 基于FPGA的二进制转BCD

    BCD码(nary-Coded Decimal‎)又称二-十进制代码,亦称二进码十进数。是一种二进制的数字编码形式,用二进制编码的十进制代码。这种编码形式利用了四个位元来储存一个十进制的数码。

    在数字电路中,没有特殊说明的数码都是顺序编码的二进制。转换为BCD码,也就是将顺序编码的二进制数字的个位、十位、百位等计算出来,用四位二进制表示,组合到一起就是BCD码。

    将一个数字对10求余将得到个位。

    将一个数字减去个位后,除以10,然后在对10求余将得到十位。由于在FPGA内部,正数除法不会保留小数,所以可以直接除以10,而不用减去个位。

    将一个数字除以100,然后对10求余得到百位。

    首先设计一个8位的二进制转成BCD码。8位的二进制能够表示最大的数字为255,共有三个BCD码,输出共有12位。

    此模块命名为bin2bcd,bin为二进制输入,bcd为BCD码输出。

     设计代码如下:

    module bin2bcd (

      input   wire    [7:0]     bin,

      output  wire    [11:0]    bcd

    );

      assign bcd[3:0] = bin%10;

      assign bcd[7:4] = (bin/10)%10;

      assign bcd[11:8] = (bin/100)%10;

    endmodule

    在testbench中,可以利用随机数给出几个数值。

    `timescale 1ns/1ps

    module bin2bcd_tb;

      reg     [7:0]     bin;

      wire    [11:0]    bcd;

      bin2bcd bin2bcd_inst(

          .bin        (bin),

         

          .bcd        (bcd)

        );

      initial begin

        repeat (10) begin

          bin = {$random} % 256;

          # 20;

        end

      end

    endmodule

    在modelsim中,将bin设置为符号位,将bcd设置为十六进制。十六进制也是4个二进制码组成一个,只不过BCD码中只有0到9,而十六进制中还有A到F。

    通过RTL仿真图可以看出,bin和bcd的数字是相同的。

    在此设计代码中只有三行,但是涉及到了除法器和求余器(也可以认为是除法器),利用了较多的资源。

    为了减少资源使用,使得延迟更小,二进制转BCD还有其他的办法。

    首先分析两个BCD数码的相加。

          0101  0010

    +    0010  0110

          0111  1000

    在上述BCD码加法中,52+26最终结果等于78,结果没有任何错误。

             0101  1001

        +   0010  0010

             0111  1011

    在上述BCD码加法中,59+22最终结果等于7B,很明显出现了不属于BCD码中的数字。BCD码是用来表示十进制数字的,顺序编码时表示二进制的,当四个组到一起时,变为十六进制,当BCD码算完的结果中有大于9的数码,可以进行加六调整。加上六后,就会得到正确的进位和本位值。

    当结果为1011(B)时,加上0110(6),本位结果为0001,进位为0001。

    0111 1011(7B)调整后,为1000 0001(81),结果正确。

    上面是分析的是两个不同的BCD码相加,下面分析两个相同的BCD码相加(最终结果不用调整时),相同的两个数字相加,可以用左移表示。

                0010   0011

         +    0010   0011

               0100   0110

    两个相同的BCD码相加(最终结果需要调整时),就需要加六调整了。

      

          0010   0111

    +    0010   0111

          0100   1110

    上述结果就需要加六调整了,因为最终结果中出现了比9大的数字。因为是两个相同的数字相加,当数字大于4后,两个相同的数字相加就会大于9,此时就需要加6调整。

    当数字大于4,先加上3,此时把两个相同的结果进行相加,就实现了加之后的结果大于9,然后再加六。这两种方法是一样的。

    当数字大于4,先加上3,然后进行移位。和先加,判断结果是不是大于9,然后再加6是相等的。

    由于是相等的两个数字相加,末位肯定为0 。那么两个相同的BCD相加,再和一个1bit的数字相加,就可以认为是当数字大于4,先加上3,然后进行移位,把最后移位出来的0直接换成最后加的1bit数字即可,将上述操作定义为操作X。

    当了解了上述结论后,下面分析,利用上述结论实现二进制转BCD。

    任何一个二进制码都可以写成本位的数字乘以本位的权重的累加和。

    将一个7位的二进制数据转为BCD,首先认为是两个都为0的bcd码相加,然后加上7位数据的最高位。

    上述的结果就是最高位转换为BCD码的结果,它的权重应该是2的6次幂,但是现在是2的0次幂。

    然后将上述的结果和数据的次高位进行操作X,那么此时数据的最高位的权重变为2的1次幂,次高位的权重变为2的0次幂,结果为最高位和次高位的BCD码。

    依次类推,将八位数据全部进行操作X后,各个数据位都是自己的权重,并且结果就是BCD码。

    在操作X中,为了方便将1bit的数据去替换结果的最后一位,可以将1bit放在调整好的数据的后面,直接移位进去即可。

    在图中,经历了7 次的操作X。如果我们可以把操作X设计出来,然后级联7个即可得到正确结果。

    操作X的输入为前面的BCD码和后面的二进制(可以将这两组合到一起)。

    操作X为调整和移位,后面用调整和移位来表示。

    为了能够对比两种二进制转BCD(除法求余和调整移位),下面利用调整和移位的方法实现8位二进制转BCD。

    输入是八位,就需要进行八次的调整和移位。由于每次调整和移位的操作是完全相同的,所以将调整和移位做成一个模块。

    该模块命名为adjust_shift,输入为BCD码的位数加上二进制的位数等于20位,输出也是20位。

    module adjust_shift (

        

         input       wire        [19:0]      idata,

        

         output         wire  [19:0]      odata     

    );

         wire                  [19:0]      adjust_data;

        

         assign adjust_data[19:16] = idata[19:16] > 4'd4 ? idata[19:16] + 4'd3 : idata[19:16];

         assign adjust_data[15:12] = idata[15:12] > 4'd4 ? idata[15:12] + 4'd3 : idata[15:12];

         assign adjust_data[11:8] = idata[11:8] > 4'd4 ? idata[11:8] + 4'd3 : idata[11:8];

         assign adjust_data[7:0] = idata[7:0];

         assign odata = adjust_data << 1'b1;

    endmodule

    当调整移位设计做完之后,我们只需要级联八个就可以得到结果。第一个输入时,高位(BCD)要输入为0;最后一个输出时,高位(BCD)才是输出。

    module bintobcd (

        

         input       wire                  [7:0]       bin,

        

         output       wire                 [11:0] bcd

    );

         wire             [19:0] adjust_shift_data_0;

         wire             [19:0] adjust_shift_data_1;

         wire             [19:0] adjust_shift_data_2;

         wire             [19:0] adjust_shift_data_3;

         wire             [19:0] adjust_shift_data_4;

         wire             [19:0] adjust_shift_data_5;

         wire             [19:0] adjust_shift_data_6;

         wire             [19:0] adjust_shift_data_7;

        

         adjust_shift  adjust_shift_inst0 (.idata({12’d0,bin}),.odata(adjust_shift_data_0));

         adjust_shift  adjust_shift_inst1 (.idata(adjust_shift_data_0),.odata(adjust_shift_data_1));

         adjust_shift  adjust_shift_inst2 (.idata(adjust_shift_data_1),.odata(adjust_shift_data_2));

         adjust_shift  adjust_shift_inst3 (.idata(adjust_shift_data_2),.odata(adjust_shift_data_3));

         adjust_shift  adjust_shift_inst4 (.idata(adjust_shift_data_3),.odata(adjust_shift_data_4));

         adjust_shift  adjust_shift_inst5 (.idata(adjust_shift_data_4),.odata(adjust_shift_data_5));

         adjust_shift  adjust_shift_inst6 (.idata(adjust_shift_data_5),.odata(adjust_shift_data_6));

         adjust_shift  adjust_shift_inst7 (.idata(adjust_shift_data_6),.odata(adjust_shift_data_7));

        

         assign bcd = adjust_shift_data_7[19:8];

    endmodule

    第一级输入时,采用位拼接的方式。

    编写testbench后,经过RTL仿真验证,结果都是正确的。 在达到相同功能的前提下,调整和移位的方式实现的设计,资源利用如下:

    在达到相同的功能下,一个是164,一个是29,对比结果很明显。

    设计者:郝旭帅         QQ:746833924     QQ交流群: 173560979 

  • 相关阅读:
    Group_concat介绍与例子
    国家大学科技园名单
    shell截取第五行第三列
    (Deep) Neural Networks (Deep Learning) , NLP and Text Mining
    28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架
    SpeeDO —— 并行深度学习系统
    BrandZ:2016年全球最具价值品牌百强榜(完整报告)
    jdk1.7升级到jdk1.8后出错: [ERROR] javadoc: warning
    伪基站收集方圆500至1000米范围内的手机卡信息,并且通过伪基站设备伪装成银行、中国移动、中国联通等任意号码向手机用户发送短信或拨打电话
    360手机助手内部资料曝光,63张PPT纯干货
  • 原文地址:https://www.cnblogs.com/fendoudexiaohai/p/13151892.html
Copyright © 2011-2022 走看看