View Course Path

VHDL code for full adder using structural method – full code and explanation

In this post, we will take a look at implementing the VHDL code for full adder using structural architecture. As is customary in our VHDL course, first, we will take a look at the logic circuit of the full adder. Since we are using the structural method, we need to understand all the elements of the hardware. After the RTL logic synthesis, we will also write a testbench for the full adder. We will also generate the RTL schematic and the simulation waveforms for our code.

Full-adder-using-two-half-adders-and-OR-gate
Full adder using two half-adders and OR gate

The structural architecture deals with the structure of the circuit. Every single port, every connection, and every component needs to be mentioned in the program.  This is the first program in our VHDL course, where we will be using the structural method. So we will take a look at every step in detail. For the full code, scroll down.

How do we design the full adder with half adders using structural modeling style?

The structural architecture deals with the physical circuit that we wish to code using VHDL. Think of legos. The circuit we design is the final masterpiece. Whereas the individual components are the tiny legos. These individual components of the main circuit, on the other hand, can be defined using any other architecture. (viz behavioral or dataflow)

It’s kind of obvious. For a second, think of the compiler as a friend who knows nothing about coding. If you say to them, “Hey! Attach a couple of half adders and an EXOR gate to get a full adder”.  Your friend (the compiler) will be puzzled. “Okay, fine,” they will exclaim, “but what is a full adder and an EXOR gate?”

And that would be a fair question. We need to define the functionality of the half adder and the EXOR gate before asking the compiler to combine them and provide the functionality of a full adder.

Hence, structural architecture first defines its components. And then proceeds to describe the structure in which the components connect to give the circuit we wish to obtain.

It will all become clearer when we start writing the code. For a detailed study and guide on using the structural architecture in VHDL check out this post.

Explanation of the VHDL code for full adder using structural modeling method. How does the code work?

In the structural modeling style, as we saw above, we first define the components. In the full adder circuit, we have two half adders and an OR gate.

If you are not familiar with the circuits for these two components, we have you covered. You can read more about the half adders here and the OR gate or any other logic gate here. Moving on, we will define only one of the two half adders.

In this style of modeling, we can define a component once and use it multiple times throughout the main structural code. As we progress towards more complex circuits, we will use more components. For example, in the VHDL code for an ALU using the structural method, we use five components.

VHDL code for the half adder (Components U1 and U2)

We will be using the dataflow modeling style to define this component. Notice how each component definition starts with its own set of libraries. Almost as if it were a self-sufficient piece of code on its own. This is an essential feature of the structural model of coding in VHDL.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity HA is

Port ( A,B : in  STD_LOGIC;

       S,C : out  STD_LOGIC);

end HA;


architecture dataflow of HA is


begin

S <= A XOR B;

C <= A AND B;

end dataflow;

VHDL code for the OR gate (Component U3) 

We will be using the dataflow modeling style to define this component too.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity ORGATE is

     Port ( X,Y : in STD_LOGIC;

              Z : out STD_LOGIC);

end ORGATE;


architecture dataflow of ORGATE is


begin


Z <= X OR Y;

end dataflow;

Now that both the components are defined, we will start with the main code for the entire circuit. First, we will declare the entity. Here we need to mention all the inputs and outputs of the main circuit.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity FAdder is

Port ( FA, FB, FC : in STD_LOGIC;

          FS, FCA : out STD_LOGIC);

end FAdder;

Next comes the architecture statement. Usually, the architecture statement is followed by the begin statement.

But not here.

In the structural method of coding in VHDL, we need to connect the pre-defined components to the main program. We do this by using something known as the Component declaration statement. This is pretty similar to the entity statement in terms of syntax. The only difference is that the word entity is swapped by the word component. Observe.

architecture structural of FAdder is

component HA is

Port ( A,B : in STD_LOGIC;

       S,C : out STD_LOGIC);

end component;

component ORGATE is

Port ( X,Y: in STD_LOGIC;

         Z: out STD_LOGIC);

end component;

Next, we will declare all the signals in the circuit using the signal declaration statements. The signals will be of STD_LOGIC since that’s the datatype, we used for our port declarations.

