Using VHDL to Describe Adders

Objectives


1. Using Process Struct and If-then-else Statements

PROCESS is a VHDL construct that contains statements that are executed if there is a change in a signal in its sensitivity list. Sensitivity list is a list of signals in a PROCESS statement that are monitored to determine whether the PROCESS should be executed.

An IF statement executes one or more VHDL statements, depending on the state of a Boolean test condition. It has the following syntax format:


	IF  ___expression THEN

	    __statement;

	    __Statement;

	ELSIF   __expression  THEN

		__statement;

		__statement;

	ELSE

		__statement;

                __statement;

	END IF;

VHDL syntax requires an IF statement or a CASE statement to be written within a PROCESS block. A PROCESS is a construct containing statements that are executed if a signal in the sensitivity list of the PROCESS changes. The general format of a PROCESS is:

[label:] PROCESS (sensitivity list)

BEGIN 
	
	statement;

END PROCESS;

The following example demonstrates how the PROCESS struct and IF statements can be used to describe a half adder.

Example 1:

A half adder is described by using PROCESS STRUCT and IF_THEN_ELSE statement.

library IEEE;
use IEEE.std_logic_1164.all;


entity half_adder is 

 port(
		a	: in	std_logic;
		b	: in	std_logic;
		sum	: out	std_logic;
		carry	: out	std_logic
	);

end half_adder;


architecture arch1 of half_adder is

begin

  -- Your VHDL code defining the model goes here
  sum_process: process(a,b)
  begin 
       if ( a = b ) then
       		sum <= '0' after 5 ns;
       	else
       		sum <= ( a or b) after 5 ns;
       	end if;
       	
  end process;
  
  carry_process: process (a, b)
  begin
  		case a is
  		when '0' =>
  			carry <= a after 5 ns;
  		when '1' =>
  			carry <= b after 5 ns;
  		when others =>
  			carry <= 'X' after 5 ns;
  		end case;
  end process carry_process;	

end arch1;

2. Using Component Structure

The following table contains some important terms for using and understanding the COMPONENT structure.

Hierarchy:
	A group of design entities associated in a series of levels
	or layers in which complete designs form portions of another, 
	more general design entity.  The more general design is 
	considered to be the higher level of the hierarchy.

Component:
	A complete VHDL design entity that can be used as a part of 
	a higher-level file in a hierarchical design.

Component Declaration Statement:
	A statement that defines the input and output port names
	of a component used in a VHDL design entity.

Component Instantiation Statement:
	A statement that maps port names of a VHDL component to the
	port names, internal signals, or variables of a higher-level
	VHDL design entity.

Port:
	An input or output of a VHDL design entity or component.

Instantiate:
	To use an instance of a component.

Example 2:

Here is an example using COMPONENT STRUCTURE to describe a full adder.

library Libs;
library IEEE;
use Libs.VHDLPrims.all;
use Libs.mylib.all;
use IEEE.std_logic_1164.all;

entity full_a is 

 port(
		In1	: in	std_logic;
		In2	: in	std_logic;
		c_in	: in	std_logic;
		c_out	: out	std_logic;
		sum	: out	std_logic
	);

end full_a;


architecture arch1 of full_a is

  -- Component declarations
  component half_adder
  port (a, b: in std_logic;
  	 	sum, carry: out std_logic);
  end component;
  
  component or_2
  port (a, b: in std_logic;
  			c: out std_logic);
  end component;
  
  -- Signal declarations
  signal s1, s2, s3: std_logic;
  
begin

  -- Component interconnections
  H1: half_adder port map 
  		(a => In1, b => In2,
  		sum => s1, carry => s2);
  		
  H2: half_adder port map
  		(a => s1, b => c_in,
  		sum => sum, carry => s3);
  		
  O1: or_2 port map (a => s2, b => s3, c => c_out);

end arch1;

3. Using VHDL to Describe a 4-bit Parallel Adder

We can create a parallel adder in VHDL by using multiple instances of a full adder COMPONENT in the top level file of a VHDL design Hierarchy. The following diagram shows a graphical illustration of this concept.

	

To make this hierarchical design, we need the following:

1.	A separate component file for a full adder ( e.g. full_add.dwv), 
	saved in the folder on the library path. 

2.	A component declaration statement in the top level file of the 
	design hierarchy.

3.	A component instantiation statement for each instance of the 
	full adder component.

Each adder in the diagram is an instance of a component written in VHDL with ENTITY name full_add. We have learned different ways to create a VHDL file for a full adder. In this lab, let's use the following full adder file as the component for the 4-bit parallel adder.

library IEEE;
use IEEE.std_logic_1164.all;


entity full_add is 

 port(
		a	: in	std_logic;
		b	: in	std_logic;
		c_in	: in	std_logic;
		sum	: out	std_logic;
		c_out	: out	std_logic
	);

end full_add;


architecture adder of full_add is

begin

  -- Your VHDL code defining the model goes here
  sum   <= (a xor b) xor c_in;
  c_out <= ((a xor b) and c_in) or (a and b);

end adder;

The following shows the VHDL file for a 4-bit parallel adder using the above full adder components.

library IEEE;
library Libs;
use IEEE.std_logic_1164.all;
use Libs.VHDLPrims.all;
use Libs.mylib.all;


entity add4par is 

 port(
		c0	: in	std_logic;
		a	: in	std_logic_vector(4 downto 1);
		b	: in	std_logic_vector(4 downto 1);
		c4	: out	std_logic;
		sum	: out	std_logic_vector(4 downto 1)
	);

end add4par;


architecture arch1 of add4par is

  -- component declaration
  component full_add
     port(
       a, b, c_in: in std_logic;
       c_out, sum: out std_logic);
  end component;
  
  -- define signal for internal carry bit
  signal c: std_logic_vector(3 downto 1);
  
begin

  -- Four Component Instantiation Statements
  adder1: full_add
     port map ( a => a(1),
                b => b(1),
                c_in => c0,
                c_out => c(1),
                sum => sum(1));
                
  adder2: full_add
     port map ( a => a(2),
                b => b(2),
                c_in => c(1),
                c_out => c(2),
                sum => sum(2));
      
  adder3: full_add
     port map ( a => a(3),
                b => b(3),
                c_in => c(2),
                c_out => c(3),
                sum => sum(3));
                
  
  adder4: full_add
      
     port map ( a => a(4),
                b => b(4),
                c_in => c(3),
                c_out => c4,
                sum => sum(4));          
                             
end arch1;

In this example, the component ports of the full adder component are a, b, c_in, c_out, and sum. The connect ports for the instance adder1 are a(1), b(1), c0, c(1), and sum(1). The ripple carry from adder1 to adder2 is achieved by mapping the port c_in to c(1), which is also mapped to the port c_out of adder1. It is pretty obvious, you can see the similarities in adder2, adder3, and adder4.

4. Lab Assignments


This page last modified:
Friday, 21-Aug-2020 15:22:39 CST
Accessed     times.