VHDL coding tips and tricks: BCD
Showing posts with label BCD. Show all posts
Showing posts with label BCD. Show all posts

Monday, April 27, 2015

VHDL code for BCD to Binary conversion

In the past I have posted various codes for Binary to BCD conversion, BCD addition, BCD seven segement display etc. And I got few queries for binary to bcd conversion. So here it is:

The input is 4 digit BCD's, each 4 bit in size. And the output is 14 bit binary. The input can range from 0000 to 9999 in decimal.

With few changes in the code, it can be extended for more number of BCD digits. I hope you will experiment with the code to see how it works. Have fun!

VHDL Code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--this module is for converting a 4 digit BCD number into binary number. 
--the range of the input in decimal is 0 to 9999.
entity bcd_2_bin is
    Port ( bcd_in_0 : in  STD_LOGIC_VECTOR (3 downto 0);
           bcd_in_10 : in  STD_LOGIC_VECTOR (3 downto 0);
           bcd_in_100 : in  STD_LOGIC_VECTOR (3 downto 0);
           bcd_in_1000 : in  STD_LOGIC_VECTOR (3 downto 0);
           bin_out : out  STD_LOGIC_VECTOR (13 downto 0) := (others => '0'));
end bcd_2_bin;

architecture Behavioral of bcd_2_bin is

begin

bin_out <= (bcd_in_0 * "01")  --multiply by 1
                + (bcd_in_10 * "1010") --multiply by 10
                + (bcd_in_100 * "1100100") --multiply by 100
                + (bcd_in_1000 * "1111101000"); --multiply by 1000

end Behavioral;

Testbench Code:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
ENTITY tb_bb IS
END tb_bb;
 
ARCHITECTURE behavior OF tb_bb IS 

    COMPONENT bcd_2_bin
    PORT(
         bcd_in_0 : IN  std_logic_vector(3 downto 0);
         bcd_in_10 : IN  std_logic_vector(3 downto 0);
         bcd_in_100 : IN  std_logic_vector(3 downto 0);
         bcd_in_1000 : IN  std_logic_vector(3 downto 0);
         bin_out : OUT  std_logic_vector(13 downto 0)
        );
    END COMPONENT;

   signal bcd_in_0 : std_logic_vector(3 downto 0) := (others => '0');
   signal bcd_in_10 : std_logic_vector(3 downto 0) := (others => '0');
   signal bcd_in_100 : std_logic_vector(3 downto 0) := (others => '0');
   signal bcd_in_1000 : std_logic_vector(3 downto 0) := (others => '0');
   signal bin_out : std_logic_vector(13 downto 0);

BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: bcd_2_bin PORT MAP (
          bcd_in_0 => bcd_in_0,
          bcd_in_10 => bcd_in_10,
          bcd_in_100 => bcd_in_100,
          bcd_in_1000 => bcd_in_1000,
          bin_out => bin_out
        );

-- Stimulus process
   stim_proc: process
   begin        
      bcd_in_0 <= x"0"; bcd_in_10 <= x"1"; bcd_in_100 <= x"2"; bcd_in_1000 <= x"3";
        wait for 100 ns;
        bcd_in_0 <= x"9"; bcd_in_10 <= x"9"; bcd_in_100 <= x"9"; bcd_in_1000 <= x"9";
        wait for 100 ns;
        bcd_in_0 <= x"9"; bcd_in_10 <= x"2"; bcd_in_100 <= x"4"; bcd_in_1000 <= x"6";
        wait for 100 ns;
        bcd_in_0 <= x"0"; bcd_in_10 <= x"0"; bcd_in_100 <= x"0"; bcd_in_1000 <= x"0";
      wait;
   end process;

END;



Simulation waveform:

The code was simulated using Xilinx ISIM.


Sunday, August 4, 2013

BCD Addition - Behavioral level vhdl code

BCD or Binary coded decimal is a way of representing decimal digits in binary form. Generally 4 bits are used to represent values 0 to 9.

Decimal
Digit
BCD
8 4 2 1
00 0 0 0
10 0 0 1
20 0 1 0
30 0 1 1
40 1 0 0
50 1 0 1
60 1 1 0
70 1 1 1
81 0 0 0
91 0 0 1

In this post we discuss about BCD addition. The output of a BCD adder is also supposed to be in BCD format. So after the normal binary addition of the inputs, there should be a BCD adjustment code to convert the result to BCD format.

Consider the below BCD addition :

1001 + 1000 = 10001
   9 +    8 =    17

Since the range of input is 0 to 9, the maximum output is 18. If you consider a carry it becomes 19. This means at the output side we need a 4 bit sum and a 1 bit carry to represent the MSB digit.
For multiple digit addition , you can connect the carry_out to the carry input of the next adder. A simple cascading network of these small adders is enough to realize the multiple digit BCD addition.

VHDL code for single digit BCD addition:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bcd_adder is
    port(
        a,b  : in  unsigned(3 downto 0); -- input numbers.
        carry_in : in std_logic;
        sum  : out  unsigned(3 downto 0); 
        carry : out std_logic  
    );
end bcd_adder;

architecture arch of bcd_adder is


begin

process(a,b)
variable sum_temp : unsigned(4 downto 0);
begin
    sum_temp := ('0& a) + ('0& b) + ("0000" & carry_in); 
    if(sum_temp > 9) then
        carry <= '1';
        sum <= resize((sum_temp + "00110"),4);
    else
        carry <= '0';
        sum <= sum_temp(3 downto 0);
    end if; 
end process;   

end arch;

If you see the code, there are three inputs. The 4 bit BCD digits 'a' and 'b'. The carry_in comes from the carry output from the neighboring adder(in the LSB side). For the first adder(which adds the least significant digits) carry_in is '0'.

I have used the following test bench code to test the design. The code is synthesisable and have been tested using Xilinx ISE 13.1. It should work with other tools as well.

Testbench code for the BCD adder:-

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
 
ENTITY tb_test IS
END tb_test;
 
ARCHITECTURE behavior OF tb_test IS 

    COMPONENT bcd_adder
    PORT(
         a : IN  unsigned(3 downto 0);
         b : IN  unsigned(3 downto 0);
            carry_in : in std_logic;
         sum : OUT  unsigned(3 downto 0);
         carry : OUT  std_logic
        );
    END COMPONENT;
    
   signal a,b,sum : unsigned(3 downto 0) := (others => '0');
   signal carry,carry_in : std_logic;
 
BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: bcd_adder PORT MAP (
          a => a,
          b => b,
             carry_in => carry_in,
          sum => sum,
          carry => carry
        );
          
   -- Stimulus process
   stim_proc: process
   begin        
      a <= "1001"; b <= "1001"; carry_in <= '1'; wait for 100 ns;
        a <= "1000"; b <= "1001"; wait for 100 ns;
        a <= "0101"; b <= "1001"; wait for 100 ns;
        a <= "0011"; b <= "1001"; wait for 100 ns;
        a <= "1001"; b <= "0000"; carry_in <= '0'; wait for 100 ns;
        a <= "1001"; b <= "0111"; wait for 100 ns;
        a <= "0110"; b <= "0011"; wait for 100 ns;
      wait;
   end process;

END;

Note:- I have not given the code for cascading adders. But I hope its fairly simple to do it yourself.