精华内容
下载资源
问答
  • 假若A是16位的二进制数字,转换的数学表达式如下:A = 2^15+2^14+.....2^1+2^0在转换的时候,待转换的数是16位(两字节),环路计数器是16次,最大的结果因有65535,所以至少要用2.5字节存结果,取整之后就是3个字节做...

    假若A是16位的二进制数字,转换的数学表达式如下:

    A = 2^15+2^14+.....2^1+2^0

    在转换的时候,待转换的数是16位(两字节),环路计数器是16次,最大的结果因有65535,所以至少要用2.5字节存结果,取整之后就是3个字节做结果储存。

    转换要领如下:结果字节首先清零,

    然后待转换字节与结果字节同时向左移,移出待转换字节的最高位,逢1结果翻一翻,见0结果原封不动,环路计数器减1,重复以上过程,直到环路计数器减到零。

    注:在逢1结果翻一翻中还是加6修正,51中是有直接指令DA,但精简指令内核的MCU

    都没有这条指令,因此处理上就完全不同,可以参考以下代码。看看是用了哪些技巧代替了DA指令。

    -----对于单片机汇编算法的初学者,该如何把转换两字节改成转换多字节?-----

    以下附上来自AVR stduio 自带的bin2 to BCD 例程。

    ;****************************************

    ;* "bin2BCD16" - 16-bit Binary to BCD conversion

    ;*

    ;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit

    ;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0).

    ;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2.

    ;*

    ;* Number of words :25

    ;* Number of cycles :751/768 (Min/Max)

    ;* Low registers used :3 (tBCD0,tBCD1,tBCD2)

    ;* High registers used  :4(fbinL,fbinH,cnt16a,tmp16a)

    ;* Pointers used :Z

    ;*

    ;***************************************************************************

    ;***** Subroutine Register Variables

    .equ   AtBCD0 =13    ;address of tBCD0

    .equ   AtBCD2 =15    ;address of tBCD1

    .def   tBCD0 =r13     ;BCD value digits 1 and 0

    .def   tBCD1 =r14     ;BCD value digits 3 and 2

    .def   tBCD2 =r15     ;BCD value digit 4

    .def   fbinL =r16       ;binary value Low byte

    .def   fbinH =r17       ;binary value High byte

    .def   cnt16a =r18     ;loop counter

    .def   tmp16a =r19    ;temporary value

    ;***** Code

    bin2BCD16:

    ldi     cnt16a,16      ;Init loop counter

    clr     tBCD2           ;clear result (3 bytes)

    clr     tBCD1

    clr     tBCD0

    clr     ZH                ;clear ZH (not needed for AT90Sxx0x)

    bBCDx_1:lsl fbinL    ;shift input value

    rol     fbinH            ;through all bytes

    rol     tBCD0  ;

    rol     tBCD1

    rol     tBCD2

    dec    cnt16a         ;decrement loop counter

    brne   bBCDx_2    ;if counter not zero

    ret   ;   return

    bBCDx_2:  ldi   r30,  AtBCD2+1   ;Z points to result MSB + 1

    bBCDx_3:

    ld     tmp16a,-Z           ;get (Z) with pre-decrement

    ;----------------------------------------------------------------

    ;For AT90Sxx0x, substitute the above line with:

    ;

    ; dec ZL

    ; ld tmp16a,Z

    ;

    ;----------------------------------------------------------------

    subi  tmp16a,-$03   ;add 0x03

    sbrc  tmp16a,3        ;if bit 3 not clear

    st     Z,tmp16a       ; store back

    ld      tmp16a,Z       ;get (Z)

    subi   tmp16a,-$30  ;add 0x30

    sbrc  tmp16a,7        ;if bit 7 not clear

    st     Z,tmp16a        ; store back

    cpi     ZL,AtBCD0     ;done all three?

    brne  bBCDx_3        ;loop again if not

    rjmp  bBCDx_1

    展开全文
  • 1. BCD码的求和BCD码使用4位二进制数来表示十进制中0~9这10个数的数码。例如,十进制的237,其BCD码就是0010_0011_0111,但是其二进制是1110_1101。我们先来研究两个4位的BCD码相加的情况。设这两个BCD码对应的...

    1. BCD码的求和

    BCD码使用4位二进制数来表示十进制中0~9这10个数的数码。例如,十进制的237,其BCD码就是0010_0011_0111,但是其二进制是1110_1101。

    我们先来研究两个4位的BCD码相加的情况。设这两个BCD码对应的十进制是a,b,其中a,b∈{0,1,2,...,9}。此时只有3种情况:

    0≤a+b≤9

    10≤a+b≤15

    16≤a+b≤18

    也就是说:

    对于第一种情况,结果本身就是对应的BCD码。例如,0100+0101=1001,即4+5=9;

    对于第二种情况,其结果对于4位运算来说没有产生进位,但是结果超过了BCD码表示的范围(因为4位BCD码最多表示9)。例如,5+8=13,0101+1000=1101

    对于第三种情况,其结果对于4位运算来说不仅产生了进位,而且其结果也超过了BCD码表示的范围。例如,4+13=17,0100+1101=1_0001

    第一种情况显然不需要再修正。

    第二种情况,例如,5+8=13,我们希望得到BCD码是0001_0011,但是运算结果1101,因此如果我们加上了6,就可以得到正确结果:1101+0110=0001_0011。这是因为,十进制是逢十进一,但是4位BCD加法,在看作是二进制数做加法时,是逢十六进一。因此,如果结果是10≤a+b≤15,加上6以后就是16+0≤a+b+6≤16+5,此时因为逢十六进一的原因,就得到了结果1_0≤[a+b+6]≤1_5,这个结果就是对的。

    第三种情况,因为16≤a+b≤18,逢十六进一后,我们得到了1_0≤[a+b]≤1_2,为了使结果正确,如果我们加上一个修正值6,就得到1_6≤[a+b+6]≤1_8,从而结果也变得正确。

    综上所述,如果两个BCD码相加:

    如果结果小于9,则不做操作

    如果结果大于9,则需要加上6作为修正值

    考虑一个例子,比如 35+99=134。35和99的BCD码分别是0011_0101和1001_1001。先计算低4位:0101+1001=1110,因为这个值大于9,因此加上6作为修正:1110+0110=1_0100。现在计算高四位,同时注意到还有一个进位:0011+1001+0001=1101,这个值还是大于9,加上6,得到1101+0110=1_0011。因此最终结果是1_0011_0100,这刚好就是134的BCD码。

    我们之所以能够安全地加上进位,是因为BCD加法比照的就是十进制的加法,只不过前者是4位为一个单位,而后者是以1位数字作为一个单位。加上修正值后,BCD加法的进位就相当于十进制加法的进位。图示如下:

    42ad12622dc8

    2. 二进制转BCD码

    给定一个二进制数,要转BCD码。一个常用算法就是不断将该数除以10,以此依次分解出个位、十位、百位……上的数字,这些数字的4位二进制数就是对应的BCD。但是这样的算法需要不断做除法操作十分的麻烦。我们可以使用名为加三左移法来完成。

    这个算法基于以下的事实:

    一个数乘以2,相当于其二进制左移1位

    两个BCD码相加,如果结果大于9,需要加上6作为修正

    一个n位二进制数

    math?formula=h%3Db_%7Bn-1%7Db_%7Bn-2%7D%5Cdotsc%20b_0,其展开是

    math?formula=h%3D%5Csum_%7Bi%3D0%7D%5E%7Bn-1%7D%20b_i2%5Ei如果使用秦九韶算法的嵌套形式写法,可以写成:

    math?formula=h%3D2(2(%5Cdotsc(2(2b_%7Bn-1%7D%2Bb_%7Bn-2%7D)%2Bb_%7Bn-3%7D)%5Cdotsc)%2Bb_1)%2Bb_0或者若令

    math?formula=%5Cbegin%7Bcases%7D%20%5Cmathcal%7BH%7D_i%26%3D2%5Cmathcal%7BH%7D_%7Bi%2B1%7D%2Bb_%7Bi%7D%5C%5C%20%5Cmathcal%7BH%7D_%7Bn-1%7D%26%3Db_%7Bn-1%7D%5Cend%7Bcases%7D

    math?formula=h%3D%5Cmathcal%7BH%7D_0如果使用这种形式,我们先计算的是

    math?formula=%5Cmathcal%7BH%7D_%7Bn-1%7D,然后是

    math?formula=%5Cmathcal%7BH%7D_%7Bn-2%7D%3D2%5Cmathcal%7BH%7D_%7Bn-1%7D%2Bb_%7Bn-2%7D,然后是

    math?formula=%5Cmathcal%7BH%7D_%7Bn-3%7D%3D2%5Cmathcal%7BH%7D_%7Bn-2%7D%2Bb_%7Bn-3%7D,……,最后是

    math?formula=%5Cmathcal%7BH%7D_%7B0%7D%3D2%5Cmathcal%7BH%7D_%7B1%7D%2Bb_%7B0%7D

    注意到

    math?formula=2%5Cmathcal%7BH%7D_i就是把

    math?formula=%5Cmathcal%7BH%7D_i左移1位,这样就会在最右边空出一个位,之后再加

    math?formula=b_%7Bi-1%7D就是用

    math?formula=b_%7Bi-1%7D填充这个最低位,从而我们得到了

    math?formula=%5Cmathcal%7BH%7D_%7Bi-1%7D。不断左移,最终就能得到

    math?formula=h,现在我们来设计一个算法使得左移结束后能得到对应的BCD码。

    math?formula=R是一个无限长的、初始状态为所有位都是0的理想寄存器,

    math?formula=h是欲转换的数。我们使用下面的归纳法来构造证明我们通过不断左移最终能够得到存储在

    math?formula=R中的

    math?formula=h对应的BCD码:

    初始:

    math?formula=h左移

    math?formula=b_%7Bn-1%7D进入

    math?formula=R,通过若干运算后,

    math?formula=R中是

    math?formula=%5Cmathcal%7BH%7D_%7Bn-1%7D的BCD码。这个显然是成立的,因为

    math?formula=%5Cmathcal%7BH%7D_%7Bn-1%7D%3Db_%7Bn-1%7D是1位(不是0就是1,对应BCD码就是本身),将其左移进

    math?formula=R后,

    math?formula=R的值立即是

    math?formula=%5Cmathcal%7BH%7D_%7Bn-1%7D的BCD码

    假设:设某一时刻,已经将

    math?formula=b_i左移入

    math?formula=R,通过若干运算后,此时

    math?formula=R中是

    math?formula=%5Cmathcal%7BH%7D_%7Bi%7D的BCD码

    归纳:现在准备移入

    math?formula=b_%7Bi-1%7D,我们希望这个步骤结束后,

    math?formula=R的值是

    math?formula=%5Cmathcal%7BH%7D_%7Bi-1%7D的BCD码。因为此时

    math?formula=R

    math?formula=%5Cmathcal%7BH%7D_%7Bi%7D的BCD码,现在对

    math?formula=R从最低位开始每四位作为一个单位

    math?formula=u,即将

    math?formula=R划分为

    math?formula=R%3D%5Cdotsc%5Cdotsc%20u_%7B2%7Du_%7B1%7Du_%7B0%7D,设

    math?formula=i%3D0,做如下处理:

    如果从

    math?formula=u_i开始之后全部为0,则过程结束

    否则如果

    math?formula=u_i%3C5,则转第4步

    否则,令

    math?formula=u_i%3Du_i%2B3,保留4位

    math?formula=i%3Di%2B1,转第1步

    为什么要加3呢?这是因为如果

    math?formula=u_i%5Cgeqslant%205,那么加法结果要加修正值6,也就是

    math?formula=2u_i%2B6,这等价于

    math?formula=2(u_i%2B3);如果

    math?formula=u_i%3C5,那么加法结果就不需要修正。此外,因为

    math?formula=R目前本身就是BCD码,因此必然

    math?formula=u_i%5Cleqslant9,从而加3不会产生进位。如此处理后,将

    math?formula=R左移一位,也就是乘以2,此时得到的就是

    math?formula=2%5Cmathcal%7BH%7D_%7Bi-1%7D的BCD码。现在,因为乘以2的关系,

    math?formula=R必然是偶数,故而BCD最低位的数值

    math?formula=u_0%5Cleqslant8,于是加上

    math?formula=b_%7Bi-1%7D后有

    math?formula=u_0%2Bb_%7Bi-1%7D%5Cleqslant9。从而,得到的就是

    math?formula=%5Cmathcal%7BH%7D_%7Bi-1%7D正确的BCD码。

    由数学归纳原理,移动len(h)次后,我们最终可以得到

    math?formula=h的BCD码。

    作为一个例子,考虑使用该算法将

    math?formula=134的二进制1000_0110转为BCD码:

    初始:R=..._0000_0000,h=1000_0110(下面使用#作为占位符)

    R中的

    math?formula=u_i均小于5,不做处理。R左移1位,h左移一位进入R:R=..._0000_0001,h=0000_110#

    R中的

    math?formula=u_i均小于5,不做处理。R左移1位,h左移一位进入R:R=..._0000_0010,h=0001_10##

    R中的

    math?formula=u_i均小于5,不做处理。R左移1位,h左移一位进入R:R=..._0000_0100,h=0011_0###

    R中的

    math?formula=u_i均小于5,不做处理。R左移1位,h左移一位进入R:R=..._0000_1000,h=0110_####

    R中的

    math?formula=u_0%3D8%5Cgeqslant5,对其做加3处理得到R=..._0000_1011。R左移1位,h左移一位进入R:R=..._0001_0110,h=110#_####

    R中的

    math?formula=u_0%3D6%5Cgeqslant5,对其做加3处理得到R=..._0001_1001。R左移1位,h左移一位进入R:R=..._0011_0011,h=10##_####

    R中的

    math?formula=u_i均小于5,不做处理。R左移1位,h左移一位进入R:R=..._0110_0111,h=0###_####

    R中的

    math?formula=u_0%3D7%5Cgeqslant5%2Cu_1%3D6%5Cgeqslant5,对其都做加3处理得到R=..._1001_1010。R左移1位,h左移一位进入R:R=..._0001_0011_0100,h=####_####

    现在,

    math?formula=h已经全部移入,此时

    math?formula=R的值就是0001_0011_0100,它就是

    math?formula=134的BCD码。

    C语言的算法如下:

    #include

    #define N 50

    #define DIGITS_NUM 8*sizeof(byte_t)

    typedef char byte_t;

    byte_t regstr[N];

    void resetRegstr(){

    for(int i=0;i

    }

    void show8421bcd(){

    int i=0;

    for(i=0;i

    if(regstr[i]!=0) break;

    }

    if(i==N) {

    printf("0\n");

    return;

    }

    for(;i

    byte_t unit=regstr[i];

    for(int j=0;j

    printf("%d",(unit>>(4*(DIGITS_NUM/4-j-1)))&0xF);

    }

    }

    printf("\n");

    }

    byte_t _processUnit(byte_t unit){

    byte_t newval=0;

    for(int j=0;j

    int val=0xF&(unit>>(4*j));

    newval|=(val+(val>4?3:0))<

    }

    return newval;

    }

    int to8421bcd(byte_t *num,int n){

    resetRegstr();

    for(int k=0;k

    byte_t digit=num[k];

    for(int i=DIGITS_NUM-1;i>-1;i--){

    byte_t bi=(digit>>i)&0x1;

    for(int j=N-1;j>-1;j--){

    byte_t bi_=_processUnit(regstr[j]);

    regstr[j]=(bi_<<1)|bi;

    bi_=(bi_>>(DIGITS_NUM-1))&0x1;

    if(bi_==1&&j==0) return 0;

    bi=bi_;

    }

    }

    }

    return 1;

    }

    void main(){

    byte_t nums[]={/*2,321,973,245,437,681,127 */

    0x20,0x39,0x4E,0x5D,0x48,0x46,0x1D,0xE7

    };

    int ok=to8421bcd(nums,8);

    if(!ok){

    printf("something wrong...\n");

    }else{

    show8421bcd();

    }

    }

    展开全文
  • 一、BCD码 1、BCD码概述 2、BCD分类 1、有权码 2、无权码 3、BCD运算问题 二、二进制BCD码 1、原理实现 2、模块划分 3、仿真调试 4、仿真验证 三、BCD转二进制 1、原理实现 2、模块划分 3、仿真验证

    一、BCD码

    1、BCD码概述

    • BCD码(Binary-Coded Decimal‎),用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。
    • 相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免去使计算机作浮点运算时所耗费的时间
    • BCD码也称二进码十进数,BCD码可分为有权码和无权码两类。其中,常见的有权BCD码有8421码、2421码、5421码,无权BCD码有余3码、余3循环码、格雷码。

    图片表示
    在这里插入图片描述

    流程详解:
    二进制数:1010 0010 = 2 5 + 2 7 + 2 1 = 2 + 32 + 128 = 162 2^5+2^7+2^1=2+32+128=162 25+27+21=2+32+128=162
    BCD码是用四位二进制数表示十进制数【0~9】
    0001 = 2 0 = 1 2^0=1 20=1
    0110= 2 2 + 2 1 = 6 2^2+2^1=6 22+21=6
    0010= 2 1 = 2 2^1=2 21=2

    2、BCD分类

    BCD码可分为有权码和无权码两类。其中,常见的有权BCD码有8421码、2421码、5421码,无权BCD码有余3码、余3循环码、格雷码

    • 有权码,自然二进制代码是按照二进制代码各位权值大小,以自然向下加一,逢二进一的方式来表示数值的大小所生成的代码。
    • 有权码和无权码区别是每一位是否有权值。

    1、有权码

    8421
    8421 BCD码是最基本和最常用的BCD码,它和四位自然二进制码相似,各位的权值为8、4、2、1,故称为有权BCD码。和四位自然二进制码不同的是,它只选用了四位二进制码中前10组代码,即用0000~1001分别代表它所对应的十进制数,余下的六组代码不用。
    运算规则:

    十进制0123456789
    二进制(BCD8421)0000000100100011010001010110011110001001
    按权相加0 2 0 2^0 20 2 1 2^1 21 2 1 + 2 0 2^1+2^0 21+20 2 2 2^2 22 2 2 + 2 0 2^2+2^0 22+20 2 2 + 2 1 2^2+2^1 22+21 2 2 + 2 1 + 2 0 2^2+2^1+2^0 22+21+20 2 3 2^3 23 2 3 + 2 0 2^3+2^0 23+20

    实例验证:

    十进制数: 4 + 3 = 7 4+3=7 4+3=7
    二进制数: 0100 + 0011 = 0111 0100+0011=0111 0100+0011=0111

    /*二进制加法:逢二进一 */
         0 1 0 0    4
       + 0 0 1 1    3
    
         0 1 1 1    7
    

    5421

    十进制0123456789
    二进制(BCD5421)0000000100100011010010001001101010111100

    2421

    十进制0123456789
    二进制(BCD2421)0000000100100011010010111100110111101111

    总结:
    有权码就是对应数字为对应位的权值,1代表可以取到该值,0表示取不到。
    8421:十进制数:5 二进制数:0101 即4和1能取到 4 + 1 = 5 4+1=5 4+1=5
    5421: 十进制数:5 二进制数:1000 即5能取到 5 5 5
    2421:十进制数:9 二进制数:1111即2和4和2和1都能取到 2 + 4 + 2 + 1 = 9 2+4+2+1=9 2+4+2+1=9

    2、无权码

    余三码
    余3码是8421 BCD码的每个码组加3(0011)形成的。常用于BCD码的运算电路中。

    十进制0123456789
    二进制(BCD余三码)0011010001010110011110001001101010111100

    实例验证:

    十进制数:7
    二进制数;0111
    2 2 + 2 1 + 2 0 = 4 + 2 + 1 = 7 2^2+2^1+2^0=4+2+1=7 22+21+20=4+2+1=7

    /*二进制加法:逢二进一 */
         0 1 1 1    7
       + 0 0 1 1    3
    
         1 0 1 0   余三码: 7  十进制数:10
    

    余三循环码
    余3循环码是无权码,即每个编码中的1和0没有确切的权值,整个编码直接代表一个数值。主要优点是相邻编码只有一位变化,避免了过渡码产生的“噪声”。

    十进制0123456789
    二进制(BCD余三循环码)0010011001110101010011001101111111101010

    3、BCD运算问题

    我们知道,BCD是用四位二进制数表示十进制数【0~9】的,而四位二进制数可以表示的十进制数为 2 4 = 16 2^4=16 24=16 个即【0~15】,当运算超出范围怎么办?
    解决方案:
    5 + 8 = 13 5+8=13 5+8=13为例
    十进制数: 5 + 8 = 13 5+8=13 5+8=13
    二进制数: 0101 + 1000 = 1101 0101+1000=1101 0101+1000=1101
    差值: 16 − 10 = 6 16-10=6 1610=6
    将所得值加6,产生进位,高位补0
    1101 + 0110 = 00010011 1101+0110=00010011 1101+0110=00010011
    在这里插入图片描述

    /*二进制加法:逢二进一 */
               1 1 0 1    13
             + 0 1 1 0    6
            1  1          产生进位
      0 0 0 1  0 0 1 1    高位补0
    

    二、二进制BCD码

    1、原理实现

    使用逐步移位法来实现二进制数向BCD码的转换;
    变量定义:

    • B:需要转换的二进制数位宽
    • D:转换后的BCD码位宽(其中BCD码的位宽计算如下:根据二进制数的位宽,求出它的无符号数能表示的最大值和最小值,如数据位宽是8位则数据范围大小就是0~255,我们取最大值255,每一个数字对应4位BCD码,三个数字就对应3x4=12位的BCD码)
    • N:需要转换的二进制数位宽加上转换后的BCD码位宽

    逐步移位法的规则:

    • 准备一个N比特的移位寄存器;
    • 二进数逐步左移;
    • 每次左移之后每个BCD位做大四加三的调整;
    • 二进数全部移完,得到结果。

    移位流程表

    移位次数BCD[11:8]BCD[7:4]BCD[3:0]bin[7:0]说明
    010100101输入二进制数
    1101001010左移一位,低位补0
    21010010100左移两位,低位补0
    310100101000101=5;大于4加3
    3100000101000加3不移位
    410000010100001000移位,原始值也移位,低位补0
    510000010100000循环移位,低位补0
    6100000101000000循环移位,低位补0
    71000001010000000循环移位,低位补0
    71011001010000000循环移位,低位补0
    810110010100000000循环移位,低位补0
    BCD165移位结束,输出BCD码

    2、模块划分

    顶层模块
    在这里插入图片描述
    代码实现

    module bin2bcd (
        
        input         [7:0]       bin    ,//二进制输入
        output        [11:0]      bcd     //bcd码输出
    );
    
       //信号定义
       wire        [19:0]         bcd_reg0  ;
       wire        [19:0]         bcd_reg1  ;
       wire        [19:0]         bcd_reg2  ;
       wire        [19:0]         bcd_reg3  ;
       wire        [19:0]         bcd_reg4  ;
       wire        [19:0]         bcd_reg5  ;
       wire        [19:0]         bcd_reg6  ;
       wire        [19:0]         bcd_reg7  ;
       wire        [19:0]         bcd_reg8  ;//八次移位结果输出
    
       assign bcd_reg0 = {12'b0000_0000_0000,bin};//将输入的八位二进制转换为二十位
       //第一次移位
       bcd_modify b1
       (.data_in(bcd_reg0),.data_out(bcd_reg1));
       //第二次移位
       bcd_modify b2
       (.data_in(bcd_reg1),.data_out(bcd_reg2));
       //第三次移位
       bcd_modify b3
       (.data_in(bcd_reg2),.data_out(bcd_reg3));
       //第四次移位
       bcd_modify b4
       (.data_in(bcd_reg3),.data_out(bcd_reg4));
       //第五次移位
       bcd_modify b5
       (.data_in(bcd_reg4),.data_out(bcd_reg5));
       //第六次移位
       bcd_modify b6
       (.data_in(bcd_reg5),.data_out(bcd_reg6));
       //第七次移位
       bcd_modify b7
       (.data_in(bcd_reg6),.data_out(bcd_reg7));
       //第八次移位
       bcd_modify b8
       (.data_in(bcd_reg7),.data_out(bcd_reg8));
       //BCD输出
       assign bcd = {bcd_reg8[19:8]};//取高12位为输出结果
    
    endmodule
    

    移位模块
    在这里插入图片描述
    代码实现

    //移位处理模块
    
    module bcd_modify (
        
        input       [19:0]    data_in ,//移位比较数据输入
        output      [19:0]    data_out //移位比较数据输出
    );
    
        //信号定义
        wire         [3:0]      reg1    ;//移位结果输出
        wire         [3:0]      reg2    ;
        wire         [3:0]      reg3    ;
    
        //左移大4加3比较 [19:16]
        bcd_cmp c1
        (.cmp_in(data_in[19:16]),.cmp_out(reg1));
        //左移大4加3比较 [15:12]
        bcd_cmp c2
        (.cmp_in(data_in[15:12]),.cmp_out(reg2));
        //左移大4加3比较 [11:8]
        bcd_cmp c3
        (.cmp_in(data_in[11:8]),.cmp_out(reg3));
        //比较完成 左移一位
        assign data_out = {reg1[2:0],reg2,reg3,data_in[7:0],1'b0};
        
    endmodule
    

    大四加三处理模块
    在这里插入图片描述
    代码实现

    //大四加三处理
    module bcd_cmp(
    
        input      [3:0]    cmp_in  ,//比较器数据输入
        output  reg[3:0]    cmp_out  //比较器数据输出
    );
       
       always @(*) begin
           if(cmp_in > 4)
           cmp_out = cmp_in + 3;//大于四加三
           else
           cmp_out = cmp_in;//小或等于四 不作处理
       end
    
    endmodule
    

    3、仿真调试

    仿真文件【testbench】

    `timescale 1ns/1ps
    module bin2bcd_tb();
    reg        [7:0]     bin   ;
    wire       [11:0]    bcd   ;
    bin2bcd u_bin2bcd
    (
        .bin         ( bin   ),
        .bcd         ( bcd   )
    );
    parameter CYCLE = 20;
    initial begin
        #(CYCLE*200);
        bin = 8'b0;//bin信号初始化
        #(CYCLE*100);
        bin = 8'b1010_1101;//173
        #(CYCLE*100);
        bin = 8'b0000_1101;//13
        #(CYCLE*100);
        bin = 8'b1010_0100;//164
        #(CYCLE*100);
        bin = 8'b1000_0000;//128
        #(CYCLE*100);
        bin = 8'b1111_1111;//255
        $stop;
    end
    endmodule
    

    【do】文件

    vlib work
    vmap work work
    #编译testbench文件
    vlog  bin2bcd_tb.v
    #编译设计文件
    vlog ../rtl/bcd_cmp.v
    vlog ../rtl/bin2bcd.v
    vlog ../rtl/bcd_modify.v
    #指定仿真顶层
    vsim -novopt work.bin2bcd_tb
    #添加信号到波形窗
    add wave -position insertpoint sim:/bin2bcd_tb//*
    

    do调试流程
    打开仿真调试工具modelsim
    在这里插入图片描述
    点击【file】->【change Directory…】
    在这里插入图片描述
    找到tb文件【或者仿真测试文件还有do文件所在目录】
    在这里插入图片描述
    左下角查看打开的目录
    在这里插入图片描述
    使用指令,开始仿真【do do.do】;然后回车

    do filename.do
    

    在这里插入图片描述
    编译无报错【注意错误和警告信息】
    在这里插入图片描述

    4、仿真验证

    将bin用十进制表示,加上【unsigned】
    在这里插入图片描述

     #(CYCLE*200);
        bin = 8'b0;//bin信号初始化
        #(CYCLE*100);
        bin = 8'b1010_1101;//173
        #(CYCLE*100);
        bin = 8'b0000_1101;//13
        #(CYCLE*100);
        bin = 8'b1010_0100;//164
        #(CYCLE*100);
        bin = 8'b1000_0000;//128
        #(CYCLE*100);
        bin = 8'b1111_1111;//255
    

    对比可以发现,输入值符合预期。
    下面任意取一个值进行验证。

    十进制数:128
    BCD码表示:0001 0010 1000

    取BCD输出的高12位为输出结果【输入为8,低位为移位补0值】
    在这里插入图片描述
    经过对比,输出与实际值吻合。

    三、BCD码转二进制

    1、原理实现

    移位算法原理
    二进制码左移一位等于未左移的二进制码*2,例如有二进制码101001,转成十进制等于41,左移一位得到1010010,转成十进制等于82。也就是说二进制码左移1位加上左移3位可以等效于二进制码乘以10。

    2、模块划分

    移位相加
    在这里插入图片描述
    代码实现

    /************************工程说明*********************
       BCD码转二进制码
    *****************************************************/
    module bcd2bin(
    
        input                 clk      ,//系统时钟 50Mhz
        input                 rst_n    ,//复位 低电平有效
        input        [3:0]    bw       ,//BCD码百位
        input        [3:0]    sw       ,//BCD码十位
        input        [3:0]    gw       ,//BCD码个位
        output       [9:0]    bin       //二进制输出
    );
    
       //信号定义
       reg           [9:0]    bw_v1   ;//BCD码百位寄存器1
       reg           [9:0]    bw_v2   ;//BCD码百位寄存器2
       reg           [9:0]    bw_v3   ;//BCD码百位寄存器3
       reg           [9:0]    sw_v1   ;//BCD码十位寄存器1
       reg           [9:0]    sw_v2   ;//BCD码十位寄存器2
       reg           [9:0]    gw_v1   ;//BCD码个位寄存器
    
       /**********************换算规则:**********************
       BCD百位:a*100=a*(64+32+4)=a*64+a*32+a*4 =a000000+a00000+a00,即a左移6位加上左移5位加上a左移2位 
       BCD十位:a*10=a*(8+2)=a*8+a*2 =a000+a0,即a左移3位加上左移1位     
       BCD个位:个位数据不变
       将所有的各个位的转换结果相加就是转换后的二进制数
       左移运算:2^n      右移运算:1/(2^n)
       ******************************************************/
       //寄存器赋初值
       always @(posedge clk or negedge rst_n) begin
           if(!rst_n)begin
             bw_v1 <= 0;
             bw_v2 <= 0;
             bw_v3 <= 0;
             sw_v1 <= 0;
             sw_v2 <= 0;
             gw_v1 <= 0;
           end
           else begin
             bw_v1 <= bw << 6;//左移六位
             bw_v2 <= bw << 5;//左移五位
             bw_v3 <= bw << 2;//左移两位
             sw_v1 <= sw << 3;//左移三位
             sw_v2 <= sw << 1;//左移一位
             gw_v1 <= gw;//个位保持不变
           end
       end
       assign bin = bw_v1 + bw_v2 + bw_v3 + sw_v1 + sw_v2 + gw_v1;
    
    endmodule
    

    3、仿真验证

    仿真测试文件【testbench】

    //时间单位/精度
    `timescale 1ns/1ps
    
    module bcd2bin_tb();
    //激励信号
    reg                        clk    ;
    reg                        rst_n  ;
    reg            [3:0]       bw     ;
    reg            [3:0]       sw     ;
    reg            [3:0]       gw     ;
    //输出信号
    wire           [9:0]       bin    ;
    
    //模块例化
    bcd2bin    u_bcd2bin
    (
        .clk       ( clk    ),
        .rst_n     ( rst_n  ),
        .bw        ( bw     ),
        .gw        ( gw     ),
        .sw        ( sw     ),
        .bin       ( bin    )
    );
    
    //产生时钟
    parameter CYCLE = 20;
     
     always #(CYCLE/2) clk = ~clk;
      
      //产生激励
      initial begin
          clk   = 1'b0;
          rst_n = 1'b0;
          bw = 4'd0; sw = 4'd0; gw = 4'd0;//000
          #(CYCLE*500);
          rst_n = 1'b1;
          #(CYCLE*1000);
          bw = 4'd1; sw = 4'd2; gw = 4'd0;//120
          #(CYCLE*1000);
          bw = 4'd3; sw = 4'd2; gw = 4'd9;//329
          #(CYCLE*1000);
          bw = 4'd7; sw = 4'd0; gw = 4'd3;//703
          #(CYCLE*1000);
          bw = 4'd0; sw = 4'd2; gw = 4'd7;//027
          #(CYCLE*1000);
          bw = 4'd2; sw = 4'd9; gw = 4'd0;//290
          #(CYCLE*5000);
          $stop;
    
      end
    
    endmodule
    

    do文件

    vlib work
    vmap work work
    
    #编译testbench文件
    vlog bcd2bin_tb.v
    
    #编译设计文件 
    vlog ../rtl/bcd2bin.v
    
    #指定仿真顶层
    vsim -novopt work.bcd2bin_tb
    
    #添加信号到波形窗
    add wave -position insertpoint sim:/bcd2bin_tb//*
    

    验证结果
    输入值查看
    在这里插入图片描述
    仿真输入值

    bw = 4'd0; sw = 4'd0; gw = 4'd0;//000
          #(CYCLE*500);
          rst_n = 1'b1;
          #(CYCLE*1000);
          bw = 4'd1; sw = 4'd2; gw = 4'd0;//120
          #(CYCLE*1000);
          bw = 4'd3; sw = 4'd2; gw = 4'd9;//329
          #(CYCLE*1000);
          bw = 4'd7; sw = 4'd0; gw = 4'd3;//703
          #(CYCLE*1000);
          bw = 4'd0; sw = 4'd2; gw = 4'd7;//027
          #(CYCLE*1000);
          bw = 4'd2; sw = 4'd9; gw = 4'd0;//290
          #(CYCLE*5000);
    

    输出结果

    百位:左移六位+左移五位+左移两位
    十位:左移三位+左移一位
    个位:不变

    在这里插入图片描述
    经对比,结果符合预期。

    展开全文
  • 24位BIN转BCD码://--------------start of file---------------- --extern void bin2bcd(unsigned char *output, unsigned long input); --void bin2bcd(unsigned char *output, unsigned long input) -{ -*output ...

    24位BIN转BCD码:

    //--------------start of file---------------- -

    -

    extern void bin2bcd(unsigned char *output, unsigned long input); -

    -

    void bin2bcd(unsigned char *output, unsigned long input) -

    { -

    *output = 0; -

    if (input >= 4000000000) { *output += 0x40; input -= 4000000000; } -

    if (input >= 2000000000) { *output += 0x20; input -= 2000000000; } -

    if (input >= 1000000000) { *output += 0x10; input -= 1000000000; } -

    if (input >= 800000000) { *output += 0x08; input -= 800000000; } -

    if (input >= 400000000) { *output += 0x04; input -= 400000000; } -

    if (input >= 200000000) { *output += 0x02; input -= 200000000; } -

    if (input >= 100000000) { *output += 0x01; input -= 100000000; } -

    output++; -

    -

    *output = 0; -

    if (input >= 80000000) { *output += 0x80; input -= 80000000; } -

    if (input >= 40000000) { *output += 0x40; input -= 40000000; } -

    if (input >= 20000000) { *output += 0x20; input -= 20000000; } -

    if (input >= 10000000) { *output += 0x10; input -= 10000000; } -

    if (input >= 8000000) { *output += 0x08; input -= 8000000; } -

    if (input >= 4000000) { *output += 0x04; input -= 4000000; } -

    if (input >= 2000000) { *output += 0x02; input -= 2000000; } -

    if (input >= 1000000) { *output += 0x01; input -= 1000000; } -

    output++; -

    -

    *output = 0; -

    if (input >= 800000) { *output += 0x80; input -= 800000; } -

    if (input >= 400000) { *output += 0x40; input -= 400000; } -

    if (input >= 200000) { *output += 0x20; input -= 200000; } -

    if (input >= 100000) { *output += 0x10; input -= 100000; } -

    if (input >= 80000) { *output += 0x08; input -= 80000; } -

    if (input >= 40000) { *output += 0x04; input -= 40000; } -

    if (input >= 20000) { *output += 0x02; input -= 20000; } -

    if (input >= 10000) { *output += 0x01; input -= 10000; } -

    output++; -

    -

    *output = 0; -

    if (input >= 8000) { *output += 0x80; input -= 8000; } -

    if (input >= 4000) { *output += 0x40; input -= 4000; } -

    if (input >= 2000) { *output += 0x20; input -= 2000; } -

    if (input >= 1000) { *output += 0x10; input -= 1000; } -

    if (input >= 800) { *output += 0x08; input -= 800; } -

    if (input >= 400) { *output += 0x04; input -= 400; } -

    if (input >= 200) { *output += 0x02; input -= 200; } -

    if (input >= 100) { *output += 0x01; input -= 100; } -

    output++; -

    -

    *output = 0; -

    if (input >= 80) { *output += 0x80; input -= 80; } -

    if (input >= 40) { *output += 0x40; input -= 40; } -

    if (input >= 20) { *output += 0x20; input -= 20; } -

    if (input >= 10) { *output += 0x10; input -= 10; } -

    *output += (unsigned char)(input & 0x0F); -

    } -

    -

    unsigned char output[5]; -

    -

    int main(int argc, char* argv[]) -

    { -

    -

    bin2bcd(output,0xFFFFFFFF); -

    bin2bcd(output,3999999999); -

    bin2bcd(output,0); -

    return 0; -

    } -

    -

    //--------------end of file-----------------

    16位BIN转BCD码

    #include

    #define wufuhao_zifu unsigned char

    void calculate(unsigned int value)

    {

    wufuhao_zifu tempA;    //变量保存16位的高8位

    wufuhao_zifu tempB;    //变量保存16位的低8位

    wufuhao_zifu temp1;    //变量保存16位数据的个位

    wufuhao_zifu temp2;    //变量保存16位数据的十位

    wufuhao_zifu temp3;    //变量保存16位数据的百位

    wufuhao_zifu temp4;    //变量保存16位数据的千位

    wufuhao_zifu temp5;    //变量保存16位数据的万位

    tempA=value>>8;

    tempB=value&0x00ff;

    temp1=temp2=temp3=temp4=temp5=0;

    while(((tempA==0x27)&&(tempB>=0x10))||(tempA>0x27))

    {

    if(tempB>=0x10)

    {

    tempB-=0x10;

    tempA-=0x27;

    }

    else

    {

    tempB+=(~0x10)+1;

    tempA-=0x27+1;

    }

    temp5++;

    }

    while(((tempA==0x03)&&(tempB>=0xe8))||(tempA>0x03))

    {

    if(tempB>=0xe8)

    {

    tempB-=0xe8;

    tempA-=0x03;

    }

    else

    {

    tempB+=(~0xe8)+1;

    tempA-=0x03+1;

    }

    temp4++;

    }

    while(((tempA==0)&&(tempB>=0x64))||(tempA>0))

    {

    if(tempB>=0x64)

    {

    tempB-=0x64;

    }

    else

    {

    tempB+=(~0x64)+1;

    tempA-=1;

    }

    temp3++;

    }

    while(tempB>=0x0a)

    {

    tempB-=0x0a;

    temp2++;

    }

    while(tempB>=0x01)

    {

    tempB-=0x01;

    temp1++;

    }

    }

    void main()

    {

    while(1)

    {

    calculate(65535);

    }

    }

    ---------------------------------------------------------------------------------------------------------------

    非常快速的16位BIN转BCD程序

    #include

    unsigned char dig[5];

    void bin2bcd(unsigned int x)

    {

    unsigned char i,j,k;

    k = x;

    x >>= 2;

    i = x >> 8;

    j = (i + i + i) << 1;

    if (i > 41) {i++;j+=6;}

    j += x;

    if ((unsigned char)x > j ) {i++;j+=6;}

    if (j > 249) {i++;j+=6;}

    dig[0] = i / 10;                      //10000

    dig[1] = B;                           //1000

    dig[2] = j / 25;                      //100

    dig[3] = (B<<2 | k&3) / 10;           //10

    dig[4] = B;                           //1

    }

    void main()

    {

    while(1)

    {

    bin2bcd(32768);

    }

    }

    展开全文
  • 二进制转BCD码(8421)

    万次阅读 多人点赞 2018-12-02 15:48:52
    在显示温度、电压、电流等数据时,通常需要将二进制数据十进制进行显示。最常用的方法是将二进制码转换成BCD码(8421)。  8421码:它只选用了四位二进制码中前10组代码,即用0000~1001分别代表它所对应的...
  • #include #include #define uchar unsigned charuchar BCD_Decimal(uchar bcd) ;int main(void){uchar ch = 0x20 ;uchar dec = BCD_Decimal(ch) ;printf("dec = %d\n",dec);...}//BCD转十进制函数,输入BC...
  • 关于这类算法,以前的文章已经讲过类似的:BCD转二进制#include // HEX转BCD//bcd_data(<0x255,>0)unsigned char BCD2HEX(unsigned int bcd_data){unsigned char temp;temp=((bcd_data>>8)*100)|((bcd...
  • 硬件算法__二进制转BCD

    千次阅读 2017-08-30 18:54:14
    参考二进制转BCD码数字逻辑电路中经常遇到级制转换为BCD码的要求,比如显示数码管什么的,这是为了方便人们的固有计数模式。这里学习一个移位加3法 举个例子(一下直接贴原文了,加上小白的翻译) 2.Purpose: ...
  • 写在前面的话 在前面小节的学习中,我们已经...在数学中,我们都知道随便一个十进制数如5468 ,那么它的计算过程可以转换为:5468= 5*1000+4*100+6*10+8,因此BCD二进制数的算法就是: abcd = a*1000 + b*...
  • Double-Dabble Binary-to-BCD Conversion Algorithm
  • 在做而论道上篇博文中,回答了一个16位二进制数转换成BCD码的问题,给出了一个网上广泛流传的经典转换程序。.说它经典,不仅是因为它已经流传已久,重要的是它的编程思路十分清晰,十分易于延伸推广。做而论道曾经...
  • 目录写在前面正文快速认识实现方式一实现方式写在最后写在前面FPGA基础知识极简教程(9)讲到了七段数码管的显示Verilog设计,我们都知道,要在数码管上显示的数字,使用BCD编码是具有优势的(或者是最正确的)。...
  • 二进制转BCD

    万次阅读 2015-05-15 22:33:25
    但是,在FPGA里面用求商和求余将会非常消耗资源,这样就必须用到二进制转BCD码了,这里介绍一种简单的加3移位算法。 注:B代表二进制,D代表十进制,0x代表十六进制,BCDBCD码,下同。 1、加3移位法 以二进制数...
  • BCD码与二进制的转换

    千次阅读 2020-03-29 19:53:55
    百位|位|个位|二进制高4位|二进制低4位 二进制BCD算法 从低到高依次判断个位、位、百位这三列的数是否大于等于5,如果是则加3修正 左移整个数据结构1位 重复1和2步8次(重复次数取决于需要表示的数字的...
  • 听说99%的同学都来这里充电吖 本系列为线下学员学习笔记整理分享,如有想要报名参加线下培训,可以点击以下超链接文章了解,购买开发板可以到叁...本篇文章,记录BCD二进制、二进制转BCD的原理,及verilog...
  • 进制转BCD码(加3移位法)动态显示实例 本文实现一个二进制转十进制的电路,8位拨码开关(SW7-SW0)作为一组8位二进制输入信号,拨码开关SW11作为复位开关,拨码开关SW10作为使能开关,将8位二进制输入转为3位...
  • BCD转换成十进制

    千次阅读 2019-10-20 23:23:54
    BCD码是指用二进制来表示十进制数的编码,即用4位二进制来表示一位十进制数,因此4位二进制数表示最大的十进制数9(1001),只取十六个数中的十个数(有别于8421码)。 为了表示两个十进制数(十位、个位),需要两...
  • 本例为单字节二进制数(0X20)转换为非压缩BCD 码,存在0X25,0X24,0X23 中,0X25 为百位,0X23 为个位。main: MOV a,@0xa4 ;赋值MOV 0x20,aMOV 0x21,aMOV 0x22,aMOV a,@0x0 ;0x23,0x24,0x25 单元清0MOV 0x23,aMOV 0x24,a...
  • C语言:十进制BCD码互换

    万次阅读 2021-08-30 16:38:17
    最近写单片机 RTC 日期、时间配置,需要实现十进制BCD码互换,将示例Demo分享给各位朋友~
  • BCD十进制转换的算法

    万次阅读 2014-06-13 09:00:10
    BCD是指用二进制来表示十进制数的编码,即用4位二进制来表示一个十进制数,因此4位二进制数表示最大的十进制数9(1001),只取十六个数中的十个数(有别于8421码)。 为了表示两个十进制数(十位、个位),需要两...
  • 80X86汇编语言,编写一条程序实现任意两个五位数相加并显示结果...存放5位十进制数.Y DB 6,7,8,9,0;都是非压缩的BCD码.Z DB 6 DUP?6位数的和.DATAS ENDSCODES SEGMENTASSUME CS:CODES,DS:DATASSTART:MOV ...
  • 十进制BCD码转换的算法

    万次阅读 多人点赞 2018-08-06 13:13:47
    BCD是指用二进制来表示十进制数的编码,即用4位二进制来表示一位十进制数,因此4位二进制数表示最大的十进制数9(1001),只取十六个数中的十个数。 比如: BCD码:0x99(153),该BCD码转换成十进制是99. 算法...
  • BCD码、十六进制与十进制

    千次阅读 2017-09-07 22:46:26
    在做嵌入式软件的设计中,经常会遇到十六进制、BCD码与十进制之间的转换,最近做M1卡的应用中,涉及了大量的十六进制、BCD码与十进制之间的转换。通过对BCD码、十六进制 权的理解,轻松的实现了他们之间的互换。 ...
  • BCD码与16进制转算法

    万次阅读 2019-06-04 21:16:26
    转载来自: link.(侵删) ...// HEX转BCD //bcd_data(<0x255,>0) unsigned char BCD2HEX(unsigned int bcd_data) { unsigned char temp; temp=((bcd_data>>8)*100)|((bcd_data>...
  • 二进制转十进制

    2021-11-28 11:31:53
  • BCD 码(Binary-Coded Decimal),又称二 - 十进制码,使用 4 位二进制数来表示 1 位十进制数中的 0~9 这 10 个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。
  • bcd转二进制

    2016-08-30 20:08:00
    最简单的BCD转二进制的方法是什么呢? 我们知道BCD码每4位表示一个10进制数,我们现在假设num_reg是一个16位的BCD码,也就是4位的十进制数。那么num_reg[15:12]表示这个数的最高位,他的权值是1000,这个应该可以...
  • 学习中经常要用到将十进制数据转换为BCD码,算法比较简单,简单说明一下。 **BCD码:**4位二进制数来表示一位十进制数的编码,例如十进制数279,转换为BCD码就是’h177。 算法实现流程:二进制数据每次左移一位,每...
  • 微机原理实验-二进制BCD转换广州大学学生实验报告开课学院及实验室:实验中心学 院 机电 年级、专 业、班 微机原理实验2013 年 11 月 4 日姓名 学号 成绩 指导 教师实验课程名称 实验项目名称 一、实验目的二进制...
  • 今天给大侠带来一表透彻 二进制转BCD之大四加三算法,话不多说,上货。 这里超链接几篇,给各位大侠参考。 基于FPGA的二进制转BCD设计(附代码) FPGA学习altera 系列 第二十三篇 二进制转BCD FPGA学习altera ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,195
精华内容 878
关键字:

bcd算法二进制转十进制