Search code examples
signalsadditionvhdlbcdieee

BCD adder of 4-BCD-digit numbers in VHDL


I am trying to implement a BCD adder of two 4-digit numbers i.e. 16 bits using the code of 1-digit BCD adder I found here. I used this code as the basic module and then I created a top entity that created and connected 4 instances of this basic adder. I also did some conversions between the incompatible types in VHDL. The third file I created is a test bench that I simulated to check the implementation. So, the 1-digit BCD adder is:

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;

The top entity with four of these adders is:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.ALL;

entity TopAdder is
port(
    in1: in std_logic_vector(15 downto 0);
    in2: in std_logic_vector(15 downto 0);
    sum: out std_logic_vector(15 downto 0);
    carry: out std_logic);
end TopAdder;

architecture structural of TopAdder is

component 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 component;

signal carry1,carry2,carry3: std_logic;
signal in1_s,in2_s,sum_s: unsigned(15 downto 0);

begin
    in1_s <= unsigned(in1);
    in2_s <= unsigned(in2);
    sum <= std_logic_vector(sum_s);

    adder1: bcd_adder
    port map(in1_s(3 downto 0),in2_s(3 downto 0),'0',sum_s(3 downto 0),carry1);

    adder2: bcd_adder
    port map(in1_s(7 downto 4),in2_s(7 downto 4),carry1,sum_s(7 downto 4),carry2);

    adder3: bcd_adder
    port map(in1_s(11 downto 8),in2_s(11 downto 8),carry2,sum_s(11 downto 8),carry3);

    adder4: bcd_adder
    port map(in1_s(15 downto 12),in2_s(15 downto 12),carry3,sum_s(15 downto 12),carry);

end structural;

The test bench is:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY test1 IS
END test1;
ARCHITECTURE behavior OF test1 IS 
    COMPONENT TopAdder
    PORT(
         in1 : IN  std_logic_vector(15 downto 0);
         in2 : IN  std_logic_vector(15 downto 0);
         sum : OUT  std_logic_vector(15 downto 0);
         carry : OUT  std_logic
        );
    END COMPONENT;
   signal in1 : std_logic_vector(15 downto 0) := (others => '0');
   signal in2 : std_logic_vector(15 downto 0) := (others => '0');
   signal sum : std_logic_vector(15 downto 0);
   signal carry : std_logic;

BEGIN
   uut: TopAdder PORT MAP (
          in1 => in1,
          in2 => in2,
          sum => sum,
          carry => carry
        );

   stim_proc: process
   begin        
      wait for 100 ns;  

        in1<="0000000000000001";
        in2<="0000000000000010";
      wait for 100 ns;

        in1<="0000000000001001";
        in2<="0000000000000001";
      wait; 
   end process;
END;

The simulation shows the following: enter image description here

The problem is that the "big" adder as well as the "small" adders are not working for additions that create carry that has to be sent to the next "small" adder. As a result, the first addition in the test bench 1+2=3 is correct but the second one 9+1=0 is false. I tried some other additions, but those who generate carry are false in the simulation. What is wrong here?

Just to clarify: in the picture, the 4 repetitions of the signals carry_in,sum[3:0],carry represent the carry in, the sum, and the carry out of each small adder from the rightmost to the leftmost adder and from up to down in the simulation picture.


Solution

  • Your sensitivity list for your process in bcd_adder lists only a and b, but carry_in is also a significant input. On your second set of input values, the process in your adder2 instance only triggers when the inputs are initially assigned, and at this simulation time, the value of carry_in to that instance is still 0 due to delta delays through the adder1 instance.