6.111 > FPGA Labkit > Xilinx Tools Tutorial

Xilinx Tools Tutorial


The Xilinx Integrated Software Environment (ISE) is a powerful and complex set of tools. The purpose of this guide is to help new users get started using ISE to compile their designs. This guide provides a very high-level overview of how the tools work, and takes the reader through the process of compiling. The ultimate reference to ISE is of course the official documentation, which is installed on every PC in the lab, and is available from the Xilinx website. Because the documentation is so voluminous, this guide will attempt to provide some help with finding the right sections of the documentation to read. Don't miss the required reading section at the end of this guide which points out some sections of the documentation that every 6.111 student should read before beginning a complex labkit project.

From HDL to FPGA

The process of converting hardware design language (HDL) files into a configuration bitstream which can be used to program the FPGA, is done several steps.

First, the HDL files are synthesized. Synthesis is the process of converting behavioral HDL descriptions into a network of logic gates. The synthesis engine takes as input the HDL design files and a library of primitives. Primitives are not necessarily just simple logic gates like AND and OR gates and D-registers, but can also include more complicated things such as shift registers and arithmetic units. Primitives also include specialized circuits such as DLLs that cannot be inferred by behavioral HDL code and must be explicitly instantiated. The libraries guide in the Xilinx documentation provides an complete description of every primitive available in the Xilinx library. (Note that, while there are occasions when it is helpful or even necessary to explicitly instantiate primitives, it is much better design practice to write behavioral code whenever possible.)

In 6.111, we will be using the Xilinx supplied synthesis engine known as XST. XST takes as input a verilog (.v) file and generates a .ngc file. A synthesis report file (.srp) is also generated, which describes the logic inferred for each part of the HDL file, and often includes helpful warning messages.

The .ngc file is then converted to an .ngd file. (This step mostly seems to be necessary to accommodate different design entry methods, such as third-part synthesis tools or direct schematic entry. Whatever the design entry method, the result is an .ngd file.)

The .ngd file is essentially a netlist of primitive gates, which could be implemented on any one of a number of types of FPGA devices Xilinx manufacturers. The next step is to map the primitives onto the types of resources (logic cells, i/o cells, etc.) available in the specific FPGA being targeted. The output of the Xilinx map tool is an .ncd file.

The design is then placed and routed, meaning that the resources described in the .ncd file are then assigned specific locations on the FPGA, and the connections between the resources are mapped into the FPGAs interconnect network. The delays associated with interconnect on a large FPGA can be quite significant, so the place and route process has a large impact on the speed of the design. The place and route engine attempts to honor timing constraints that have been added to the design, but if the constraints are too tight, the engine will give up and generate an implementation that is functional, but not capable of operating as fast as desired. Be careful not to assume that just because a design was successfully placed and routed, that it will operate at the desired clock rate.

The output of the place and route engine is an updated .ncd file, which contains all the information necessary to implement the design on the chosen FPGA. All that remains is to translate the .ncd file into a configuration bitstream in the format recognized by the FPGA programming tools. Then the programmer is used to download the design into the FPGA, or write the appropriate files to a compact flash card, which is then used to configure the FPGA.


By itself, a Verilog model seldom captures all of the important attributes of a complete design. Details such as i/o pin mappings and timing constraints can't be expressed in Verilog, but are nonetheless important considerations when implementing the model on real hardware. The Xilinx tools allow these constraints to be defined in several places, the two most notable being a separate "universal constraints file" (.ucf) and special comments within the Verilog model.

A .ucf file is simply a list of constraints, such as

net "ram0_data<35>" loc="ab25"
which indicates that bit 35 of the signal ram0_data (which should be a port in the top-level Verilog module) should be assigned to pin AB25 on the FPGA. Sometimes it is useful to combine several related constraints on one line, using "|" characters to separate constraints.
net "ram0_data<35>" loc="ab25" | fast | iostandard=lvdci_33 | drive=12;
The above example again assigns bit 35 of the signal ram0_data to pin AB25, and also specifies that the i/o driver should be configured for fast slew rate, 3.3V LVTTL level signaling (with a built-in series termination resistor), and a drive strength of 12mA. See the Xilinx documentation for more details, but don't worry: all of the pin constraints have been written for you (more on this later).

Constraints can also be specified within special comments in the Verilog code. For example,

