In this post, we’ll implement the VHDL code for a full adder using structural architecture. To begin, we’ll review the logic circuit of the full adder, which you can check out in detail in our VHDL course. Since we’re using the structural approach, we’ll focus on understanding each hardware element, from the components to the connections. After synthesizing the RTL logic, we’ll also write a testbench for the full adder and generate the RTL schematic along with simulation waveforms. This step-by-step guide is perfect for those wanting to deepen their structural VHDL skills.

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. We will take a look at every step in detail. For the full code, scroll down.
Contents
How do we design a full adder using half adders in structural modeling?
In structural modeling, we describe the physical components of a circuit and their connections. Imagine building with Legos: the final circuit is your masterpiece, while the individual pieces are the Legos themselves. These components—such as half adders and XOR gates—can be defined using any architecture, such as behavioral or dataflow.
To explain, think of the compiler as someone unfamiliar with coding. If you tell them, “Attach a couple of half adders and an XOR gate to form a full adder,” they’d understandably be confused. “What is a full adder and what does an XOR gate do?” they’d ask.
That’s why, in structural modeling, we first define the functionality of each component—like the half adder and XOR gate—before connecting them to create the full adder circuit. The key is to break down the building blocks before assembling the complete structure.
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
A testbench in VHDL is a simulation environment used to verify the functionality of your design. For the full adder, the testbench provides a set of inputs and checks the outputs, ensuring that the circuit behaves as expected. It helps identify any issues early in the design process by simulating different input combinations and observing the resulting output. By using a testbench, you can test your full adder’s performance before it’s implemented in hardware.
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
An RTL (Register Transfer Level) schematic visually represents the logic of your design, showing how data moves between registers and how the components are connected. For the full adder, the RTL schematic provides a clear depiction of the structural architecture, illustrating the interconnections between the half adders, XOR gates, and the final output. It helps you verify that the design matches the intended behavior and provides insight into how your VHDL code translates into hardware logic.
Simulation waveform
A simulation waveform visually shows how the signals in your design behave over time. For the full adder, the simulation waveform demonstrates how the input values (A, B, Cin) and the output (Sum, Cout) change during different test cases. It helps you verify that the full adder works as expected, ensuring that the inputs correctly generate the desired outputs according to the truth table. By reviewing the waveform, you can catch timing issues, signal mismatches, or logic errors in the design.
Frequently Asked Questions (FAQs) about Full Adder using Structural Architecture
What is the structural architecture in VHDL?
Structural architecture in VHDL refers to designing the physical structure of a circuit by defining and connecting individual components. It involves describing each component’s ports, connections, and functionality to build a complete system. For instance, when implementing a full adder, you would define the half adders and logic gates like XOR, AND, and OR before combining them to form the final circuit.
How is a full adder implemented using VHDL?
A full adder can be implemented in VHDL by first defining the half adder and XOR gate components. Using structural modeling, you combine two half adders and an OR gate to create the full adder. Each component is described separately, and then they are connected to produce the desired sum and carry outputs.
What is a testbench in VHDL?
A testbench in VHDL is used to simulate and verify the functionality of your design. It acts as a virtual environment where you apply inputs to your design and check the outputs. A well-written testbench helps ensure that your full adder works as expected by simulating various input combinations and comparing the results with the expected truth table.
What does an RTL schematic do in VHDL?
An RTL (Register Transfer Level) schematic provides a graphical representation of the hardware described in your VHDL code. It shows the data flow between components and the logical relationships between registers, gates, and other elements. For a full adder, an RTL schematic helps visualize the design structure, making it easier to debug and understand how the circuit operates at a hardware level.
How do simulation waveforms help in VHDL?
Simulation waveforms provide a time-based visualization of the signals in your design. They help in debugging and verification by displaying how inputs and outputs change over time. For a full adder, the simulation waveform shows the transitions of the input signals (A, B, Cin) and the resulting output (Sum, Cout), allowing you to check if the full adder behaves correctly according to the expected logic.