CMPE 480 – ADVANCED DIGITAL LOGIC DESIGN
Department of Electrical and Computer Engineering
University of Alberta
VHDL Design Flow
VHDL Design Flow
his tutorial is intended to provide you with an introduction to the tools that
you will be using through the term. This tutorial will guide you through the
design flow of a digital system, from its modeling in a hardware description
language (VHDL) to its implementation in an FPGA. While this tutorial
attempts to expose you to the most common features of the tools, it will not
demonstrate all. Once completing the tutorial you are encouraged to explore the
capabilities of the tools. The more familiar you are with your design environment, the
more productive you will be.
When you finish this lab you will know how to:
Create a VHDL design and verify its syntax.
Create a test bench waveform.
Synthesize and implement your design.
Perform behavioral and post-place and route simulations of your design.
Create a configuration bitstream for an FPGA.
Background – VHDL Design Flow
STEP 1 - Design Entry
The first step in the design process is to input your design into a machine-readable
format. To do this you will use a Computer Aided Design (CAD) tool. In CMPE 480
we will use Xilinx Foundation. This is s typical CAD tool supports many design entry
methods, such as a schematic capture, HDL entry (VHDL/Verilog) or a component
netlist. In this course, all the designs are described using VHDL.
STEP 2 – Functional Simulation
Once a design has been described, the next step is to simulate it. This is done to verify
that the design will meet the requirements of its specification. The first type of
simulation that is performed is a Functional Simulation. This is also referred to as a
Behavioral simulation in Xilinx Foundation.
A behavioral simulation is used to verify that logical behavior of the circuit. It is very
important to realize that simulations of this type DO NOT contain any physical
implementation details, which means that they DO NOT include any component delay
timing information. Designs that pass a functional simulation are on their way to being
realizable in hardware, but will not necessarily work as expected.
It is also very important to realize that some statements in VHDL are not synthesizable
and are therefore included for simulation purposes only. Consider the following
Z <= A and B after 2ns;
The after qualifier is an arbitrary delay that cannot be realized in hardware, thus it is
not synthesizable and would be ignored by most synthesis tools. It is included to model
expected delays in a behavioral simulation.
STEP 3 - Synthesis
During synthesis, the CAD tool will interpret your VHDL design information and
infer standard building blocks to implement your design (registers, multiplexers, lookup
tables, adders, etc.). Subtle differences in your VHDL description can result in different
hardware being synthesized at this stage. Different hardware inferences can result in
large variations in system performance.
STEP 4 – Implementation
The Xilinx implementation process takes your design through the TRANSLATE, MAP,
and PLACE AND ROUTE sub-processes. The TRANSLATE process convert the
netlist generated from the synthesis process, into a form specific to the target device.
The MAP process translates the standard building blocks into the specific resources
available in the target hardware. The PLACE & ROUTE process picks up where the
MAP process leaves off by allocating specific resources (placing) and interconnecting
(routing) the placed design.
At the end of this process you can perform a post-place and route simulation. This is
the most accurate simulation available through the Xilinx toolset. It will give you an
indication of what to expect of your design once it is actually implemented.
STEP 5 – Device Configuration
After the design has been verified, a binary hardware configuration file is generated
(bitstream). This file is then downloaded into the FPGA via the JTAG interface.
Part I - Getting Started
In this tutorial you will create an 8-bit up/down counter using VHDL as the design
description language. Your design will be synthesized and a bitstream file will be
generated. The bitstream will be used to configure an FPGA in a Digilab board. You
will be able to interact with your counter through switches and push-buttons to control
its operation. The count will be shown in a set of 7-segment displays in a D2IO board.
Starting Xilinx Foundation
Double click on the Project Navigator shortcut icon on the desktop,
Start → Programs → Xilinx ISE 7.1i → Project Navigator
Creating a New Project
A project is a collection of all files necessary to create and to download a design to a
selected FPGA. We will begin by creating a new project:
1. Select File → New Project to open the new project dialog box.
2. Select a meaningful name for the project. A directory of the same name will be
created in the path shown in the Project Location.
3. Select HDL as the Top-Level Module Type, and click NEXT.
4. Fill in the properties as shown below:
In CMPE 480 we use a Spartan II XC2S200-PQ208-6 FPGA. Our synthesis tool will
be XST. We use ModelSim as our simulator and we will use VHDL as our hardware
description language. Remember those settings, because every project you create in this
class will have the same settings.
5. Click Next to proceed to the Create New
dialog box in the next section of the tutorial.
dialog box. We will fill this
Creating a VHDL Source
A block diagram of the up/down counter is illustrated below. It has five inputs:
CLOCK, DIRECTION, LOAD, RESET and COUNT_IN. The direction of the up/down
counter is indicated by the DIRECTION input (0 = down, 1 = up). The LOAD input sets
the count to the value that appears in the 8-bit bus COUNT_IN. When the RESET input
is ‘1’, the count is set to 0. There is one 8-bit bus output called COUNT_OUT, which
shows the current count.
Now we will generate a VHDL module where we will model the behaviour of the
1. Click on the New Source button in the Create New Source dialog box.
2. Select VHDL Module as the source type.
3. Enter counter as the file name.
4. Verify that the Add to project checkbox is selected, and then click NEXT.
5. Define the ports of your VHDL module in the Define VHDL Source dialog box.
column, enter the port names:
CLOCK, RESET, DIRECTION,
LOAD, COUNT_IN, and COUNT_OUT.
In the Direction column indicate whether each port is an input, output or inout.
The only output is COUNT_OUT, all the other ports are inputs.
Because COUNT_OUT and COUNT_IN are 8-bit buses, select 7 in the MSB (Most
Significant Bit) column, and 0 in the LSB (Least Significant Bit) column of each of
Your table should look similar to this:
6. Click NEXT in the dialog box and then click Finish in the next one to conclude the
declaration of your module.
7. Click NEXT in the New Project Wizard dialog box.
8. The dialog box that you see now allows you to add existing files to the project.
This is useful when some previously built modules are to be reused. Since this is
not our case, just click on Next, verify your project specifications and if everything
is correct click on Finish. If necessary, click on the Back button to correct some of
the project specifications.
Notice that Xilinx has created a new VHDL file using a standard template and the
information entered in the New Source Wizard. Some standard libraries have been
included, your entity has been defined and your architecture has been declared. By this
time, the VHDL module should look like this:
Defining the Architecture
Now that we have a design file to work with, let’s define the architecture (behavior) of
our module. Enter the following code exactly as it appears into the body of your
architecture. Take a few minutes to examine the VHDL code and understand how the
counter is modeled.
Creating a Test Bench
To perform a functional simulation, you will need a test bench. A test bench is another
VHDL file that is used as a wrapper to instantiate one copy of the design, to provide
inputs to your design and monitor the outputs. You can create this file manually, or
you can use the test bench waveform editor to create a standard template based test
bench which you can enhance later if required).
1. Select Project → New Source to open the new source dialog box. This should look
2. This time we will select Test Bench Waveform. Note that you could select VHDL
Test Bench or Verilog Test Fixture if you wanted to create the test bench
manually. In keeping with good naming, we will create our test benches’ with the
same name as the design they are intended to test and add the suffix ‘_tb’.
3. Once you have provided a name for your test bench, click NEXT. You are now
asked to associate your test bench with a source file. In this case we only have one
source file so select it, click NEXT. Verify your test bench settings, click FINISH.
4. You will now specify the timing parameters used during simulation. The Clock
high time and Clock low time together define the clock period for which the
design must operate. The Input setup time defines when inputs must be valid. The
Output valid delay defines the time after active clock edge when the outputs must
be valid. Set the Initial Length of Test Bench to 5000ns and then Click OK.
Defining the Simulation Inputs
Now you should see the HDL Bencher tool in your workspace window. This tool is
used to enter input stimulus and expected results graphically. Inputs are represented by
blue squares. Outputs are represented with yellow squares. Clicking in any colored
square will toggle its value (for single bit signals). The CLOCK signal has been initialized
for you, but you still need to define the other inputs.
1. Let’s start with the RESET. Click on cycle 1 so the signal is set high. Click again on
cycle 2 to set the signal low. We just defined a reset in the first cycle to initialize our
2. Click on cycle 1 of DIRECTION to set the signal high, and then go to 1900ns and
click again to set it back to low. We will count up for 8 cycles and then we will
count down for the rest of the test bench.
3. Click on cycle 1 of COUNT_IN, and enter the number 64. Click on LOAD at
4300ns so the signal is set to high. Click on the next cycle to set LOAD back to
low. We are setting the count to the value 64 after 4300ns.
Once you save your test bench, notice that it is automatically added to your project.
Also notice that it is ‘under’ the design module that the test bench was associated with.
Select the test bench file in the source window and notice the processes window
change. The processes available for a test bench are different from those available for a
VHDL file. Xilinx automatically generates a corresponding VHDL behavioral model
for the test bench waveform specified in the GUI. To view this file, select View
Generated Test Bench As HDL from the processes window with the test bench
selected in the source window. Test benches created in this fashion will have a *.vhw
We are now ready to simulate our design!
Now that we have created a test bench file, we
are ready to launch the simulator. The Xilinx
toolset does not include its own simulator.
Instead, they choose to partner with third party
tools. In CMPE 480, we will use Model
Technology’s ModelSim XE (Xilinx Edition).
ModelSim itself is a powerful tool and warrants
some extra investigation. For now, we will cover
only what we need to know to get going.
With the test bench selected in the source
window you should see something like the figure
on the left. Expanding the ModelSim Simulator
process we see each of the available types of
simulation listed. They are listed in order of less
to more accuracy from top to bottom
To perform a functional (behavioral) simulation,
simply double click Simulate Behavioral Model. This will launch ModelSim.
Let’s take a quick look at the ModelSim interface. ModelSim is a command line driven
tool . Everything that can be done via the GUI can be done via the command line, or
an automated script (macro). A command line reference is available on the course
website for those who wish to take advantage of the more advanced features. By
default, when ModelSim launches there are four windows displayed. Other windows
can be accessed via the View menu selection in the workspace window.
The main workspace window contains the Command Line Interface. In the LI, all of
the commands invoked by the Xilinx macros are displayed, as well as the output from
ModelSim itself, including any warnings or errors. The console also includes a prompt
where single commands can be entered manually. Examining the commands that are
echoed in this window will reveal more details about the simulators inner-workings.
Double clicking any errors displayed will open the Source window and highlight the
erroneous line in your VHDL description.
The structure window displays the hierarchy of your design. The top-level module will
always be your test bench. Embedded within the test bench is the Unit Under Test
(UUT). The UUT is your design file. If your design contains nested design modules,
each component will be listed in the structure window.
When you perform behavioral level simulations, modules
are listed in the structure window with the name given to
the component when it is instantiated. If you perform any
of the back-annotated simulations, the names listed in the
structure window are associated with the physical level
resources. This can make ‘drilling down’ much more
challenging. But more about that later.
The signal window will show all of the ports
declared in the entity definition for the selected
module. These signals can then be dragged into
the wave window to be monitored.
The wave window displays the results of the actual simulation. You will spend a lot of
time using this window, so it is a good idea to spend some time familiarizing yourself
with its capabilities. For example, you can customize your display by aligning, color
coding and selecting the radix for your signals and then File → Save Format to save the
display setting as a macro. You can then File → Load Format to restore your settings the
next time you run a simulation. This is very useful. Play here.
Once you are satisfied with the settings, print the waveform.
When printing your waveform, be sure that the area of interest in your
simulation takes up the entire display area. Zoom in our out as necessary to make this
true. It is in your best interest to make the display as readable as possible. Imagine that
you are giving this to your technically challenged boss. It should be very readable
without going into excruciating details. When annotating your waveform, make
sufficient comments so that a technically proficient colleague would be able to discern
the purpose, and the outcome of the simulation.
Once the design has been proven to work logically, we can turn our attention toward
the implementation details. That is, taking the design from the realm of the theoretical
to the actual. Close ModelSim.
Synthesis is a very straightforward step with the Xilinx toolset. Keep in mind that when
you execute a process in Xilinx, you are executing that process on the source file
currently selected in the sources window.
To synthesize your design, select it in the sources window and double click
Synthesize-XST. This will begin the synthesis process; monitor the console window
for any errors. If the synthesis was successful, a green check mark will appear beside
the synthesis process.
Once a design has been synthesized, it is time to address the physical implementation
details. For the most part, your CAD tools automatically handle these details. There are
a number of user definable constraints that can be specified to refine system
performance; most of which are related to timing constraints. We won’t cover those
issues at this point.
After all of the user constraints have been set, you are ready to implement your design.
Once again we will put our trust in the tools to perform the low level details required
for implementing our design into a specific hardware device.
major advantage of using an abstracted HDL language for digital design is
that it allows designers to focus on design issues and leave implementation details to
the CAD tools. This allows designers to test multiple architectures quickly. However,
this can also been seen as a disadvantage as the designer is no longer in direct control
of the hardware details required to implement their design. This can lead to uncertainty
in the debugging phase and an overall lack of understanding of the final circuit.
The implementation process is again very straightforward with the Xilinx toolset. Select
your design module in the sources window and double click the Implement Design
process. This can take some time if you have a large design or slow computer. Monitor
the console window for warnings or errors. Confirm that the process completed
Once a design has been implemented, a post place and route simulation can be
performed. This is the most accurate timing simulation that our tool can provide
because it knows all the details of our physical implementation.
Select the test bench in the sources window and then choose Simulate Post-Place &
Route VHDL Model in the processes window. This will launch ModelSim.
Take a close look to the transitions in COUNT_OUT, and compare this results to those
obtained with a behavioural simulation.
Download the file Lab0_FPGA.zip and extract it in your computer. This file contains a
project with a pre-built configuration that will abstract you from the hardware details
of the Digilab board where you will download your design. A block diagram of this
system is shown in the figure shown in the next page.
The D2IO driver controls the output of data to the 7-segment displays, and LEDs. It
also reads the inputs coming from the push-buttons and switches, and can provide
them to another module, such as our up/down counter. The LOAD, RESET, and
DIRECTION inputs are provided through the push-buttons. COUNT_IN is set through
the switches and the COUNT_OUT is displayed in two 7-segment displays.
1. In the Project Navigator select File → Open Project.
2. Select the project Lab0_FPGA, from the directory you just extracted.
Your Sources window should look like this:
Block diagram of the components in project Lab0_FPGA.
Adding your Up/Down Counter to the Project
You may have noticed that there is a question mark on the counter module of the
project. This shows that ISE cannot find a file with the VHDL module for the
counter. You need to add your own module here.
1. Select Project → Add Source.
2. Select your counter module from your previous project. Click on OPEN.
3. Select VHDL Design File as the type of the source.
4. Click on the toplevel module in the sources window and synthesize your design.
There should be no errors at this time.
Once the design is synthesized, the most basic user constraint that must be performed
is the pin assignment. Pin assignment is the process of associating logical ports with
physical pins. If you do not specify which pins your logical ports should be connected
to, the tools will randomly assign pin locations. This will not suffice in cases where our
target device is already located on a fixed Printed Circuit Board (as in our lab).
Pin assignments and other user-defined constraints are contained in a User Constraint
File (*.ucf). In this lab, we provide you with a pre-built UCF. In later labs you will learn
how to build one by yourself.
1. To add this file to the project:
2. Select Project → Add source.
3. Select the file toplevel.ucf and click on OPEN.
4. A dialog box will appear, asking you to associate the constraints file with a source.
Select toplevel from the list of options and then and click OK.
Configuring the FPGA
Once the pin numbers have been assigned to the logical ports, let’s create the
toplevel.bit file (the bit file will always have the same filename as the entity you are
implementing) and download it to the D2 board. Before you generate the bit file, select
the toplevel source file and right click the Generate Programming File process. Select
Properties. Select the Startup Options tab. For FPGA Start-Up Clock, use the pulldown box to select JTAG Clock.
Be sure that your D2 board is powered and the parallel cable is properly connected. If
you are at a station with a parallel port switch box, be sure that the switch is set to
Now we should be set. Expand the Generate Programming File process and double
click the Configure Device (iMPACT) process. If you have not implemented your
design at this point it will automatically be synthesized and implemented. The iMPACT
Device Configuration Utility should launch automatically.
When iMPACT runs it will ask you a few questions about what you are trying to do.
First select Boundary-Scan Mode. Click Next. Now select Automatically connect to
cable and identify Boundary-Scan chain. Click FINISH. An information box may
now pop-up. Read it.
You are now asked to specify a programming file. This will be our toplevel.bit file. Use
the dialog box to locate your programming file and click OPEN. At this point another
information box may pop-up. For some reason Xilinx seems to detect our XC2S200
device as a XCV200 device, so it gets a little confused. Don’t worry about it; we
actually do have a XC2S200 click YES. Now, simply right-click the device and select
The counter should be working by this time. The 7-segment displays in the board
should be showing the current count. Interact with the counter through the pushbuttons and switches and verify that the design is working as expected.
IO is assigned as follows:
Demonstration (8 marks)
Show your working implementation to the Lab Instructor or a TA.
Demonstrate the complete design functionality.
This demonstration is worth 80% of Lab 0.
Part II - Floorplanner and FPGA Editor (brief tutorial)
This section is an introduction to two new design tools that we will use during this lab:
the floorplanner and the FPGA Editor. In order to follow this tutorial you will first
need to create a VHDL module with the half-adder description that we discuss below.
Synthesize the sample design and verify its functionality with a behavioural simulation.
Sample Design – Half-Adder
Our sample design is a Half-Adder (HA). The HA performs bit-wise addition between
two input bits. We will examine a half-adder in more detail in Lab 1, but for now you
can use the code to learn how the floor planner works.
The VHDL equivalent of the external interface description is known as an
declaration. The HA entity declaration would appear as follows:
entity ha is
Port ( X
architecture Behavioral of ha is
Sum <= X xor Y;
Carry <= X and Y;
Floorplanning is particularly useful on structured designs and data path logic. With the
floorplanner, designers can see where to place logic for optimal results, placing data
paths exactly at the desired location on the die.
The floorplanner enables designers to plan a design prior to or after using Place-andRoute (PAR) software. Invoking floorplanner after a design has been placed and routed
allows designers to view and possibly improve the results of the automatic
implementation. In an iterative floorplan design flow, designers floorplan and place
and route interactively.
The logic placement in the floorplan window can be modified as often as necessary to
achieve design goals. Iterations of a floorplanned design can be saved for use later as a
constraints file during PAR.
In this lab we will use the floorplanner to define a user constraint file (UCF) containing
our pin assignments.
1. Select your design file in the sources window and expand the
toolbox in the processes window.
2. Double-click Assign Package Pins in the processes window.
3. The following message provides information about the UCF file creation process.
Information messages are denoted by the blue question mark on the left of the
dialog box. It is highly recommended that you read them. Click Yes, it will launch
the PACE editor.
4. The Pace editor allows you to graphically associate your logical ports to the
physical pins of your target package. Expanding the I/O Pins folder in the Design
Browser window will reveal the logical ports in your design. The ports are also
listed in the Design Object List. You can then drag and drop the logical ports onto
the pins you wish to assign them to (you will have to zoom in quite a bit to be
accurate at this). Alternately, you can type the desired pin number into the LOC
field in the Design Browser List. All pin numbers MUST be prefixed by a P. So if
you waned to assign logical port A to physical pin 7 you would type P7 in the LOC
field. Perform the pin assignment and save your work.
5. Once you save the settings, all of the information contained in the GUI interface is
written to a *.ucf file (the UCF file will have the same name as the design entity
that you are configuring) in your project folder. You can view the contents of the
file in a text editor. The pin assignment section will look similar to this:
#PACE: Start of PACE I/O Pin Assignments
NET "Carry" LOC = "P6" ;
NET "Sum" LOC = "P5" ;
NET "X" LOC = "P3" ;
NET "Y" LOC = "P4" ;
You can edit the text file directly if you wish to avoid use of the slower GUI.
6. Implement your design.
FPGA Editor is a graphical application used for displaying and configuring FPGAs.
This tool allows you to perform a variety of functions on your designs including:
Place and route critical components before running the automatic place and
Finish placement and routing if the routing program does not completely route
Add probes to your design to examine the signal states of the targeted device.
Create an entire design by hand (advanced users).
To view the final implementation of your design, ensure your design module is still
selected in the sources window.
1. Expand the Implement Design process.
2. Now expand the Place & Route process.
3. Double click View/Edit Routed Design (FPGA Editor). This will launch the FPGA
The FPGA Editor workspace includes three windows:
window, and World window.
Array window, List
The Array window displays a graphical representation of the FPGA device. The
device components and the interconnections (both logical and routed) between
these components are displayed in this window. When you zoom out at maximum
you should be able to see all of the 1176 configurable logic blocks (CLB) in the
Spartan II FPGA.
The List window displays a list of the components, nets, layers, paths, macros, and
constraints in your design. Use the pull-down list box at the top of the window to
specify the items you want displayed in the List window.
The World window shows the area of the device that is currently displayed in the
Array window. As you pan and zoom the Array window, notice the corresponding
changes in the size and position of the white rectangle within the World window.
Also, any objects selected in the Array window appear in the World window. You
can drag the white rectangle with the mouse button to pan the display to the
1. Zoom in into the Array and take a closer look to the CLB’s. When you zoom
in, the white rectangle in the world window will indicate your position in the
2. In the List window, select the component Sum_OBUF of type SLICE. This is
the slice of the CLB in which the HA has been implemented. Each CLB is
made up of two identical slices. Our HA is so small that it fits in a single slice.
3. Notice that a small red square appears on the World window when you click
on Sum_OBUF. This small square shows the exact location of the slice. Drag
the white rectangle until it covers the slice. A magnified view of the slice will be
available in the Array window. Zoom in until you can see the slice and its
connections to the FPGA pins.
4. Double click on the red CLB Slice in the Array window. A new window will
appear showing the internal architecture of the CLB slice and the resources
that were used to implement your design will be highlighted.
Any design that you implement in this lab must be realizable in these standard blocks.
Although not all FPGA architectures are identical, they are all based upon some regular
array of basic building blocks. So any design you ever build using an FPGA will
eventually be implemented into standard blocks. Understanding the physical
architecture you are targeting will allow you to maximize your design efficiency.
The following is an excerpt from the Spartan-II 2.5V Family Functional Description
(posted in the lab website):
The basic building block of the Spartan II CLB is the Logic Cell.
Each LC includes a 4-input function generator, carry logic, and a
storage element. Output from the function generator in each LC
drives the CLB output and the D input of the flip-flop. Each
Spartan II CLB contains four LCs, organized in two similar slices.
Spartan II function generators are implemented as 4-input Look-Up
Tables. In addition to operating as a function generator, each LUT
can provide 16x1-bit synchronous RAM. Furthermore, the two LUTs
within a slice can be combined to create 16x2-bit or 32x1-bit
synchronous RAM, or a 16x1-bit dual-port synchronous RAM.
Storage elements in the Spartan II slice can be configured either
as edge-triggered D-type flip-flops or as level sensitive latches.
The D inputs can be driven either by function generators in within
the slice of directly from slice inputs, bypassing the function
Demonstration (2 marks)
For Lab 0, show that you are familiar with the FPGA Editor to the Lab Instructor or a
TA. This demonstration is worth 20% of Lab 0.