3

As we can see that,in VHDL ,MOD and REM only can be simulated but can't be synthesized.So how can we get the BCD from an unsigned integer? For example,the integer is 23,how can we get the BCD:0b0010 and 0b0011? Thanks.

user1673133
  • 31
  • 1
  • 1
  • 2

3 Answers3

1

This has been covered elsewhere:

https://electronics.stackexchange.com/questions/22611/binary-to-bcd-converison

  • A lookup table is one option
  • A big case statement is another (Which will get turned into a lookup table)
  • Or an iterative method where you keep subtracting 10 until the remainder is < 10 - the count of subtractions is your tens digit, the remainder is your units digit.
Community
  • 1
  • 1
Martin Thompson
  • 16,395
  • 1
  • 38
  • 56
1

I am providing two VHDL functions below. This is to convert from binary to packed BCD and vice-versa. I have verified these on Xilinx Spartan 3AN Family and they can be synthesized. Use ieee.numeric_std.all; and ieee.std_logic_1164.all; libraries

Function 1: Binary to BCD --source:http://vhdlguru.blogspot.com.es/2010/04/8-bit-binary-to-bcd-converter-double.html (SO user Peque found the original url)

    function to_bcd ( bin : unsigned(7 downto 0) ) return unsigned is
        variable i : integer:=0;
        variable bcd : unsigned(11 downto 0) := (others => '0');
        variable bint : unsigned(7 downto 0) := bin;

        begin
        for i in 0 to 7 loop  -- repeating 8 times.
        bcd(11 downto 1) := bcd(10 downto 0);  --shifting the bits.
        bcd(0) := bint(7);
        bint(7 downto 1) := bint(6 downto 0);
        bint(0) :='0';


        if(i < 7 and bcd(3 downto 0) > "0100") then --add 3 if BCD digit is greater than 4.
        bcd(3 downto 0) := bcd(3 downto 0) + "0011";
        end if;

        if(i < 7 and bcd(7 downto 4) > "0100") then --add 3 if BCD digit is greater than 4.
        bcd(7 downto 4) := bcd(7 downto 4) + "0011";
        end if;

        if(i < 7 and bcd(11 downto 8) > "0100") then  --add 3 if BCD digit is greater than 4.
        bcd(11 downto 8) := bcd(11 downto 8) + "0011";
        end if;

    end loop;
    return bcd;
    end to_bcd;

Function 2: BCD to Binary

    --(c)2012 Enthusiasticgeek for Stack Overflow. 
    --Use at your own risk (includes commercial usage). 
    --These functions are released in the public domain and 
    --free to use as long as this copyright notice is retained.

    --multiplication by 10 is achieved using shift operator   X<<3 + X<<1
    --input should be packed BCD.
    function to_binary ( bcd : unsigned(11 downto 0) ) return unsigned is
        variable i : integer:=0;
        variable binary : unsigned(7 downto 0) := (others => '0');  
        variable temp : unsigned(6 downto 0) := (others => '0');
        variable bcdt : unsigned(11 downto 0) := bcd;   
        variable tens : unsigned(7 downto 0) := (others => '0');
        variable hundreds_stepI : unsigned(7 downto 0) := (others => '0');
        variable hundreds_stepII : unsigned(7 downto 0) := (others => '0');

       begin

         for i in 0 to 11 loop  -- repeating 12 times.

         if(i >=0 and i<4) then
            binary := ((temp&bcdt(i) ) sll i ) + binary;
         end if;         

         if(i >=4 and i<8) then         
            tens := (((temp&bcdt(i) ) sll (i-4) ) sll 3) + (((temp&bcdt(i) ) sll (i-4) ) sll 1); --multiply by 10           
            binary := tens + binary;
         end if;         

         if(i >=8 and i<12) then         
            hundreds_stepI := (((temp&bcdt(i) ) sll (i-8) ) sll 3) + (((temp&bcdt(i) ) sll (i-8) ) sll 1); --multiply by 10
            hundreds_stepII := (hundreds_stepI sll 3) + (hundreds_StepI sll 1); -- multiply by 10 again so the effect is now multiply by 100                
            binary := hundreds_stepII + binary;
         end if;

         end loop;     

       return binary;
    end to_binary;

Note: You can convert your integer to unsigned using the info on the following link convert integer to std_logic

Community
  • 1
  • 1
enthusiasticgeek
  • 2,640
  • 46
  • 53
  • 1
    -1 for adding a copyright notice to a code that is not your own: http://vhdlguru.blogspot.com.es/2010/04/8-bit-binary-to-bcd-converter-double.html – Peque May 10 '15 at 19:32
  • @Peque Yup you are correct. I think I copied and pasted the copyright template I have for all VHDL for both the codes. I wrote to to_binary (to the best of my knowledge - that was three years ago). I generally give references whenever applicable - somehow I must have missed this one. Updated answer. Thanks for pointing it out. – enthusiasticgeek May 11 '15 at 14:47
0

You may be interested in having a look at the "double dabble" algorithm:

http://en.wikipedia.org/wiki/Double_dabble

Basically, what you do is create a register for the BCD representation that you put "at the left" of the integer representation. Here is an example, in which we want to convert the number 23 to its BCD representation:

BCD_1  BCD_0      Original
0000   0000       10111

Now you create a for loop in which you shift the Original bits to the left (you push those bits into the BCD register). In this loop, you must check, for each BCD_X digit, if they are greater than 4; in that case, you add 3 to that digit:

shift_iteration   BCD_1  BCD_0      Original
0                 0000   0000       10111
1                 0000   0001       01110       (no digit greater than 4)
2                 0000   0010       11100       (no digit greater than 4)
3                 0000   0101       11000       (5 in BCD_0! we add 3...)
still 3...        0000   1000       11000       (after addition, shift again)
4                 0001   0001       10000       (no digit greater than 4)
5                 0010   0011       00000       (no digit greater than 4)

Once you have pushed all the original bits to the BCD register (using the +3 rule when any digit was greater than 4) the BCD represents 0010 0011 (23).

For more details, see the Wikipedia article. You'll even find an example of a VHDL implementation.

Peque
  • 13,638
  • 11
  • 69
  • 105