reg [7:0] state;
// synthesis attribute init of state is "03";
The Xilinx synthesis engine will identify the phrase "synthesis attribute" within any comments, and will add the constraint following this phrase to the list of constraints loaded from a .ucf file. In the above example, the initial state of the state signal after the FPGA finishes configuring itself will be set to 8'h03. In general, it is bad form to specify the initial state of signals using constraints, rather than implementing a reset signal. In some advanced designs, however, such initializations are sometimes necessary.

The tools recognize a huge variety of constraints, and an entire section of the online manual is dedicated to explaining them. Fortunately, understanding a few simple constraints is sufficient for most designs.

ISE and the 6.111 Labkit

The FPGA used in the labkit has 684 i/o pins, and most of them are actually being used. To simplify the process of adding pin constraints to a new design, two template files have been developed The file labkit.v is a template top-level Verilog module. This module defines names for all of the signals going in or out of the FPGA. Additionally, it provides default assignments for all FPGA outputs, so that unused circuits on the labkit are disabled. A template constraints file, labkit.ucf ties the signals in labkit.v to the appropriate physical FPGA pins.

A Tutorial

Download the following source files:

Create a New Project

  1. Select "New Project" from the "File" menu
  2. Enter a project name and choose a project location. Be sure the top-level module type is set to HDL (hardware design language).
  3. On the next form, enter the target device information. The FPGA on the labkits is a Virtex 2 family XC2V6000, speed grade 4, in a BF957 package.
  4. The next form allows you to create a new source file. If you have already written the Verilog code for your project, click "Next" to advance to the next form, which allows you to add existing source files. You can also add existing files to your project later, after the project has been created.
  5. After creating or adding any source files, click "Next" until you reach the project summary form, and then click "Finish" to create the project.

Add Sources and Constraints

  1. If you did not add all of your Verilog source files when creating the project, add them now by choosing "Add Source..." from the "Project" menu.

Modify the Top-Level Template

  1. To instantiate the counter module, add the following code to labkit.v, just before the endmodule statement.
    counter counter1 (.clock(clock_27mhz), .led(led));
  2. The stock labkit.v file assigns a default value to the LED outputs. In order to drive the LEDs with the counter module, we need to delete the following line, which can be found near the end of labkit.v.
    assign led = 8'hFF; // Turn off all LEDs

Compile the Design

  1. The labkit.ucf file includes constraints for all of the FPGA outputs defined in labkit.v. Most designs, however, will not use all of these signals, in which case the synthesis engine will optimize the unused signals out of the design. It is therefore necessary to tell the place-and-route tool not to generate an error if it encounters a pin constraint for a (now) nonexistent signal. To do this, right-click on the "Implement Design" item in the process pane, and select "Properties...". Check the box to "allow unmatched LOC constraints".
  2. Make sure the top-level labkit module is selected in the sources window.
  3. Double click "Generate Programming File" in the tasks window. This will cause the "Synthesize", "Implement Design" and "Generate Programming File" tasks to be run in order. A green check mark will appear beside each task when it is successfully completed. It will take approximately 5 minutes for everything to complete. (The tools seem to hang for a few minutes while generating the pad report, but this normal.)

Move the Design to a Compact Flash Card

  1. In the process pane, double-click on "Generate PROM, ACE or JTAG file". (You may have to expand the "Generate Programming File" line to see this item.)
  2. The iMPACT programming tool will launch, and a wizard will ask you several questions about what you want to do. You want to generate a SystemACE file.
  3. When asked to choose between the CF and MPM versions of SystemACE, choose CF (Compact Flash). The operating mode is unimportant.
  4. It is not necessary to specify the size of the CF card.
  5. Choose a name and a location for the SystemACE file collection you are about to generate.
  6. SystemACE allows up to eight designs to be stored on a single CF card. A switch on the labkit selects which design will be loaded into the FPGA. Check the boxes for as many designs as you want to include on the CF card.
  7. iMPACT will ask you to add design files for each configuration. You can potentially add more than one design file for each of the eight configurations (if there were more than one FPGA on the board, for example), but for the labkits, only add one design per configuration.
  8. Ignore the warnings about changing the configuration clock.
  9. Once all of the configurations have been specified, choose "Finish" and generate the .ace files. This takes a minute or two.
  10. Right click anywhere in the upper pane of the iMPACT window (with the system diagram) and select "Copy to CompactFlash...". Select the collection you just generated and copy it to the CF card.
  11. Insert the CF card in the labkit. Make sure the configuration source is set to "JTAG/CF", and select the configuration selector switch to the appropriate number. Power on the labkit, and your configuration should load.
MIT 6.111 Introduction to Digital Systems, Updated April 18, 2004