SIGNAL S0,S1,S2:STD_LOGIC;

And now we

begin

The main body of the program is simple. All you need to do is to list each component (U1, U2, and U3) and assign the signals to their appropriate ports for each component.

U1:HA PORT MAP(A=>FA,B=>FB,S=>S0,C=>S1);

U2:HA PORT MAP(A=>S0,B=>FC,S=>FS,C=>S2);

U3:ORGATE PORT MAP(X=>S2,Y=>S1,Z=>FCA);

end structural;

VHDL code for full adder using the structural method

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

entity HA is
Port ( A,B : in  STD_LOGIC;
       S,C : out  STD_LOGIC);
end HA;

architecture dataflow of HA is

begin

S <= A XOR B;
C <= A AND B;

end dataflow;

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

entity ORGATE is
     Port ( X,Y : in STD_LOGIC;
              Z : out STD_LOGIC);
end ORGATE;

architecture dataflow of ORGATE is

begin


Z <= X OR Y;

end dataflow;


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

entity FAdder is
Port ( FA, FB, FC : in STD_LOGIC;
          FS, FCA : out STD_LOGIC);
end FAdder;

architecture structural of FAdder is

component HA is
Port ( A,B : in STD_LOGIC;
       S,C : out STD_LOGIC);
end component;

component ORGATE is
Port ( X,Y: in STD_LOGIC;
         Z: out STD_LOGIC);
end component;

SIGNAL S0,S1,S2:STD_LOGIC;

begin

U1:HA PORT MAP(A=>FA,B=>FB,S=>S0,C=>S1);
U2:HA PORT MAP(A=>S0,B=>FC,S=>FS,C=>S2);
U3:ORGATE PORT MAP(X=>S2,Y=>S1,Z=>FCA);

end structural;

Testbench for full-adder using VHDL

We will be writing a testbench using process and assert statements. You can learn all about writing testbenches in VHDL here.

library IEEE;
use IEEE.std_logic_1164.all;

entity adder_process_tb is
end entity;

architecture tb of adder_ff_process_tb is
component FAdder is
Port ( FA, FB, FC : in STD_LOGIC;
FS, FCA : out STD_LOGIC);
end component;

signal FA, FB, FC, FS, FCA : STD_LOGIC;

begin

uut : FAdder port map(
FA =>FA, FB =>FB,
FC => FC, FS => FS, FCA => FCA);

stim : process 
begin

FA <= '0';
FB <= '0';
FC <= '0';
wait for 10 ns;
assert ((FS = '0') and (FCA = '0'))
report "test failed for input combination 000" severity error;

FA <= '0';
FB <= '0';
FC <= '1';
wait for 10 ns;
assert ((FS = '1') and (FCA = '0'))
report "test failed for input combination 001" severity error;

FA <= '0';
FB <= '1';
FC <= '0';
wait for 10 ns;
assert ((FS = '1') and (FCA = '0'))
report "test failed for input combination 010" severity error;

FA <= '0';
FB <= '1';
FC <= '1';
wait for 10 ns;
assert ((FS = '0') and (FCA = '1'))
report "test failed for input combination 011" severity error;

FA <= '1';
FB <= '0';
FC <= '0';
wait for 10 ns;
assert ((FS = '1') and (FCA = '0'))
report "test failed for input combination 100" severity error;

FA <= '1';
FB <= '0';
FC <= '1';
wait for 10 ns;
assert ((FS = '0') and (FCA = '1'))
report "test failed for input combination 101" severity error;

FA <= '1';
FB <= '1';
FC <= '0';
wait for 10 ns;
assert ((FS = '0') and (FCA = '1'))
report "test failed for input combination 110" severity error;

FA <= '1';
FB <= '1';
FC <= '1';
wait for 10 ns;
assert ((FS = '1') and (FCA = '1'))
report "test failed for input combination 111" severity error;
wait;

end process;
end tb;

RTL schematic

Full_Adder_Structural-RTL

Simulation waveform

Full_Adder_Structural-Waveform

Edit: Post updated with the testbench, RTL Schematic, and Simulation Waveform by Deepak Joshi.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.