Structural Design in VHDL
using Components and Packages
Revised by: Basawaraj
Last modified: 04/23/2014
Introduction
VHDL specification permits two types of circuit description namely behavioral and structural. There are advantages and disadvantages to using either behavioral or structural descriptions. Behavioral description, because it attempts to describe the behavior of the circuit, is easier to code but has some serious disadvantages such as, not all statements are synthesizable (converted into hardware equivalent); debugging behavioral code is difficult, especially description of large circuits; no standard algorithms for synthesizing code. Unlike behavioral description which codes a circuit as a single VHDL code file, in structural description the circuit is first divided into small sub-circuits or “blocks” that together form the whole circuit and the sub-circuits are all described in individual files that are later linked together in a top-level file. The sub-circuits are similar to functions used in various programming languages. Ease of debugging and standard synthesizing algorithms are some of the advantages of structural description. Another advantage of structural description is that it permits parallel development of the circuit, i.e. different teams can individually work on design, development and testing of the sub-circuits that can then be combined. In addition the sub-circuits once designed can be easily reused in multiple circuits.
Example
Circuit for Structural Description
Consider a 4-bit Johnson counter; it can either be described as a behavioral circuit using a “black-box” description (Fig. 1(a)) or as a structural circuit using D flip-flops (Fig. 1(b)).
Fig.
1 (a): 4-bit Johnson Counter Fig.
1 (b): 4-bit Johnson Counter using D flip-flops
Note: - Johnson counter is a type of ring counter with the complement of the output of last register fed to the input of the first register; while a ring counter is a circular shift register with the output of the last register fed to the input of the first register.
VHDL code for D
flip-flop
Truth table and NAND implementation of clocked D
flip-flop are shown below. ‘x’ in Table 1 represents
‘Do not care’ condition, i.e. the circuit operation is identical whether the
value is high (1) or low (0) for that input.
Table 1: Positive edge triggered D
Flip-Flop Truth Table
CLK |
Q(t) |
D |
Q(t+1) |
0 |
x |
x |
Q(t) |
1 |
x |
x |
Q(t) |
1 -> 0 (Negative edge) |
x |
x |
Q(t) |
0 -> 1
(Positive edge) |
x |
x |
D |
Fig. 2: NAND implementation of
positive edge triggered D flip-flop
D flip-flop can
either be described as behavioral circuit using the truth table above or as a structural
code using the NAND implementation shown above. Both these implementations are
provided below. Note: in the code here is represented as Qbar.
Behavioral description of D flip-flop
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DFF is
port( D: in std_logic;
CLK: in std_logic;
Q: out std_logic;
Qbar: out std_logic
);
end DFF;
architecture behv
of DFF is
begin
process(D, CLK)
begin
-- clock high
if (CLK’event
and CLK='1') then
Q <= D;
Qbar <= not(D);
end if;
end process;
end behv;
----------------------------------------------
Structural description of D flip-flop
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DFF is
port( D: in bit;
CLK: in bit;
Q: out bit;
Qbar: out bit
);
end DFF;
architecture struct
of DFF is
signal n1, n2, n3, n4: bit;
signal q1, q1bar: bit;
begin
Q <= q1;
Qbar
<= q1bar;
q1bar <= (q1 nand n3);
q1 <= (q1bar nand n2);
n4 <= (D nand n3);
n3 <= not(CLK and n2 and n4);
n2 <= (CLK nand n1);
n1 <= (n2 nand n4);
end struct;
----------------------------------------------
VHDL Code for Johnson
Counter: Structural Description
Step 1: The first step involves creating
the project for Johnson counter and adding the D flip-flop description to the
project.
1. Using description from Lab1 create a new project Counter.
2. Use the “Add New File” option to add a VHDL description of the D flip-flop, name the VHDL file DFF. Note: You can use either the behavioral or structural description, but use of the structural description is recommended.
3. Compile and simulate the D flip-flop to test that its operation is consistent with the truth table give in Table 1.
Now that we have created the requisite project and added the D flip-flop to it the next step is to create the counter. There are three options to creating the structural description of Johnson counter: a) components, b) packages, and c) libraries. Here we will consider only components and packages.
Table 2: Johnson Counter Truth Table
Q(0) |
Q(1) |
Q(2) |
Q(3) |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
Repeat |
Step 2: The next step is to use the D flip-flop to create the Johnson counter.
Option 1: The first option is to use D flip-flop as a component to create Johnson counter.
This involves the following steps:
1. To the Counter project created in Step 1 above, using the “Add New File” option, add a new source file named JohnsonCounter. The source code of this file is given below; you can copy and paste it.
2. Compile and simulate this new source file, use “Compile All” option. Verify that its operation is consistent with the truth table give in Table 2.
Note: You can use more than one component subject to two requirements, a) all components are declared in the architecture declarative section; and b) VHDL code of all the components used are added to the project.
Structural description of Johnson
Counter using component
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity JohnsonCounter
is
port (
Clk : in bit;
Q : out bit_vector(3
downto 0));
end JohnsonCounter;
architecture Structural_Cnt
of JohnsonCounter is
signal Q1 : bit_vector(3 downto 0);
signal Q1bar : bit_vector(3 downto 0);
-- begin component declaration
-- note component’s have to be declared in the
-- architecture
declaration section, i.e. between
-- architecture
declaration and architecture begin statement.
component
DFF is
port
( D : in bit;
CLK : in bit;
Q : out bit;
Qbar : out bit
);
end
component;
-- end component declaration
begin
Q <= Q1;
U0 : DFF port
map (Q1bar(3), CLK, Q1(0), Q1bar(0));
U1
: DFF port map (Q1(0), CLK, Q1(1), Q1bar(1));
U2
: DFF port map (Q1(1), CLK, Q1(2), Q1bar(2));
U3
: DFF port map (Q1(2), CLK, Q1(3), Q1bar(3));
end Structural_Cnt;
----------------------------------------------
Option 2: The second option is to use D flip-flop in a package to create Johnson counter.
Using component declaration, as in option 1 above, necessitates declaring entities of all the components used. This option, component declaration, while simple has some readability issue, i.e. makes the code less readable especially if there are a large number of components to be declared. Packages are one option to handle this issue. Packages are VHDL files that list one or more components, the VHDL code of the components (consisting of requisite entity-architecture pair) should be in the same directory as the “package” file.
Structural design using packages involves the following steps:
1. To the Counter project created in Step 1 above, using the “Add New File” option, add a new source file named packageflipflop. The source code of this file is given below; you can copy and paste it.
Package containing declaration of
required components
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package packageflipflop
is -- begin package declaration
-- begin component declaration
component DFF is
port(D : in bit;
CLK : in bit;
Q : out bit;
Qbar :
out bit);
end component
DFF;
-- declare any additional components, say other flip-flops here
-- end component declaration
end package packageflipflop;
-- end package declaration
----------------------------------------------
2. To the Counter project, using the “Add New File” option, add another source file named JohnsonPack. The source code of this file is given below; you can copy and paste it. This is the VHDL code Johnson counter and uses package declaration to define components that are used. Note: The major difference between this VHDL code and the code with component declaration is the lack of component declaration in JohnsonPack code. The declaration of the package having the D flip-flop, along with the library declarations, at the beginning of the code allows the architecture to access the details necessary for using the component.
Structural description of Johnson
Counter using package
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.packageflipflop.all;
-- Package declaration
entity JohnsonPack
is
port (
Clk : in bit;
Q : out bit_vector(3
downto 0));
end JohnsonPack;
architecture Structural_Cnt
of JohnsonPack is
signal Q1 : bit_vector(3 downto 0);
signal Q1bar : bit_vector(3 downto 0);
-- note that we do not need to declare
components,
-- D flip-flop in this case, as we have declared the
-- package containing D flip-flop
component along with
-- library declarations.
begin
Q <= Q1;
U0 : DFF
port map (Q1bar(3), CLK, Q1(0), Q1bar(0));
U1
: DFF port map (Q1(0), CLK, Q1(1), Q1bar(1));
U2
: DFF port map (Q1(1), CLK, Q1(2), Q1bar(2));
U3
: DFF port map (Q1(2), CLK, Q1(3), Q1bar(3));
end Structural_Cnt;
----------------------------------------------
3. Compile and simulate this new source file, use “Compile All” option. Verify that its operation is consistent with the truth table give in Table 2.
Note:
1. Libraries are collection of packages and/or functions.
2. On Windows, if you installed Active-HDL Student Edition in C:\ drive using the setting suggested here then the standard/built-in/vendor libraries are located at
C:\Aldec\Active-HDL Student Edition\vlib
3. The first line in all the VHDL codes above is:
library ieee;
This line acts as a pointer to the ieee library (ieee.lib) located at: C:\Aldec\Active-HDL Student Edition\vlib\ieee
4. The next line is,
use ieee.std_logic_1164.all;
This instructs the tool to use all entities in the std_logic_1164 package. Note that there are multiple packages, each with many entities, inside the ieee library file. Also, if the first line, i.e. library ieee, is absent (or not included) you will get an error. This is because the command “use ieee.std_logic_1164.all” instructs the Active-HDL (or Xilinx ISE Project Navigator) to use std_logic_1164 package in ieee.lib but the pointer to the location of the library is missing.
This package includes definition of standard keywords/commands such as bit, bit_vector, std_logic, std_logic_vector, etc and must always be included at the beginning.
5. User defined libraries, similar to ieee standard library, can be in any directory that is accessible to the tool (e.g. Active-HDL). Hence user defined packages included in a library can also be in any directory, but if the packages have not been added to a library then they must be in the same directory as the projects using them.