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:
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.
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.