Created on: 19 February 2013
Adding two unsigned 4-bit numbers in VHDL using the VHDL addition operator (+) – a 4-bit binary adder is written in VHDL and implemented on a CPLD.
There are many examples on the Internet that show how to create a 4-bit adder in VHDL out of logic gates (which boils down to using logical operators in VHDL). A full adder adds only two bits and a carry in bit. It also has a sum bit and a carry out bit. The idea is that a number of these 1-bit adders are linked together to form an adder of the desired length.
It may not be necessary to implement an adder in this way, as VHDL can use the addition operator (+) to add two numbers. We will look at adding two STD_LOGIC_VECTOR data types together.
The design is implemented on a CPLD on the home built CPLD board. Half of the switch bank on the board (4 switches) is used to input one of the values to be added, the other half of the switch bank is used to input the second value to be added. The result (sum) of the addition of the two 4-bit numbers is displayed on 5 LEDs.
From the previous tutorial, we know that we can add two numbers together that are of the STD_LOGIC_VECTOR data type if we use the STD_LOGIC_SIGNED or the STD_LOGIC_UNSIGNED package from the IEEE library, e.g.:
library IEEE; use IEEE.STD_LOGIC_UNSIGNED.ALL;
This enables us to use inputs connected to switches and outputs connected to LEDs of the STD_LOGIC_VECTOR type defined in the Ports section of the ENTITY part of the VHDL.
Adding two numbers in the ARCHITECTURE part of the VHDL is as simple as this:
SUM <= NUMBER1 + NUMBER2;
We will be using two 4-bit inputs connected to 4 switches each as our numbers that will be added together. So the size of these numbers will be 4 bits each (3 downto 0).
The biggest output number (sum) generated by adding two 4-bit numbers together will be 1111b + 1111b = 11110b. So the vector used for our sum needs to be 5 bits in length (4 downto 0).
The only problem with adding two 4 bit numbers in VHDL and then putting the result in a 5 bit vector is that the highest bit (or carry) will be truncated. In other words, even if the size of the sum vector is 5 bits, a 4 bit sum will be placed in it.
We will now look at two ways of implementing the same 4-bit binary adder and solve the problem of adding two 4-bit numbers and displaying the 5-bit result.
The first way of solving the problem of adding two 4-bit numbers and displaying the 5-bit result is to make the two 4-bit input numbers 5 bits in length, but keep the MSB of each number at 0.
This code shows how to implement the adder in VHDL:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity binary_4_bit_adder_top is Port ( NUM1 : in STD_LOGIC_VECTOR (4 downto 0) := "00000"; NUM2 : in STD_LOGIC_VECTOR (4 downto 0) := "00000"; SUM : out STD_LOGIC_VECTOR (4 downto 0)); end binary_4_bit_adder_top; architecture Behavioral of binary_4_bit_adder_top is begin SUM <= NUM1 + NUM2; end Behavioral;
The code makes all the vectors to be 5 bits wide. The two input vectors are initialized with a value of 00000b so that the MSB is always 0.
To implement the above code on the home built CPLD board, we need to compensate for the inverting inputs and outputs connected to the switches and LEDs by inverting all inputs and outputs:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity binary_4_bit_adder2 is Port ( NUM1 : in STD_LOGIC_VECTOR (4 downto 0) := "11111"; NUM2 : in STD_LOGIC_VECTOR (4 downto 0) := "11111"; SUM : out STD_LOGIC_VECTOR (4 downto 0)); end binary_4_bit_adder2; architecture Behavioral of binary_4_bit_adder2 is signal A : STD_LOGIC_VECTOR (4 downto 0); signal B : STD_LOGIC_VECTOR (4 downto 0); signal X : STD_LOGIC_VECTOR (4 downto 0); begin X <= A + B; -- compensate for inverting inputs and outputs A <= not NUM1; B <= not NUM2; SUM <= not X; end Behavioral;
In the above code, the inputs are initialized to 11111b because they will be inverted to 00000b by the code at the bottom of the ARCHITECTURE implementation.
The inputs from the switches (NUM1 and NUM2) are inverted before doing the addition. The result of the addition is inverted before displaying it on the LEDs (SUM).
This is a better solution to the problem of adding two 4-bit numbers and displaying the result in a 5-bit vector. The VHDL concatenation operator (&) is used to put a 0 in front of each of the the two 4-bit numbers before adding them.
The concatenation operator can be used to join extra data to the left or the right of the vector:
RESULT <= ('0' & NUMBER); -- join a 0 to the beginning of NUMBER and put into RESULT RESULT <= (NUMBER & '0'); -- join a 0 to the end of NUMBER and put into RESULT
VHDL code for the second adder example:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity binary_4_bit_adder3_top is Port ( NUM1 : in STD_LOGIC_VECTOR (3 downto 0); -- 4-bit number NUM2 : in STD_LOGIC_VECTOR (3 downto 0); -- 4-bit number SUM : out STD_LOGIC_VECTOR (4 downto 0)); -- 5 bit result end binary_4_bit_adder3_top; architecture Behavioral of binary_4_bit_adder3_top is begin SUM <= ('0' & NUM1) + ('0' & NUM2); end Behavioral;
Again, we need to compensate for the inverting inputs and outputs of the home built CPLD board. The VHDL code below works the same way as the code above, but inverts all inputs and outputs:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity binary_4_bit_adder4_top is Port ( NUM1 : in STD_LOGIC_VECTOR (3 downto 0); NUM2 : in STD_LOGIC_VECTOR (3 downto 0); SUM : out STD_LOGIC_VECTOR (4 downto 0)); end binary_4_bit_adder4_top; architecture Behavioral of binary_4_bit_adder4_top is signal A : STD_LOGIC_VECTOR (3 downto 0); signal B : STD_LOGIC_VECTOR (3 downto 0); signal X : STD_LOGIC_VECTOR (4 downto 0); begin X <= ('0' & A) + ('0' & B); -- compensate for the inverting inputs and outputs A <= not NUM1; B <= not NUM2; SUM <= not X; end Behavioral;