0

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.

mgus
  • 808
  • 4
  • 17
  • 39
  • In addition to fru1tbat's answer pointing out carry_in isn't in the sensitivity list for the unnamed process in bcd_adder, you're test1 test bench code doesn't match your waveform image. You could add a `wait for 100 ns;` statement right before the final wait statement to allow the display of he last addition of 9+1. Otherwise simulation stops where your yellow cursor is. –  Feb 03 '15 at 16:45
  • It may not be really important, but what you're saying is not correct. The `wait` statement in my case kept the simulation for 1000 nanoseconds in total. There has to be an option in Xilinx that sets that value regardless of the testbench. If I had used `wait for 100 ns` instead of `wait` the total time would be 300ns which would also be enough to see the result. – mgus Feb 03 '15 at 19:19
  • A simulation finishes when TIME reaches TIME'HIGH (IEEE Std 1076-2008, 14.7.5.3 a) ), when no further events are scheduled TIME is advanced to TIME'HIGH (14.7.5.1 para 2, a) ). If your tool adds 800 ns it added a process not in your code and it's not implied by the final wait. Changing the final wait to wait for 100 ns; execution would resume after 100 ns (14.7.5.1 para 2, c) ) "The next time at which a process resumes"). Other VHDL tools aren't guaranteed to have a creative implementation. (I was checking fru1tbat's answer, lacking demonstration, I upvoted both question and answer). –  Feb 03 '15 at 21:46

1 Answers1

0

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.

fru1tbat
  • 1,605
  • 9
  • 16