The simplest form of adder is Ripple carry adder. But sometimes we might need adders which are faster than that. That is when Carry look ahead adders come to the rescue.
By calculating all the carry's in advance, this type of adder achieves lower propagation delays and thus higher performance. The disadvantage comes from the fact that, as the size of inputs goes beyond 4 bits, the adder becomes much more complex.
In this post I have written the VHDL code for a 4 bit carry look ahead adder. For the block diagram and explanation of the logic, you might want to see pages 1 to 3 in this pdf.
cla_adder.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity cla_adder is
port( A,B : in std_logic_vector(3 downto 0);
cin : in std_logic;
S : out std_logic_vector(3 downto 0);
cout : out std_logic
);
end cla_adder;
architecture Behavioral of cla_adder is
signal P,G : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";
signal C : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00000";
component cla_block is
port (
P : in std_logic_vector(3 downto 0);
G : in std_logic_vector(3 downto 0);
C : out std_logic_vector(4 downto 0);
cin : in std_logic
);
end component;
begin
--first level
P <= A xor B;
G <= A and B;
--second level
gen_c : cla_block port map(P,G,C,cin);
--third level
S <= P xor C(3 downto 0);
cout <= C(4);
end Behavioral;
cla_block.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity cla_block is
port (
P : in std_logic_vector(3 downto 0);
G : in std_logic_vector(3 downto 0);
C : out std_logic_vector(4 downto 0);
cin : in std_logic
);
end cla_block;
architecture Behavioral of cla_block is
begin
C(0) <= cin;
C(1) <= G(0) or (P(0) and cin);
C(2) <= G(1) or (P(1) and G(0)) or (P(1) and P(0) and cin);
C(3) <= G(2) or (P(2) and G(1)) or (P(2) and P(1) and G(0)) or (P(2) and P(1) and P(0) and cin);
C(4) <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0)) or (P(3) and P(2) and P(1) and P(0) and cin);
end Behavioral;
Testbench code:
I have used the same testbench code(tb_adder.vhd), at the bottom of this post. But make sure you change the name of the initiated entity.
Simulated waveform:
The waveform should look like this. The code checks for all the input combinations and the signal "error" shows the number of errors. If all goes well, "error" signal should remain at zero.
By calculating all the carry's in advance, this type of adder achieves lower propagation delays and thus higher performance. The disadvantage comes from the fact that, as the size of inputs goes beyond 4 bits, the adder becomes much more complex.
In this post I have written the VHDL code for a 4 bit carry look ahead adder. For the block diagram and explanation of the logic, you might want to see pages 1 to 3 in this pdf.
cla_adder.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity cla_adder is
port( A,B : in std_logic_vector(3 downto 0);
cin : in std_logic;
S : out std_logic_vector(3 downto 0);
cout : out std_logic
);
end cla_adder;
architecture Behavioral of cla_adder is
signal P,G : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";
signal C : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00000";
component cla_block is
port (
P : in std_logic_vector(3 downto 0);
G : in std_logic_vector(3 downto 0);
C : out std_logic_vector(4 downto 0);
cin : in std_logic
);
end component;
begin
--first level
P <= A xor B;
G <= A and B;
--second level
gen_c : cla_block port map(P,G,C,cin);
--third level
S <= P xor C(3 downto 0);
cout <= C(4);
end Behavioral;
cla_block.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity cla_block is
port (
P : in std_logic_vector(3 downto 0);
G : in std_logic_vector(3 downto 0);
C : out std_logic_vector(4 downto 0);
cin : in std_logic
);
end cla_block;
architecture Behavioral of cla_block is
begin
C(0) <= cin;
C(1) <= G(0) or (P(0) and cin);
C(2) <= G(1) or (P(1) and G(0)) or (P(1) and P(0) and cin);
C(3) <= G(2) or (P(2) and G(1)) or (P(2) and P(1) and G(0)) or (P(2) and P(1) and P(0) and cin);
C(4) <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0)) or (P(3) and P(2) and P(1) and P(0) and cin);
end Behavioral;
Testbench code:
I have used the same testbench code(tb_adder.vhd), at the bottom of this post. But make sure you change the name of the initiated entity.
Simulated waveform:
The waveform should look like this. The code checks for all the input combinations and the signal "error" shows the number of errors. If all goes well, "error" signal should remain at zero.
In the "behavorial" of cla_block.. to compute "C" you have used OR wherever required?
ReplyDeleteWe are adding terms, right? So, we should use XOR, right?
Or, is it because, we are only interested in if there is a carry or not, hence we use OR?
check the pdf link in the article for the block diagram and implementation details.
Deletewat is the vhdl programme for pipelined floating point adder
ReplyDelete