You are on page 1of 91

CUSTOMIZING THE PCI ADD-IN CARD

PROJECT

Submitted in partial fulfilment of the requirements for the degree of


Bachelor of Engineering

By

ARSIWALA MURTAZA A
DIPESH NEBHNANI
KOLI SWAPNIL P

Under the guidance of


Mrs.SAPNA PRABHU (Internal)
Mr. SUNIL KULKARNI (External)

Department of Electronics Engineering

Fr.Conceicao Rodrigues College of Engineering


Bandstand, Bandra (West), Mumbai 400050

University of Mumbai
April, 2008
Acknowledgement

Projects that find immediate industrial or research applications are a


rarity at the BE level. The fact that we were allowed to work on a
very current application and that too for a research institute like Tata
Institute of Fundamental Research (TIFR) behooves us to acknowledge
the contribution of quite a few people.
I would like to express my heartfelt gratitude to Mr. Deshpande, our
principal, and Mrs. Unnikrishnan, our HOD, for allowing us to work
on the project in the first place.
Mr. Sarkar (Pelletron section, TIFR), has played a major role in our
getting the project at TIFR.
We would like to thank our external guide, Mr. Sunil Kulkarni, for
guiding us through every stage of the process and virtually egging us
on towards project completion. We would also like to acknowledge
Mr. J. Gore’s (Pelletron section, TIFR) timely advice, which went a
long way in us understanding the finer aspects of our project. Since
reconfigurable hardware was an area of electronics with which we
were vaguely familiar with, the experience of Mr. Kulkarni and Mr.
Gore in this field has proved invaluable to us.
And finally, we would like to thank Mrs. Sapna Prabhu (Electronics
Deparment, Fr. CRCE), our internal guide, for making the PCI
protocol so much easier to understand and for being a steady source of
support throughout the duration of the project despite our
irregularities.

ii
Abstract

The project is being done for the BARC Branch of Tata Institute of
Fundamental Research (TIFR). A PCI card designed by the TIFR team,
houses an FPGA (XCS2S200 Package PQ208) which acts as a
controller. The project objective is to program the FPGA using VHDL
so that it emulates the PCI controller and ensure basic data transfer to
and from the card. This would set up the card for further applications
ranging from Data Acquisition to Data Processing.

iii
Contents

1) Introduction.....................................................................1

2) Review of
Literature........................................................................5

3) Introduction to
LogiCores........................................................................8

4) The PCI
core...............................................................................15

5) User
Application.....................................................................34

6) Design
Verification....................................................................48

7) Downloading and

Testing the
core...............................................................................58

8) Application.....................................................................69

iv
9) Further
Work.............................................................................70

10) Conclusion....................................................................72

11) References.................................................................... 73

12) Appendix........................................................................74

v
Chapter 1

Introduction

“The basic premise of this project is to serve as a stepping stone to a


faster, reliable and a more convenient Data Acquisition System”.
Data Acquisition Systems (DAQ) are an integral part of any control
system. They are used to collect data for processing or documentation
from a system under observation. The reliability of a system depends,
to a certain extent, on the integrity of the data collected through the
Data Acquisition System. Thus it is imperative that these systems
(DAQs) be accurate, lossless and operate at speeds equivalent to
processing speeds.
As technology has advanced through the years, the process of
acquiring data has become more innovative. In the days of yore, a
DAQ comprised of a technician logging data by manually observing
parameters at various checkpoints. Gradually, with improvements in
microprocessor technology, the technician was replaced wholly by
autonomous data monitoring and logging systems. In the 1980s, the
personal computing revolution gave a further boost to DAQs
technology. With increased processor speeds and the ability to
interface these systems directly to the processor, one saw a
remarkable improvement in the speed and reliability with which these
systems could work with data. The term data acquisition was now used
only in a titular capacity. This was because these systems could, in
addition to their original intended function, carry out a wide array of
processes.
These systems can be based upon any computer interface though the
most popular systems today are based on Ethernet, Peripheral
Component Interconnect (PCI) and Universal Serial Bus (USB). From
among them, the PCI interface affords the fastest data transfer rates
because it is directly connected to the system bus. The relevant
specifications of the PCI bus in comparison to the USB are as follows

1
 A 32 bit PCI bus supports a peak data transfer rate of
132Mbytes/second as opposed to a maximum of 12 Mbits/sec
which the USB supports.

 Both these protocols are not processor specific. This means that
the same hardware can be used on any platform which supports
the PCI or USB interface.

 The PCI protocol supports a full bitlevel specification of the


configuration registers necessary to support automatic device
detection and configuration.

 Both the interfaces support plug and play capability, the


distinction being that USB supports hot plug and play (devices
can be added during runtime) while PCI does not.

 Now, envision a Data Acquisition System in the form of a PCI


add in card which has a reconfigurable hardware element like a
Field Programmable Gate Array (FPGA) or a Complex
Programmable Logic Device (CPLD) in the form of the PCI
controller. This card could find limitless applications which
would be limited only by a programmer’s ability to write
Hardware Description Language (HDL).

The project is being done in the Pelletron Accerator section of the


BARC branch of Tata Institute of Fundamental Research (TIFR)--a
premiere research institute in India. They are working on a project
involving electron accelerators which requires extensive data logging
and analysis. A PCI card with an on-chip FPGA (XC2S200 package:
PQ208) has been designed by their research team. The FPGA is to be
programmed in HDL (VHDL) to emulate a PCI controller. Before the
card can be used for data acquisition, it is important to ensure that the
card satisfies the rigid timing specifications of the PCI protocol and
that basic data transfers are possible to and from the card. To ensure
reliability with the PCI protocol, a standard 32 bit PCI Logicore
available from Xilinx is being used. A core is a pre-synthesized
software written in HDL, which can be instantiated as a component in

2
the main project. After the core is customized to meet the desired
specification, a User Application which would enable us to perform
basic read and write operations from the card has to be written. A
User Application is a concomitant with the PCI Logicore, and is
written by the designer to describe the device function. Thus the core
ensures that the PCI protocol is maintained, while the User
Application defined the card function. A functional schematic of the
PCI card is shown below:

A successful attempt at data transfer from and into the card would
mean that the primary purpose of the project has been achieved, i.e.,
to set up the card for further applications. These applications could
range from a basic data collecting unit to a very complex data
processing device.
The project is very significant from the standpoint of data
acquisitions. After ensuring that basic operations can be performed,
an on chip Analog to Digital Converter (ADC) can be utilized to
monitor analog voltages at desired nodes. A User Application which
makes a log of this data can be written and the data can be made
available to a desktop computer on demand where it can be displayed
graphically. Thus, data can be monitored from the comfort of a
desktop PC.
PCI based DAQs available commercially, perform a similar function.
However an important distinction between the designed card and the
Application Specific devices which are readily available is that
reconfigurable hardware is being used in the former. The functionality
of the device can be changed as fast as a program can be written for it

3
in HDL. Thus the same card can be used as a simple data collecting
device or a highly complex computing unit which processes the data
on board and uses the desktop only as a display device.

The proceeding sections define logic cores and their utilization in


projects. The discussion then moves onto the PCI core, its generation,
customization and instantiation; and then the design of the User
Application. A chapter on testing the device explains how the FPGA is
programmed and then tested using Win Driver. Finally, applications of
such a card are discussed in brief followed by further work we
propose can be done with the card.

4
Chapter 2
Review of Literature

The feature that has revolutionized computers in the last decade and a
half is the plug and play capability of its peripherals. Right from
devices like graphic cards, Random Access memory and secondary
storage devices to Hot plug and play devices like Flash drives and
basic I/O devices like keyboards and mouse, they have made
interacting with and using computers a lot easier for the average
individual. Data transfer protocols like the SCSI (Small Computer
System Interface), USB (Universal Serial Bus), PCI (Peripheral
Component Interconnect) and more recently SATA (Serial ATA) have
aided fast data transfer speeds for these plug and play devices.
Hence, any exposure to these protocols, especially a chance to work
on developing such a device as our final year project would have been
welcome.
Thus, when Mr. Sunil Kulkarni, our external guide, asked us to work
on a project related to the PCI protocol, we readily accepted. Since
none of us had any experience with the subject at hand we had to
study various books and refer to umpteen manuals in order to get a
thorough understanding of the task at hand. This is how we went about
with it:
Our first task was to get ourselves acquainted with the PCI protocol.
For this we referred– The PCI Architecture by Tom Shanley and
Don Anderson.
The book begins by introducing the PCI specifications in light of its
advantages over other protocols. It gave us a firm grounding in how
the protocol works, important concepts like Targets and Initiators
(elementary concepts required to understand the project) and basic
signals that would be useful from an implementation point of view.
The project deals mainly with software, to be more precise, the PCI
LogiCORE. The Logicore (details in the proceeding chapters), is a
software code in one of the HDL languages which the user can utilize
in his project by instantiation. The core requires licences which can

5
be obtained from the Xilinx website. Our success depended on how
well we got acquainted with the core. For this, we had to refer to the
PCI Logicore Manual obtained from the Xilinx online help. This
manual describes in detail the following:
1) PCI and user interface signals (the signals that would be
utilized by the user of the core).

2) Configuration register settings.

3) Treatment of signals that one does not use.

4) Read and write protocol.

The examples in the logicore manual are in Verilog, thus a little


online help was required to translate these into VHDL.
In addition to this the PCI logicore User guides were required to
understand how the core was to be linked to the main project
(Instantiation).
We have used the Xilinx ISE 9.2i software suit for the project. This
suit provides the entire gamut of tools that we would require for
project development including Project Navigator, Architecture
Wizard, Constraints Editor, Floorplanner, FPGA Editor, iMPACT
and of course, the Core Generator. In order to acquaint ourselves
with these tools, we had to refer, quite frequently, to the Xilinx
Software Manuals. Now in case you think I m conjuring the Manuals
out of thin air, let me add one more to the list. To finally program our
FPGA (XC2S200 package PQ208) we had to refer to the XILINX
FPGA Manuals. This manual gives the specifications of the FPGA
used and give an in depth description of the techniques used to
program an FPGA.
XILINX offers project development solutions in both Verilog and
VHDL. Since we had prior experience of using VHDL (very
elementary), we decided to stick with it for our project. Using VHDL
Programming by Example by Douglas L. Perry, we learned how to
code effectively, the difference between synthesizable and non-

6
synthesizable code, and how a behavioural description is transformed
into an RTL schematic and how this is mapped onto an FPGA.
The proceeding chapters deal with the software core, the PCI core and
how this core is configured. Then we move on to the main User
Application Design.

7
Chapter 3
Introduction to Logicores

Contrary to general perception, a core is not a hardware component or


Application Specific Integrated Circuit (ASIC). The Logicore, in
XILINX terminology, is a software code in Hardware Description
Language (HDL) which allows us to utilize components ranging from
basic elements such as flip flops to more complex devices such as
Ethernet controllers from the Xilinx library.
The concept of cores might be intangible to those who have never used
them. These are analogous to functions( ) encountered in many
programming languages. When a core is generated, certain files
(discussed later) are generated. One of these files contains an
instantiation of the device (Wrapper file), while another file contains
an instantiation template providing a format which helps us utilize the
core. If you’ve understood this, it would resemble calling a function
which itself calls a function. For those who haven’t understood, things
will become clearer as we move on. First let us take a look at the tool
which generates these cores.
XILINX Core Generator:
Xilinx CORE Generator System provides a catalogue of user-
customizable functions ranging in complexity from commonly used
functions such as memories and FIFOs, to system-level building
blocks such as filters and transforms. Higher level functions such as
Endpoints for PCI Express and PCI/PCI-X, Ethernet MACs, XAUI,
SPI-4.2, Reed Solomon, and other Forward Error Correction functions
are also included in evaluation form to allow you to “Try before you
Buy”. Each Function is called an Intellectual Property (IP). Xilinx
offers a host of IPs for free with the ISE WebPACK.
You can also generate tailored HDL to quickly configure FPGA
architectural elements such as MGTs and Ethernet and PCI Express
hard blocks using the integrated LogiCORE GUI-based customizers
and ISE Architecture Wizards. Through its seamless integration with

8
the ISE development environment, the CORE Generator system
streamlines your design process and makes utilization of the core
easier.
Key Features:
1) Included with all versions of ISE Foundation as well as ISE
WebPACK software.
2) Search for IP by keyword, or sort the IP listings alphabetically, or
by function type.
3) Easy access to detailed information on each core (data sheets, user
guides, release notes, licensing status, enhancement listings for new
versions).
4) Regular updates keep you up to date with new features,
enhancements and architecture support.
5) Includes Memory Editor tool to allow you to specify memory
initialization values for CORE Generator based memory cores.

6) Automatically install IP core updates along with required ISE


service packs using WebUpdate.

When a core is generated, several files are created. Similarly the core
requires several files as input, for generation. Here is a brief
description of all these files.
CGP File
The CGP file is the CORE Generator project file. The file stores user-
specified project settings.
CORE Generator Input Files
CGF File
As a log file, the CGF file is used in the Memory Editor to record the
user-specified inputs that are used to generate the COE files for a
memory. As a specification file, a CGF file can be used to define the
data contents of COE files for memory blocks.
COE File
An ASCII input coefficient file used when multiple data values must
be specified for a core, usually as an array.
XAW File

9
A binary file that holds the configuration settings for an Architecture
Wizard core. The XAW file is used as an input file when an
Architecture Wizard core is recustomized. The XAW file is also an
output file written out by the CORE Generator when an Architecture
Wizard core is generated.
XCO File
CORE Generator input file containing the parameters used to generate
a core. The XCO file is used as an input file when a core is
recustomized or regenerated. The XCO file is also an output file
generated by the CORE Generator.

CORE Generator Output Files


ASY File
A graphical symbol information file used by the ISE tools and some
third party interface tools to create a symbol representing the core.
10oregent.log File
A text file containing a log of all the actions performed and messages
displayed during a CORE Generator session. The 10oregent.log file is
automatically written by the CORE Generator. You can refer to the log
to see what occurred during that session.
EDN File
EDIF Implementation Netlist for a core. Describes how the core is to
be implemented. Used as input to the Xilinx implementation tools.
A padded.edn file is an EDN file with input and output pads added to
the core. The padded.edn file, which is named
generated_core_name_padded.edn, is an EDIF wrapper file generated
for a core when the Generate netlist wrapper with IO pads project
option is enabled. The file adds input pads and output pads to the
core, enabling you to process the generated core through the Xilinx
design flow as if it were a complete chip design.
File List (flist.txt) File
The File List file, which is named generated_core_name_flist.txt, is a
text file listing all of the output files produced when a customized
core was generated in the CORE Generator.

10
MIF File
Memory Initialization File which is automatically generated by the
CORE Generator System for some CORE Generator modules when an
HDL simulation flow is specified. A MIF data file is used to support
HDL functional simulation of modules which use arrays of values.
Examples include memories, FIR filters, and bit correlators.
NDF File
An optional output file produced for cores that generate NGC files.
The NDF files allow third party synthesis tools to infer resource
utilization and timing from the NGC files associated with these new
cores.

NGC File
A binary Xilinx implementation netlist. The logic implementation of
certain CORE Generator IP is described by a combination of a top
level EDN file plus one or more NGC files.
Readme File
The Readme file, which is named generated_core_name_readme.txt,
lists the output files produced when a core is generated and describes
each file.
SYM File
Schematic symbol file used to instantiate a generated core into the
ISE Schematic Editor.
UCF File
Xilinx UCF (User Constraints File). The file is a UCF template
containing constraints generated when a core is elaborated. The
constraints in the file are cut and pasted into the UCF file of an ISE
project. All Architecture Wizard cores, and some other IP cores,
generate UCF files.

VHD File
VHDL wrapper file, which is used to support VHDL functional
simulation of a core. The VHD wrapper passes customized parameters
to the generic core simulation model.

11
VHO File
VHDL template file. The components in this file can be used to
instantiate a core.
XAW File
As an output file, the XAW file is a binary file that holds the
configuration settings for an Architecture Wizard core. The CORE
Generator generates an XAW file in the project directory for each
Architecture Wizard core that it creates.
XCO File
As an output file, the XCO file stores the project and core parameter
settings used to generate a particular core. The CORE Generator
generates an XCO file in the project directory for each IP core that it
creates.

XSF File
A Xilinx Netlist Format port list file used by the Mentor Graphics
tools to create a symbol representing the core.
From among the files described above, the user actually deals with
only a few. That is to say, only a few file are required to link a core o
the main project.
The procedure for linking a core to the main project is as shown
below:
Generation:
Core Generator can be accessed by the following path: Start
Menu=>Programs=>Xilinx 9.2i =>Accessories=>Core Generator.
Select a device from the left panel of the Core Generator window:

12
The above window pops up when you select the device: Adder
Subtractor. It allows you to configure the device and make
adjustments to parameters such as function (Adder, Subtractor, Both),
Port Width, Data Types and Radix.
After clicking on generate, a readme file, enumerating the various
generated files and their paths and function pops up.
The next step would be to link the core with the main project.
To do this, the .vhd (Wrapper file) is first added to the project by
right clicking the project in the Sources panel and selecting the “Add
copy of Source” option from the list. Navigate to the Core Generator
project folder and select the wrapper file.
After this, instantiate the core into the parent design by following
these steps.

13
To instantiate a core in a VHDL design
1. Copy the component declaration and the instantiation from the
core’s instantiation template (VHO file) into the appropriate
areas of the parent design.

2. In the parent design, change your_instance_name (a dummy


name from the instantiation template) to the actual instance
name.

3. In the parent design, modify the port connections copied from


the instantiation template to reflect the actual connections to
the parent design.

The component declaration and component instantiation block


establish a link in the VHDL code to the EDIF implementation netlist
for the CORE Generator module. This link is necessary to ensure that
the core is integrated properly when the parent VHDL design has been
synthesized. The VHDL instantiation of the core in the parent design
serves as a placeholder for the core. During design implementation the
Xilinx tools merge the core’s EDIF and/or NGC netlists with the rest
of the parent design.

The above text was a brief introduction to cores in general. In the


next chapter, we move onto the most important part o the project,
namely, the PCI core. Here, we attempt to explain the generation of
the core, the various settings in the configuration space and the
different files that are created.

14
Chapter 4
The PCI Core (Configuration, Components and Instantiation)

The PCI logicore simulates the PCI protocol replete with the rigid
timing specifications. This chapter deals with an overview of the core,
generation and configuration, and the procedure for using this core in
our project.
General Description
The Initiator/Target core for PCI is a pre-implemented and fully
tested module for Xilinx FPGAs. The pinout for each device and the
relative placement of the internal logic are predefined. Critical paths
are controlled by constraints and guide files to ensure predictable
timing. This significantly reduces engineering time required to
implement the PCI portion of your design. Resources can instead be
focused on the unique user application logic in the FPGA and on the
system-level design. As a result, Xilinx products for PCI minimize
your product development time. The core meets the setup, hold, and
clock-to-timing requirements as defined in the PCI specification. The
interface is verified through extensive simulation. Other FPGA
resources that can be used in conjunction with the core to enable
efficient implementation of a PCI system include:
•Block SelectRAM™ memory. Blocks of on-chip ultra-fast RAM with
synchronous write and dual-port RAM capabilities. Used in PCI
designs to implement FIFOs.
•SelectRAM memory. Distributed on-chip ultra-fast RAM with
synchronous write option and dual-port RAM capabilities. Used in PCI
designs to implement FIFOs.
•Internal three-state bus capability for data multiplexing. The
interface is carefully optimized for best possible performance and
utilization in Xilinx FPGA devices.
Functional Description
The Figure illustrates the major functional blocks generated when a
PCI core is generated using Core Generator:

15
Figure Courtesy Xilinx

I/O Interface Block


The I/O interface block handles the physical connection to the PCI bus
including all signaling, input and output synchronization, output
three-state controls, and all request-grant handshaking for bus
mastering.
User Application
The Initiator/Target core for PCI provides a simple, general-purpose
interface for a wide range of applications.
Configuration Space

This block provides the first 64 bytes of Type 0, version 3.0


Configuration Space Header, as shown in The Table, to support
software-driven Plug-and-Play initialization and configuration. This
includes information for Command and Status, and three Base Address
Registers (BARs). The capability for extending configuration space
has been built into the user application interface. This capability,
including the ability to implement a capabilities pointer in
configuration space, allows you to implement functions such as power
management and message signalled interrupts in your application.

16
Table Courtesy Xilinx

Note : The shaded areas are not implemented and return zero.

Parity Generator/Checker

17
This block generates and checks even parity across the AD bus, the
CBE# lines, and parity signals. It also reports data parity errors via
PERR# and address parity errors via SERR#.

Initiator State Machine

This block controls the Initiator/Target core for PCI initiator


functions. The initiator control logic uses one-hot encoding for
maximum performance.

Target State Machine

This block controls core target functions. The target control logic
uses one-hot encoding for maximum performance.

Core Configuration

The core can be easily configured to fit unique system requirements


using the Xilinx CORE Generator GUI or by changing the HDL
configuration file. The following customization options, among many
others, are supported by the core.

•Device and vendor ID

•Base Address Registers (number, size, and type)

Burst Transfer

The PCI bus derives its performance from its ability to support burst
transfers. Performance of any PCI application depends largely on the
size of the burst transfer. Buffers to support PCI burst transfer can
efficiently be implemented using on-chip RAM resources.

Generation of the PCI core:

18
Open the Core Generator tool by going through following path:

Start Menu=>Programs=>Xilinx9.2i=>Accessories=>Core Generator.

2) Click ‘File’ in the menu bar and select ‘New Project’.

1) Enter the name of the project and select the location. For our
project it is: C:\Xilinx9.2i\bin\nt\coregen.
coregen is the name of the Project. All the cores generated in this
project will be stored in this location.

2) Select the following parameters and click ‘OK’.

19
3) Now click the ‘View by Name’ tab in the left panel and select the
‘LogiCORE 32-bit Initiator/Target for PCI (Spartan only)’ IP.

4) In the right panel, select the ‘customize’ link. This would cause
the following configuration window to pop up:

20
5) The above screenshot shows the first 16 d-words of the
Configuration space. Here, we can make changes to few of the
configuration registers.

6) Here, not for any particular reason, we have made changes only to
the Base Address Registers. We have used only BAR0 to acquire a
16 bit memory. We set the BAR0 in the following manner.

21
7) After clicking ‘OK’, we click on Generate. A readme file with the
terms of use pops up.

This means that the core has been generated successfully.

All the generated files are stored in the folder:


C:/Xilinx/bin/nt/coregent/PCI

Henceforth, we will refer to this as the Install Path. There is a


procedure which is to be followed in order to utilize this core.
However, before we go into that we will first make a clear
distinction between the different components of the generated core.

Components:

The PCI core can be roughly divided into three components. These
are the pcim_lc (Wrapper file), userapp (the User Application) and
the cfg module (Configuration Module). These components are

22
linked to a parent source “ pcim_top.vhd”. They are instantiated
into the pcim_top.vhd source. Let us first take a look at these
components individually

1) The Wrapper File (pcim_lc.vhd)

The wrapper, normally, is a file which contains an instantiation


of the device and derives the signals from the Xilinx library.
The logic for each core is specified in either an EDIF or NGC
implementation netlist (component_name.edn or
component_name.ngc) and, for some cores, may also be
specified in additional NGC files, but it is not specified in the
VHD wrapper file for the core. The pcim_lc contains an
instantiation of the pcim_lc_i file. This is an NGD file which is
a combination of NGC and EDIF netlist files. When the core is
generated, the pcim_lc_i is automatically instantiated in the
pcim_lc wrapper file. However the pcim_lc_i file needs to be
manually linked to the pcim_lc file. This is explained later on.

The PCI core converts the PCI Bus signals into Local Bus
signals which can be used by the user to interface his
application to the PCI core.

2) The User Application (userapp.vhd)

The User Application is a file where the user is allowed to write


his own application. These applications make use of the User
Interface signals to maintain the rigid timing specifications of
the PCI protocol.

The User Application file (userapp.vhd) must be added to the


parent file, i.e., pci_top.vhd.

23
A schematic diagram, showing the Core (wrapper file) and the
User Application along with the signals and their brief
descriptions is given in Appendix 1.

3) Configuration File (cfg.vhd)

The PCI core is customized by settings in a text file called the


configuration file. Settings in the configuration file are
communicated to the PCI core through a 256-bit bus and affect
both the design and the functional simulation model. There are
two ways to change the values in the configuration file:

• Using the CORE Generator GUI

• Using a text editor.

For starting new designs, the CORE Generator GUI is the


recommended method; for subsequent changes, you may modify
the configuration file using a text editor.

Constraints File

The user constraints files contain various constraints required


for the PCI interface, and must always be used while processing
a design. Each constraints file is specific to a

particular device and PCI interface.

24
We now move on to actual project development. Before we
actually start work with Project Navigator, we need to copy
certain files into the coregen directory

Initial Steps

We need to identify the appropriate wrapper and constraints file


to be linked with our project. The LogiCORE PCI v3.1 Getting
Started Guide provides a complete list of files for different
FPGAs. These files can be identified for the following
parameters

Device: 2S200-PQ208-5C

Bus Type: 33 MHz 5V 32-bit

The files for this configuration are

Wrapper File: pcim_lc_33_3_s.vhd

Constraints File: 2s200pq208_32_33.ucf

The wrapper files, located in the <Install Path>/hdl/src/wrap


directory, are actually variations of the pcim_lc. hdl file located
in the <Install Path>/hdl/src/xpci directory. When starting a
new design, copy the appropriate wrapper file from the wrap/
directory into the xpci/ directory, and rename it pcim_lc. hdl.

Starting with the project

1) Open Project Navigator

Start Menu=>Programs=>Xilinx 9.2i =>Project Navigator

2) Go to File>New Project

25
A New Project Wizard pops up. Enter the name of the project
(data_core in our case) and select the Top-Level Source Type
as HDL.

3) In the next window, make the settings as shown in the


screenshot

4) In the proceeding windows, click Next-Next-Finish.

5) Now Add the pcim_top module to the project by right-


clicking xc2s200-5pq208 and clicking on ‘Add a Copy of
Source’

Navigate to <Install Path\vhdl\src\xpci\pcim_top.vhd

6) Add the following files to pcim_top.vhd in a similar manner

<Install Path\vhdl\src\xpci\pcim_lc.vhd

<Install Path\vhdl\src\xpci\userapp.vhd

26
<Install Path\vhdl\src\xpci\cfg.vhd

<Install Path\vhdl\src\ucf\2s200pq208_32_33.ucf

7) The pcim_lc.vhd file instantiates the NGD file pcim_ lc_i.


Thus this file is added to the pcim_lc in a similar manner by
navigation to
<Install Path\vhdl\src\xpci\pcim_lc_i.vhd

8) The above steps include all the files that are required for
starting with the project.

The next section deals with setting the Configuration file:

The Configuration File

The following sections define the available customization


options.

Device and Vendor ID

The Device ID is a unique identifier for the application. This


field can be any value. Change this value for the application.

// Device ID and Vendor ID

assign CFG[151:120] = 32'h4062_10ee ;

The Vendor ID identifies the manufacturer of the device or


application. Valid identifiers are assigned by the PCI Special
Interest Group to guarantee that each identifier is unique.
The value 10EEh, provided in the default configuration, is
the Vendor ID for Xilinx. Enter a vendor identification
number here. The value FFFFh is reserved.

Class Code and Revision ID

27
The Class Code identifies the general function of a device.
The value, as provided in the default configuration,
identifies the device as a generic co-processor function.

// Class Code and Revision ID

assign CFG[183:152] = 32'h0B40_0000 ;

The Class Code is divided into three byte-size fields as


described in the PCI Local Bus Specification. The upper byte
broadly identifies the type of function performed by the
device.

The middle byte defines a sub-class that more specifically


identifies the device’s function.

The lower byte defines a specific register-level programming


interface (if any). This allows device-independent software
to interact with the device.

The Revision ID indicates the revision of the device or


application. It is an extension of the Device ID. Enter the
values appropriate for the application.

Subsystem Vendor ID and Subsystem ID

The Subsystem Vendor ID further qualifies the manufacturer


of the device or application. Enter a Subsystem Vendor ID
here; typically, it is the same as the Vendor ID. Setting it to
0000h may cause issues with compliance testing. The
Subsystem ID can be set as desired to identify the device,
revision, or other manufacturing data.

// Subsystem ID and SubVendor ID

assign CFG[215:184] = 32'h4062_10ee ;

28
By default, the Subsystem Vendor ID and Subsystem ID are
set at design time and part of the resulting interface netlist.

// External Subsystem ID and Subvendor ID

assign CFG[114] = `DISABLE ;

Enabling the External Subsystem ID allows these fields to be


dynamic and supplied by the user application through the
SUB_DATA bus. This may be used to load unique values
which are determined by the user application at run-time.
When this feature is enabled, the CardBus CIS Pointer is
disabled and always set to zero.

CardBus CIS Pointer

The CardBus CIS Pointer is used in CardBus applications. By


default, this field is supplied through the SUB_DATA bus. If
the CardBus CIS Pointer is not used, the SUB_DATA bus
should be set to zero. If the interface is configured to use an
external Subsystem Vendor ID and Subsystem ID via
SUB_DATA, the CardBus CIS Pointer is disabled and always
set to zero.

Max_Lat, Min_Gnt, and Latency Timer

These registers are used to specify the desired latency timer


settings. MAX_LAT specifies how often the device needs to
gain access to the PCI Bus. MIN_GNT specifies how long the
minimum burst period should be, assuming a 33 MHz bus
speed. The values for both registers are periods of time in
units of a quarter microsecond.

29
// Max_Lat

assign CFG[231:224] = 8'h0f ;

// Min_Gnt

assign CFG[223:216] = 8'h0f ;

These registers are intended for use by the system software


and do not directly affect the operation of the PCI interface.

For applications that do not support bursting or that burst


only two words, the Latency Timer function can be disabled.
This saves additional logic and routing resources.

// Latency Timer Enable

assign CFG[112] = `ENABLE ;

Interrupt Enable

This turns on the interrupt registers in the PCI interface. The


interface only supports INTA_O.

// Interrupt Enable

assign CFG[113] = `ENABLE ;

Capabilities List

The PCI interface has the ability to implement a Capabilities


List in configuration space. If the design requires a
Capabilities List, enable this option and set the pointer to
the desired address in configuration space. Otherwise set it
to zero. Also enable the User Config Space option.

// Capabilities List Enable

30
assign CFG[116] = `DISABLE ;

// Capabilities List Pointer

assign CFG[239:232] = 8'h00 ;

// User Config Space Enable

assign CFG[118] = `DISABLE ; Note: If multiple clock


domains are used, the USER_FFS flip-flops should be limited
to those that connect to the PCI interface in the PCI clock
domain.

Interrupt Acknowledge

This bit enables the PCI interface to respond to interrupt


acknowledge cycles as a target. Enabling this feature

// Interrupt Acknowledge

assign CFG[240] = `DISABLE ;

Reserved Settings

Several option settings are reserved for implementation


specific features or for backwards compatibility. Do not
modify these option settings. The following are reserved and
should not be modified.

Base Address Registers

31
The PCI interface supports up to three BARs (Base Address
Registers). The designer is free to use any BAR desired.
Each BAR has several attributes. These attributes define:

• Whether the BAR is enabled.

Disabling the BAR allows the optimization tools to delete the


entire circuit.

• The size of the address space required.

In the core interface, the address space can be as small as 16


bytes, or as large as two gigabytes. For 80x86 systems, the
maximum allowed I/O space is 256 bytes.

• The ability of memory space to be pre-fetched.

The PCI Local Bus Specification defines memory as


prefetchable if:

♦ there are no side-effects on reads (i.e. data will not be


destroyed by reading, as from a RAM).

♦ byte write operations can be merged into a single


double-word write, when applicable.

• Whether the address space is defined as memory or I/O. The


BAR will only respond to commands that access the specified
address space.

• The address space location “preference” of the device. The


core interface supports 32- bit address spaces for both
memory and I/O.

• Whether the BAR address space is defined as 64-bit


capable. This only applies to memory spaces.

32
We have already made the settings for the BAR0 using the
GUI in Core Generator.

33
The following is the code in the Configuration file:

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

use IEEE.std_logic_arith.all;

entity cfg is

port (

CFG : out std_logic_vector (255 downto 0)

);

end cfg;

architecture rtl of cfg is

-- declare some signals for outputs.

signal cfg_int : bit_vector(255 downto 0);

-- declare literals for use later

constant MEMORY : bit := '0' ;

constant IO : bit := '1' ;

constant DISABLE : bit := '0' ;

constant ENABLE : bit := '1' ;

constant PREFETCH : bit := '1' ;

34
constant NOFETCH : bit := '0' ;

constant IO_PREFETCH : bit := '1' ;

constant TYPE00 : bit_vector(1 downto 0) := "00" ;

constant TYPE01 : bit_vector(1 downto 0) := "01" ;

constant TYPE10 : bit_vector(1 downto 0) := "10" ;

constant IO_TYPE : bit_vector(1 downto 0) := "11" ;

constant SIZE2G : bit_vector(31 downto 0) := X"80000000"


;

constant SIZE1G : bit_vector(31 downto 0) :=


X"c0000000" ;

constant SIZE512M : bit_vector(31 downto 0) :=


X"e0000000" ;

constant SIZE256M : bit_vector(31 downto 0) :=


X"f0000000" ;

constant SIZE128M : bit_vector(31 downto 0) :=


X"f8000000" ;

constant SIZE64M : bit_vector(31 downto 0) := X"fc000000"


;

constant SIZE32M : bit_vector(31 downto 0) := X"fe000000"


;

constant SIZE16M : bit_vector(31 downto 0) := X"ff000000"


;

constant SIZE8M : bit_vector(31 downto 0) :=


X"ff800000" ;

constant SIZE4M : bit_vector(31 downto 0) :=


X"ffc00000" ;

constant SIZE2M : bit_vector(31 downto 0) :=


X"ffe00000" ;

constant SIZE1M : bit_vector(31 downto 0) :=


X"fff00000" ;

constant SIZE512K : bit_vector(31 downto 0) := X"fff80000"


;

35
constant SIZE256K : bit_vector(31 downto 0) :=
X"fffc0000" ;

constant SIZE128K : bit_vector(31 downto 0) :=


X"fffe0000" ;

constant SIZE64K : bit_vector(31 downto 0) :=


X"ffff0000" ;

constant SIZE32K : bit_vector(31 downto 0) :=


X"ffff8000" ;

constant SIZE16K : bit_vector(31 downto 0) := X"ffffc000" ;

constant SIZE8K : bit_vector(31 downto 0) := X"ffffe000" ;

constant SIZE4K : bit_vector(31 downto 0) := X"fffff000" ;

constant SIZE2K : bit_vector(31 downto 0) := X"fffff800" ;

constant SIZE1K : bit_vector(31 downto 0) := X"fffffc00" ;

constant SIZE512 : bit_vector(31 downto 0) := X"fffffe00" ;

constant SIZE256 : bit_vector(31 downto 0) := X"ffffff00" ;

constant SIZE128 : bit_vector(31 downto 0) := X"ffffff80" ;

constant SIZE64 : bit_vector(31 downto 0) := X"ffffffc0" ;

constant SIZE32 : bit_vector(31 downto 0) := X"ffffffe0" ;

constant SIZE16 : bit_vector(31 downto 0) := X"fffffff0" ;

begin

--------------------------------------------------------------

-- Configure Device, Vendor ID, Class Code, and Revision ID

--------------------------------------------------------------

-- Device ID and Vendor ID

cfg_int(151 downto 120) <= X"12340000" ;

-- Class Code and Revision ID

cfg_int(183 downto 152) <= X"11800000" ;

36
--------------------------------------------------------------

-- Configure Subsystem ID and SubVendor ID

--------------------------------------------------------------

-- Subsystem ID and SubVendor ID

cfg_int(215 downto 184) <= X"00000000" ;

-- External Subsystem ID and Subvendor ID

cfg_int(114) <= DISABLE ;

--------------------------------------------------------------

-- Configure Base Address Registers

--------------------------------------------------------------

-- BAR0

cfg_int(0) <= ENABLE ;

cfg_int(32 downto 1) <= SIZE32 ;

cfg_int(33) <= NOFETCH ;

cfg_int(35 downto 34) <= TYPE00 ;

cfg_int(36) <= MEMORY ;

-- BAR1

cfg_int(37) <= DISABLE ;

cfg_int(69 downto 38) <= SIZE2G ;

cfg_int(70) <= NOFETCH ;

cfg_int(72 downto 71) <= TYPE00 ;

cfg_int(73) <= MEMORY ;

37
-- BAR2

cfg_int(74) <= DISABLE ;

cfg_int(106 downto 75) <= SIZE2G ;

cfg_int(107) <= NOFETCH ;

cfg_int(109 downto 108) <= TYPE00 ;

cfg_int(110) <= MEMORY ;

--------------------------------------------------------------

-- Configure MAX_LAT MIN_GNT

--------------------------------------------------------------

-- MAX_LAT and MIN_GNT

cfg_int(231 downto 224) <= X"00" ;

cfg_int(223 downto 216) <= X"00" ;

-------------------------------------------------------------

-- Configure other PCI Header options

-------------------------------------------------------------

-- Latency Timer Enable

cfg_int(112) <= DISABLE ;

-- Interrupt Enable

cfg_int(113) <= DISABLE ;

-------------------------------------------------------------

-- For advanced users only.

38
-------------------------------------------------------------

-- Capability List Enable

cfg_int(116) <= DISABLE ;

-- Capability List Pointer

cfg_int(239 downto 232) <= X"00" ;

-- User Config Space Enable

cfg_int(118) <= DISABLE ;

-- Interrupt Acknowledge

cfg_int(240) <= DISABLE ;

-------------------------------------------------------------

-- Do not modify any of the following settings!

-------------------------------------------------------------

-- Obsolete

cfg_int(111) <= DISABLE ;

-- Obsolete

cfg_int(117) <= DISABLE ;

-- Obsolete

cfg_int(119) <= DISABLE ;

-- Enable 66 MHz

39
cfg_int(244) <= DISABLE ;

cfg_int(248 downto 245) <= "0000";

cfg_int(254 downto 249) <= "001000";

-- Do Not Modify

cfg_int(115) <= DISABLE ;

cfg_int(241) <= DISABLE ;

cfg_int(242) <= DISABLE ;

cfg_int(243) <= DISABLE ;

cfg_int(255) <= DISABLE ;

CFG <= to_stdlogicvector(cfg_int);

end rtl;

Now that the PCI core has been configured, we can move on
to designing the User Application. The next Chapter deals
with design of the User Application.

40
Chapter 5

User Application

The User Application is a file where the user, i.e., the card
manufacturer is allowed to write the functionality of the device in
HDL.
In the previous chapter, we have defined the different components of
the PCI core, namely the PCI core (Wrapper files + NGD files), the
Configuration Module and the user application.
The first two components define the PCI protocol, take care of the
timing specifications and convert the incoming PCI Bus signals into
User Interface signals. Some of these signals are registered versions
of the PCI Bus Signals (eg : FRAMEQ_N is a registered signal for
FRAME_IO which is a PCI Bus signal) whereas others are signals
which allow us to use the User Application as a Black Box entity.

The User Interface as a Black Box

41
The PCI logic core is designed in such a manner that one can write an
application for the PCI card with elementary knowledge of the PCI
signals. Certain User Interface signals, which are derived from the
PCI Bus signals, inform the designer about when to read or write data
to the User Interface Bus. Also, the user manuals clearly define what
acknowledge signals to send before or after data transfer and what
signals to monitor for checking errors. Thus, the programmer needs to
only focus on the actual problem at hand, i.e., the function of the PCI
card. The protocol is taken care of by the core.
Since designing the User Application can be thought of as an
independent task (independent of the PCI protocol), we will treat our
design as a problem statement and utilize the User Interface Signals in
our design.

Problem Statement:
Our Primary purpose is to make the core functional.
It is essential that when the PCI card is inserted into the slot, it is
detected, the requested memory space is allotted to it and we are able
to perform the basic read and write operations to and from the card. It
is only then that the core can be utilized to its full potential.
Thus our primary goal and the most important aspect of this project is
to make sure that a basic user application can be implemented. Thus
our User Application should be capable of accepting a 16 bit data
from the core when data is written to the card, and make data
available to the core when data is read from the card.
We will split the User Application design in two parts:
1) Designing the User Application

This would consist of using the Interface signals to derive the


signals required for initiating data transfer and design of the
data buffer to store data.

2) Identifying the unused Interface signals which are to be driven


by the User Application and assigning “safe” values to these
signals.

42
A very important note
Since our device will not initiate any operations on the PCI bus, in
PCI terminology our device is a target. The core is designed in such a
manner that the Initiator and Target state machines are separate.
Thus when designing a Target Only design, we do not use the signals
that deal with Initiator functions.

Before we move on, we will first list the Interface signals associated
with the Target State Machine.
Basic Target Interface Signals
For basic transfers, a subset of the target interface signals is used. An
example of a basic target design using the reduced subset is presented
later in this chapter.
BASE_HIT[7:0]: Input indicates that one of the base address registers
recognizes that it is the target of a current transaction. This is the
first indicator to the user application that a target transaction is about
to begin.
ADIO[31:0]: Bidirectional bus provides the means for data and
address transfer to and from the core interface.
ADDR[31:0]: Input is a registered version of the PCI address
provided by the core interface. It becomes valid in the cycle after
ADDR_VLD is asserted, and remains valid through the entire
transaction. S_WRDN: Input indicates the direction of data transfer
for the current target transaction. Logic high indicates that the user
application is sinking data (such as target write). It is valid during the
cycle BASE_HIT is asserted and is held through the entire transaction.
S_CBE[3:0]: A registered version of the CBE_IO lines, and is delayed
by one cycle. It indicates the PCI command and byte enables during a
target transaction. This signal is used primarily for byte enable
information, as the command is decoded and latched in PCI_CMD
during the address phase of the transaction.
PCI_CMD[15:0]: Input is a decoded and latched version of the PCI
command for the current bus transaction.

43
S_DATA_VLD: Input has two interpretations depending on the
direction of data transfer. When the user application is sinking data
(target writes), S_DATA_VLD indicates that the user application
should capture valid data from the ADIO bus. When the user
application is sourcing data (target reads), S_DATA_VLD indicates
that a data phase has completed on the PCI Bus.
S_DATA: Input indicates that the target state machine is in the data
transfer state.

Additional Target Interface Signals


More elaborate designs involving non-deterministic target
termination, target wait state insertion, or target burst require
additional target interface signals. References to inputs and outputs
are made with respect to the user application.
ADDR_VLD: Input indicates that a valid PCI address is available on
the ADIO bus, and may be used as a clock enable by the user
application to capture a copy of this address. This is particularly
useful in target burst applications where a loadable counter must track
the target address. In non-burst applications, the latched address
present on the ADDR bus may suffice. Note, however, that the
assertion of ADDR_VLD does not mean that the user application will
be the selected target. The ADDR_VLD signal is asserted for a single
cycle.
S_SRC_EN: Input is only used during target burst reads. It indicates
to the user application that the data source which drives output data
onto the ADIO bus must provide the next piece of data. In most
applications, this signals the user application to advance the data
pointer for the data source providing the data.
CSR[39:0]: Input provides general status information about the core
interface. The high eight bits provide status information about the
current transfer. This status information is used primarily in target
burst applications with non-prefetchable sources to determine if any
associated address pointers must be “backed up.”
S_READY: Output from the user application indicates that it is ready
to transfer data, and can be used to insert wait states during the first

44
data phase of a transaction. Together with S_TERM, it is also used to
signal different types of target termination. It is important to note
that the user application is prohibited from using S_READY to insert
wait states after the first data phase.
S_TERM: Output from the user application indicates that data transfer
should cease. It is also used with S_READY to signal different types
of target termination.
S_ABORT: Output from the user application indicates that a serious
(fatal) error condition has occurred and that the current transaction
must stop.

The following signals are output by the target state machine in the
core interface.
IDLE: Input indicates that the target state machine is in the idle state
and that there is no activity on the PCI Bus.
B_BUSY: Input indicates that the target state machine has recognized
the beginning of a PCI Bus transaction. The target state machine will
change to the S_DATA state if it determines that it is the target of the
transaction.
S_DATA: Input indicates that the target state machine is in the data
transfer state.
BACKOFF: Input indicates that the target state machine is waiting for
a transaction to complete because the user application has asserted
S_TERM.

Now we will move onto the first part of the design process and drive
unused signals to benign values:
Conceptually, creating a target-only design is as simple as driving all
initiator control signals to a benign (de-asserted) state. In addition,
the user application should be designed without making use of any
initiator status or state outputs from the core interface.
However, connecting all unused control signals to logic high or logic
low may have unwanted side-effects—the map program may optimize
these signals away during the implementation step, which in itself is

45
not problematic, but the guide files, which are required to guarantee
timing in some designs, fail to work properly if certain signals are
optimized away.
The solution to this problem is to drive the initiator control signals
from the output of flip-flops. The following shows an example of this
solution:
always @(posedge CLK or posedge RST)
begin : cannot_be_optimized
if (RST) FAKE_LOGIC_0 = 1’b1;
else FAKE_LOGIC_0 = 1’b0;
end
The Table lists the initiator control signals that must be tied off and the appropriate
benign values. The table also identifies which signals must be driven from a flip-flop.
Some signals are present only in 64-bit implementations of the interface.

Signal Name Benign Value Flip-Flop

REQUEST 0 No

REQUESTHOLD 0 No

COMPLETE 1 Yes

M_WRDN 0 Yes

M_READY 1 Yes

M_CBE[3:0] 0110 Optional

CCFG_SELF 0 No

REQUEST64 0 No

M_CBE[7:4] 0000 Optional

In addition to the aforementioned signals, two more signals need to be


considered while designing the application. These signals are
S_READY and S_TERM. These two signals used in conjunction
determine the method manner in which our device terminates a
transaction.

46
For our User Application we will use a mode of Disconnection in
which the User Application will always be ready to transfer data and
will disconnect after one data phase.
always @(posedge CLK or posedge RST)
begin : cannot_be_optimized_a
if (RST) S_READY = 1’b0;
else S_READY = 1’b1;
end
always @(posedge CLK or posedge RST)
begin : cannot_be_optimized_b
if (RST) S_TERM = 1’b0;
else S_TERM = 1’b1;
end

Now, we will actually design the Application and derive signals that
would enable data transfer.

Decoding Target Transactions


The user application is responsible for monitoring outputs from the
core interface to respond to target transactions. The signals used in
target transactions are active and available at different times. The
most important signal is BASE_HIT, which indicates that the core
interface has claimed the current PCI transaction for base address
register 0.It is asserted for a single cycle. The following logic
decodes target reads and writes directed at base address register 0.
always @(posedge CLK or posedge RST)
begin : decode
if (RST)
begin
BAR_x_RD = 1'b0;
BAR_x_WR = 1'b0;
end

47
else
begin
if (BASE_HIT[x])
begin
BAR_x_RD = !S_WRDN & OPTIONAL;
BAR_x_WR = S_WRDN & OPTIONAL;
end
else if (!S_DATA)
begin
BAR_x_RD = 1'b0;
BAR_x_WR = 1'b0;
end
end
end

The last clause in the decoding block holds the decode asserted
throughout the entire data transfer state. Again, BASE_HIT[x] is only
active for a single clock cycle at the start of the transaction.
Effectively, the code above describes a synchronous set/reset flip-flop
with set dominant.

Target Writes
During a target write operation, data is captured from the ADIO bus to
a data register in the user application by asserting the LOAD input.
The first step is to generate the BAR _WR signal. The critical gating
signal is S_DATA_VLD. It is the final signal required to qualify the
write operation. Consequently, the other signals can be decoded
earlier and gated with S_DATA_VLD. The assignment for the load
input of the register would then be:
assign LOAD = BAR _WR & S_DATA_VLD;
Decoding BAR_WR and registering it before the assertion of
S_DATA_VLD allows more time for routing and reduces the number of
logic levels from the critical input, S_DATA_VLD.

48
The Write Timing Diagrams are shown below:

Target Reads
During a target read operation, data from the user application is
driven onto the ADIO bus. To do this, the user application must assert
the OE for the desired register. The first step is to generate the BAR
_RD signal on decoding target transactions. The assignment for the
output enable would then be:
assign OE = BAR _RD & S_DATA;
The Read Timing Diagrams are shown below:

49
Thus we have two derived signals, LOAD and OE, which are used by
the application to act as enables for storing and recovering data from
the Register buffer.
Design of the Register Buffer.
The Application requires a Register which latches the contents of the
ADIO Bus when LOAD is activated and outputs the stored value onto
the ADIO Bus when OE is activated.
Now this is a relatively simple design. However one must take one
precaution when dealing with the design. The implementation of the
tri-state logic should be immaculate. When none of the above signals
are activated, the output of the register should be tri-stated. In order
to implement this effectively, we use two cores to implement the
structure. These two cores are Bit Slice BUFE (Data Buffer) and Bit

50
Slice BUFT (Data Latch). This device works exactly as per our
requirement. In order to instantiate this core in our User Application,
refer “Introduction to Logicores”.
Note: Make sure that the VHD, NGC, XCO, MIF and TCL files are
copied from the <Install Path to the working project folder.

The code for the complete User Application is shown below:


--------------------------------------------------------------------------
--
-- File: userapp.vhd
-- Rev: 3.1.161
--
-- This is an example template for the user backend application.
--
-- Copyright (c) 2005-2007 Xilinx, Inc. All rights reserved.
--
----------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

entity userapp is
port (-- Interface to PCI Logicore.
FRAMEQ_N : in std_logic;
TRDYQ_N : in std_logic;
IRDYQ_N : in std_logic;
STOPQ_N : in std_logic;
DEVSELQ_N : in std_logic;

ADDR : in std_logic_vector( 31 downto 0);


ADIO : inout std_logic_vector( 31 downto 0);

CFG_VLD : in std_logic;
CFG_HIT : in std_logic;
C_TERM : out std_logic;
C_READY : out std_logic;

ADDR_VLD : in std_logic;
BASE_HIT : in std_logic_vector( 7 downto 0);

S_TERM : out std_logic;


S_READY : out std_logic;
S_ABORT : out std_logic;
S_WRDN : in std_logic;
S_SRC_EN : in std_logic;
S_DATA_VLD : in std_logic;
S_CBE : in std_logic_vector( 3 downto 0);
PCI_CMD : in std_logic_vector( 15 downto 0);

REQUEST : out std_logic;

51
REQUESTHOLD : out std_logic;
COMPLETE : out std_logic;

M_WRDN : out std_logic;


M_READY : out std_logic;
M_SRC_EN : in std_logic;
M_DATA_VLD : in std_logic;
M_CBE : out std_logic_vector( 3 downto 0);

TIME_OUT : in std_logic;
CFG_SELF : out std_logic;

M_DATA : in std_logic;
DR_BUS : in std_logic;
I_IDLE : in std_logic;
M_ADDR_N : in std_logic;
IDLE : in std_logic;
B_BUSY : in std_logic;
S_DATA : in std_logic;
BACKOFF : in std_logic;

INTR_N : out std_logic;


PERRQ_N : in std_logic;
SERRQ_N : in std_logic;
KEEPOUT : out std_logic;

CSR : in std_logic_vector( 39 downto 0);


SUB_DATA : out std_logic_vector( 31 downto 0);
CFG : in std_logic_vector(255 downto 0);

RST : in std_logic;
CLK : in std_logic
);
end userapp;

architecture rtl of userapp is

attribute syn_edif_bit_format : string;


attribute syn_edif_scalar_format : string;
attribute syn_noclockbuf : boolean;
attribute syn_hier : string;
attribute syn_edif_bit_format of rtl : architecture is "%u<%i>";
attribute syn_edif_scalar_format of rtl : architecture is "%u";
attribute syn_noclockbuf of rtl : architecture is true;
attribute syn_hier of rtl : architecture is "hard";

-- User defined components

COMPONENT DATA_GATE
PORT(
OE : IN std_logic;
I : IN std_logic_vector(31 downto 0);
O : OUT std_logic_vector(31 downto 0)
);
END COMPONENT;

52
COMPONENT DATA_LATCH
PORT(
D : IN std_logic_vector(31 downto 0);
G : IN std_logic;
Q : OUT std_logic_vector(31 downto 0)
);
END COMPONENT;

--User defined signals


SIGNAL BAR_RD : std_logic;
SIGNAL BAR_WRT : std_logic;
SIGNAL INT_BUS : std_logic_vector(31 downto 0);
SIGNAL LOAD : std_logic;
SIGNAL OE : std_logic;

begin
-- Add user application here.

process(CLK,RST,BASE_HIT) ----- BAR hit decoding


logic
begin
if(RST='1') then
BAR_RD <='0';
BAR_WRT <='0';
elsif(CLK' event and clk='1') then
if (BASE_HIT(0 downto 0) = "1") then
BAR_RD <= not(S_WRDN);
BAR_WRT <= S_WRDN;
elsif(S_DATA='0') then
BAR_RD <='0';
BAR_WRT <='0';
end if;
end if;
end process;

LOAD <= BAR_WRT and S_DATA_VLD;


OE <= BAR_RD and S_DATA;

Inst_DATA_GATE: DATA_GATE PORT MAP(


OE => OE,
I => INT_BUS,
O => ADIO);

Inst_DATA_LATCH: DATA_LATCH PORT MAP(


D => ADIO,
Q => INT_BUS,
G => LOAD);
---------------------------Unused out signals assignment ---------------

REQUEST <='0';
REQUESTHOLD <= '0';
CFG_SELF <= '0';
KEEPOUT <= '0';
C_READY <= '1';

53
C_TERM <= '1';

process(RST,CLK)
begin
if(clk' event and clk='1') then
if(RST='1') then
COMPLETE <= '0';
M_WRDN <= '1';
M_READY <= '0';
M_CBE <= "1001";
S_READY <= '0';
S_TERM <= '0';
S_ABORT <= '1';
INTR_N <= '0';
SUB_DATA <= "11111111111111111111111111111111";
else
COMPLETE <= '1';
M_WRDN <= '0';
M_READY <= '1';
M_CBE <= "0110";
S_READY <= '1';
S_TERM <= '1';
S_ABORT <= '0';
INTR_N <= '1';
SUB_DATA <= "00000000000000000000000000000000";
end if;
end if;
end process;

end rtl;

Note: After the User Application is programmed, we need to assign


package pins before we move onto the Design Verification Stage. This
is described in Appendix 1.

54
Chapter 6
Design Verification

A very important part of the programming process is design


verification. After designing the User Application, the design has to
go through two major processes before it can be downloaded onto the
FPGA. These are the processes of Synthesis and Implementation.
This chapter is aimed at giving the reader a perspective on how a
Hardware Description Language is converted into a BIT file which can
be downloaded onto an FPGA. Also, a brief description of the errors
that can crop up during Synthesis and Implementation is included for
the reader’s benefit.

Design Flow:
A schematic illustrating the design flow for an FPGA is as shown:

We will begin with the Synthesis Process:

Synthesis:
After design entry and optional simulation, you run synthesis. In the
Sources tab, select Synthesis/Implementation from the Design View

55
drop-down list, and select the pcim_top module . In the Processes
tab, double-click Synthesize.
The ISE software includes Xilinx Synthesis Technology (XST), which
synthesizes VHDL, Verilog, or mixed language designs to create
Xilinx-specific netlist files known as NGC files. Unlike output from
other vendors, which consists of an EDIF file with an associated NCF
file, NGC files contain both logical design data and constraints. XST
places the NGC file in your project directory and the file is accepted
as input to the Translate (NGDBuild) step of the Implement Design
process. To specify XST as your synthesis tool, you must set the
Synthesis Tool Project Property to XST, as described in Changing
Project, Source, and Snapshot Properties.
Note : You can set the Synthesis Tool to XST or to a partner synthesis
tool.
XST Design Flow Overview
The following figure shows the flow of files through the XST
software.

XST Input and Output Files


XST supports extensive VHDL and Verilog subsets from the following
standards:
 VHDL: IEEE 1076-1987, IEEE 1076-1993, including IEEE
standard and Synopsys

56
 Verilog: IEEE 1364-1995, IEEE 1364-2001

In addition to a VHDL or Verilog design description, XST can also


accept the following files as input:
 XCF

Xilinx constraints file in which you can specify synthesis, timing, and
specific implementation constraints that can be propagated to the NGC
file.
 Core files

These files can be in either NGC or EDIF format. XST does not
modify cores. It uses them to inform area and timing optimization.
In addition to NGC files, XST also generates the following files as
output:
 Synthesis Report

This report contains the results from the synthesis run, including area
and timing estimation.
 RTL schematic

This is a schematic representation of the pre-optimized design shown


at the Register Transfer Level (RTL). This representation is in terms
of generic symbols, such as adders, multipliers, counters, AND gates,
and OR gates, and is generated after the HDL synthesis phase of the
synthesis process. Viewing this schematic may help you discover
design issues early in the design process. For details, see Viewing an
RTL Schematic - XST.
 Technology schematic

This is a schematic representation of an NGC file shown in terms of


logic elements optimized to the target architecture or "technology,"
for example, in terms of LUTs, carry logic, I/O buffers, and other
technology-specific components. It is generated after the optimization
and technology targeting phase of the synthesis process. Viewing this
schematic allows you to see a technology-level representation of your
HDL optimized for a specific Xilinx architecture, which may help you

57
discover design issues early in the design process. For details, see
Viewing a Technology Schematic - XST .
Note When the design is run in Incremental Synthesis mode, XST
generates multiple NGC and NGR files, which each represent a single
user design partition.

XST Detailed Design Flow


The following figure shows each of the steps that take place during
XST synthesis. The following sections describe each step in detail.

HDL Parsing
During HDL parsing, XST checks whether your HDL code is correct
and reports any syntax errors.
HDL Synthesis
During HDL synthesis, XST analyzes the HDL code and attempts to
infer specific design building blocks or macros (such as MUXes,
RAMs, adders, and subtracters) for which it can create efficient
technology implementations. To reduce the amount of inferred macros,
XST performs a resource sharing check. This usually leads to a
reduction of the area as well as an increase in the clock frequency.

58
Finite state machine (FSM) recognition is also part of the HDL
synthesis step. XST recognizes FSMs independent of the modeling
style used. To create the most efficient implementation, XST uses the
target optimization goal, whether area or speed, to determine which of
several FSM encoding algorithms to use.
You can control the HDL synthesis step using constraints. You can
enter constraints using any of the following methods:
 HDL source file

Enter VHDL attributes or Verilog metacomments.


 XCF

Enter global parameters and module-level constraints in the Xilinx


constraints (XCF) file. See the "Design Constraints" chapter of the
XST User Guide for more information on the use of constraints in the
XCF file.
 Project Navigator Process Properties

Set global parameters, such as the optimization goal or effort level.


You can modify the synthesis properties in the following tabs of the
Synthesize Process Properties dialog box:
 Synthesis Options

 HDL Options

 Xilinx Specific Options

Default property values are used for the Synthesize process, unless
you modify them.
Low Level Optimization
During low level optimization, XST transforms inferred macros and
general glue logic into a technology-specific implementation. The
flows for FPGAs and CPLDs differ significantly at this stage as
follows:
 FPGA Flow

59
The FPGA flow is timing-driven and can be controlled using
constraints, such as PERIOD and OFFSET. During low level
optimization, XST infers specific components, such as the following:
 Carry logic (MUXCY, XORCY, MULT_AND)

 RAM (block or distributed)

 Shift Register LUTs (SRL16, SRL16E, SRLC16,


SRLC16E)

 Clock Buffers (IBUFG, BUFGP)

 Multiplexers (MUXF5, MUXF6, MUXF7, MUXF8)

The use of technology-specific features may come from a macro


implementation mechanism or from general logic mapping. Due to
mapping complexity issues, not all available FPGA features may be
used. The FPGA synthesis flow supports advanced design and
optimization techniques, such as Register Balancing and Incremental
Synthesis.
Synthesis Errors:
1) The most common synthesis failures occur due to syntactical
errors.

 The most common errors are misplaced semi colons (;).

 A missing “end” at the end of if statements and processes.

 Errors due to non inclusion of sequential statements in


processes.

2) Certain VHDL statements are non synthesizable. An example of


such a statement would be usage of Access types because they
could specify hardware which is dynamic in nature.

3) A possible error arises when there is a type mismatch in


assignment statements.

An example of this would be a statement like

60
b<=s;

where b – A bit data type (representing a two state logic)

s – A std_logic data type (representing a three state logic)

Such errors also arise when a vector type signal/port is assigned


to a non-vector signal/port. It is for this reason that we have
declared all the signals and ports as std_logic_vectors.

4) The XST tool might also report warnings of constructs that have
the possibility of generating mismatches between RTL
simulation results and output netlist simulation results.

Design Implementation:
After synthesis, you run design implementation, which comprises the
following steps:

1. Translate, which merges the incoming netlists and constraints


into a Xilinx design file.
2. Map, which fits the design into the available resources on the
target device.
3. Place and Route, which places and routes the design to the
timing constraints.

In the Sources tab, select Synthesis/Implementation from the Design


View drop-down list, and select the pcim_top module . In the
Processes tab, double-click Implement Design to run the
implementation process in one step, or double-click Translate, Map,
and Place & Route to run each of the implementation steps separately.

A schematic showing the various processes through which a design


goes through before it is converted to a bitstream is shown below:

61
Translate

62
The Translate process merges all of the input netlists and design
constraints and outputs a Xilinx native generic database (NGD) file,
which describes the logical design reduced to Xilinx primitives.

Map
The Map process maps the logic defined by an NGD file into FPGA
elements, such as CLBs and IOBs. The output design is a native
circuit description (NCD) file that physically represents the design
mapped to the components in the Xilinx FPGA.
Place and Route
The Place and Route process takes a mapped NCD file, places and
routes the design, and produces an NCD file that is used as input for
bitstream generation

Errors while Implementing the Design


The errors that one encounters while implementing a project similar to
ours, falls into one of these categories.
1) NGDbuild errors:

This error is encountered when the NGDbuild tool cannot


locate or access the required NCG files.

When the user application makes use of logicores such as


buffers and latches, ensure that NGC files created during
core generation are copied into the project directory.

2) Errors due to flaws in the design of the User Application.


These errors are not detected while synthesis. An example
of such an error is a case when a bus is driven by multiple
sources at the same time. The solution to this would be to
implement proper tri-state logic.

After the process of synthesis and implementation are completed


successfully, we assign package pins to the FPGA and generate the
programming file (bitstream). Now the FPGA is programmed in Master
Serial Mode. Thus an on chip PROM is sed to store the programming
file. You can use the output from the Generate Programming File

63
process, a BIT or ISC file, to create a PROM, ACE or JTAG file that
can be downloaded into the FPGA's memory cells. This process opens
iMPACT, and in iMPACT you can create a PROM, System ACE, SVF,
XSVF or STAPL file.
This process is explained in some detail in the next chapter. In
addition, the next chapter also explains how the PCI card is to be
tested using Win Driver.

64
Chapter 7
Downloading & testing the Core

In the previous chapter, a detailed explanation was given regarding


how the core is synthesized & implemented. In addition to that, the
previous chapter also explained the user about the various errors that
might creep up during this process. This chapter is aimed at
explaining the user about programming the FPGA.

Programming the FPGA


Now, this chapter explains about how the core is downloaded into the
Spartan FPGA after an error free code has been implemented.
The FPGA is being operated in the master serial mode. In this mode,
the FPGA is connected to a PROM xcf02s . The PROM will be
programmed first which will ultimately program the Spartan FPGA in
the master serial mode. The basic steps involved in this process are
as follows-
1) Cable used

 Xilinx parallel cable IV

 Model DLC7

 Power 5V,0.2A

 Serial JG -041031

One end of this cable in connected to the parallel port of the computer
(or laptop) and the other end of this cable has 6 pin viz. VCC, GND,
TCLK, TDO, TCI & TDS which are connected to the respective PROM
pins on the PCI card. The PROM xcf02s is being in the programmed in
the JTAG boundary scanning mode. The PROM operates at 3.3V which
will be provided by the external power supply. Proper care has to be
taken while connecting the PCI card as a single mistake may lead to
serious consequences.

65
2) Once the proper connections have been made click on Generate
programming file in the processes tab to generate the
programming file. This programming file will have the .bit
format.

3) Now, click on Generate PROM, ACE or JTAG file. A utility tool


named iMPACT will appear on the screen as shown below. In
this window, select the Prepare a PROM file option then click
on Next option.

66
4) After selecting the Next option a new window appears. In this
window, write the desired name & the desired location of the
PROM file for example select the file name as trans1104 . Click
on Next option.

5) Now the next window appears. From the drop down menu select
the type of the Xilinx PROM for example select the xcf02s then
click on ADD option. Finally, press the FINISH option.

6) Now, a new window appears showing the user an icon of Xilinx


PROM device. Press the ‘OK’ to start adding device file to data
stream – 0.

7) Now, select the desired file which will add another device to the
PROM device like in our case the name of the file is

67
pcim_top.bit. A new dialog box prompts by asking whether the
user wants to add another file to the data stream. Click on the
‘NO’ option.

8) Now, double click on Generate file… option so that it can be


programmed into the Xilinx PROM. Finally, an icon appears
showing us that a Xilinx PROM device is connected to Xilinx
Spartan FPGA xc2s200 along with the message PROM file
generation succeeded.

9) On the left side, an option is provided as boundary Scan mode.


Click on this option A message appears saying Right click to
add device or initialize JTAG chain . Press right option on the
mouse and select Cable auto connect. Now, again right click the
mouse and select Initialize chain or directly press CTRL + I on
the keyboard.

68
10) A new dialog box appears asking the name of the file
which has to be burnt into the Xilinx PROM. The PROM files
are generated in the .mcs format like for example the file name
is trans1104.mcs.

11) Right click the mouse and select the Program option. A
dialog box appears with the heading programming properties
basically allowing the user to select the properties. Select the
erase before programming option in this box and then simply
press ok option.

69
A process dialog box appears indicating the progress of transfer
and within a few seconds a message will appear saying Program
succeeded. Thus, indicating that the PROM device has been
programmed and also the Xilinx FPGA will be programmed with
the help of the Xilinx PROM.

12) Thus, the above icon indicates that the trans1104.mcs


has been written into the xcf02s Xilinx PROM.

70
The above process explains the user in which the core is downloaded
into the Xilinx FPGA with the help of Xilinx PROM device.

Testing the PCI card

The next step is the testing of the card. The card is tested with the
help of a software called WINDRIVER. WinDriver is a multi-utility
software which is basically used to create custom device drivers as
well to test and debug the hardware. It is a software used by hardware
developers as well as software developers to test the new hardware &
to generate the device driver code to drive the hardware.

Features of WinDriver-
1) Immediate Hardware Access
Test your hardware through a graphical user-mode application,
without having to write a single line of code.

2) Generation of hardware-specific access code


WinDriver generates a skeletal driver code, customized for the
user's hardware.

3) Field-proven quality
WinDriver's technology enables you to concentrate on your core
business and successfully create first-rate drivers without
having to invest redundant resources in driver development from
scratch.

4) Debugging
Included graphical Debug Monitor to monitor kernel level
activity throughout the driver development process.

5) Multiple operating system support


WinDriver product line supports Windows 2000 / XP / XP

71
Embedded / Server 2003, Vista, Windows CE / Mobile, Linux,
Solaris and VxWorks.

6) Cross operating system capabilities


The same driver will run under all supported operating systems
without any code modifications.

7) FPGA Access
Access, control and program FPGA chips via the PCI bus.
Enhanced support for FPGA vendors including Altera and Xilinx
is included.

8) Complete .NET Framework Support


Easily incorporate WinDriver's C# or VB.NET code into your
existing .NET application using the powerful object oriented
managed extensions for C++ library.

Steps involved in building the driver-

1) Set up-

Plug the PCI card into your PCI slot of your computer & install
WinDriver software.

2) Select your device-

 Start DriverWizard from the windows Start menu.

 Now, once the new dialog box appears select New host
driver project.

 The driver wizard will show all the Plug and Play cards in
your machine.

72
3) Install the .INF file for your plug and play device-

When developing a driver for a Plug-and-Play device


(PCI/PCMCIA/CardBus) on Plug-and-Play Windows operating
systems, in order to correctly detect the device’s resources and
communicate with the device using WinDriver, you need to
install an INF file that registers your device to work with
WinDriver.
To generate and install an INF file with DriverWizard, follow
these steps:

 Click the Generate .INF file button in the wizard’s


Select Your Device dialogue. DriverWizard will
display information detected for your device –
vendor ID, device ID, device class, manufacturer
name and device name – and allow you to modify
the manufacturer and device names and the device
class information.

73
 Click Next in the INF generation dialogue in order
to generate the INF file and install it (if selected).
 When the INF file installation completes, select and
open your device from the list described in step 2
above.

4) Detect/Define your hardware’s resources-

DriverWizard will automatically detect your Plug-and-Play


hardware’s resources (I/O
ranges, Memory ranges, PCI configuration registers and
Interrupts). You can define
additional information yourself, such as defining registers for
your device as well as
assigning read/write commands for these registers to the
interrupt.

74
5) Testing your Hardware-

Before writing your device driver, it is important to make sure


your hardware is working
as expected. Use DriverWizard to diagnose your hardware:

 Read and write to the I/O ports, memory space and your
defined registers.

The above window shows an example in which the data can be


written into and read from the Base Address Registers. The size
of the data can also be varied according to the requirements of
the user for example the data can be of 8, 16, 32 bits. As
mentioned earlier, the size of the base address registers has to
be mentioned in the cfg.vhd i.e. in the configuration file. The
user can also read and write data in the I/O ports.

To read or write, follow these steps:

 Select the area where the user want to write data i.e. I/O
or memory.

75
 Select the required BAR.

 Click on Read / Write memory.

 Select the size of the data. This should be compatible


with your BAR’s size.

 Write the desired data. Click on Write option.

 The information panel will display the message Wrote to


BAR0 at offset: 0*0 value:0x12345645.

 To read data from the BAR click on Read. The same data
will appear in the information panel window.

 If the same data does not appear or data is not written


properly then the user can conclude that there is some
error in the hardware placed in the PCI slot.

Thus, in this way the user can test his hardware.

6) Generate the Driver Code

After the testing of the hardware has been done generate the code with
the help of the Generate code toolbar icon. The user needs to select
the programming language & the developing environment in which he
would like to generate his files. Also, the user needs to indicate
whether he wishes to handle Plug-and-Play and power management
events from within the driver code and whether he wishes to generate
Kernel PlugIn code. Finally, click on ‘ OK’ the required code would be
generated.

76
Chapter 8
Applications

The last chapter describes the method for testing the PCI card using
Win Drivers. Since basic data transfer is possible without distortion,
the card is functional. At TIFR, this card will be used for Data
Acquisition in one of the many processes for electron acceleration
measurement. This would entail monitoring of AC or DC voltages at
certain points of a Beam Profile Monitor. The PCI card contains a
vacant slot where ADC 805 can be mounted. A User Application can
be written such that it facilitates data transfer from the ADC to the
PCI Bus.
Apart from this, if the User Application is built upon, there are
illimitable applications to which the card can be put. Some of these
are:
 Embedded applications in networking, industrial, and
telecommunication systems.

77
 Add-in boards for PCI such as frame buffers, network adapters,
and data acquisition boards.

 Hot swap CompactPCI boards.

 Any applications that require an interface for PCI.

The last application really defines the crux of the project. Once the
core is correctly configured and set up for use, the card can be used
for virtually any application under the sun. This as long as any HDL
is capable of describing the function and has libraries powerful
enough to synthesize and translate the design.

Chapter 9
Further Work

The major achievement of this project has been the ability to read and
write from the PCI card. Before a complete Data Acquisition System
can be designed, two important designs need to be implemented.
1) A Memory Block (RAM) for RAM

The code in the User Application implements only a single


register structure which can deal with only one data at a time.
For data logging applications, the register will be replaced by a
Block of Data. For incremental project development, we first
need to implement this design, and check for basic data transfer.

A program for this in VHDL has already been written and


implemented.

2) Design of a Data Acquisition System which can do the


following:

78
 Transfer data from an external port (connected to an
ADC) to a storage element (RAM).

 Transfer data from the memory element to the PCI bus


whenever the card is read from.

This design needs to implement a local clocking scheme


(derived from the PCI clock signal) to synchronize the data
transfer from the ADC to the storage element and the integrity
of the data while reading from memory element.
A code for this has been written, but not implemented.
Once the data Acquisition system has been designed,
downloaded onto the FPGA and tested using Win Driver, the
next step would be to design a device driver for this card using
Windriver. This software generates a driver framework in a
programming language of the user’s choice. The user is then
allowed to modify the driver to suit his application.
To make the whole process of data acquisition interactive, a
Graphical User Interface can be designed. Data can be
represented in a tabular or graphical format. The interface can
be designed in two ways.
1) Using Microsoft Visual Studio (Visual Basic)

Visual basic offers the designer custom commands to interact


with the device driver and plot data in a graphical format.

2) Using the Matlab toolbox.

After all these steps are implemented, what evolves is a


complete data acquisition system which would allow the user
to monitor and access data from the comfort of desktop PCs
and workstations.

79
Chapter 10
Conclusion

The concept of Reconfigurable hardware became popular as early as


1984 when Xilinx introduced the first FPGA. After remarkable
innovations in this field and backed by powerful libraries, Xilinx and
other similar hardware solution providers have ensured that that

80
components like FPGAs and CPLDs have become indispensable while
designing hardware and custom solutions.
This project aims to utilize the FPGA’s reconfigurable property so
that a PCI card with customized functions can be designed. Here an
FPGA is used as the controlling element. The reason for doing this is
that an FPGA can be reprogrammed easily. Once the card functions
satisfactorily, it can be reprogrammed to implement any function. This
ability, coupled with the extremely high data transfer speeds afforded
by the PCI interface means that such system can be used for myriad
applications, the most basic being Data Acquisition Systems, where
this card will eventually find application.

Chapter 11
References

1) PCI System Architecture by Tom Shanley and Don Anderson.

81
2) VHDL Programming by Example by Douglas L. Perry

3) PCI Logicore Manual

http://china.xilinx.com/support/documentation/ip_documentation/
pci_ug159.pdf

4) Core Generator User guides

5) Xilinx Software Manuals

6) Spartan II Data Sheet

http://go.6to23.com/zhangzhenyan/product/xc2s50/spartan_II.pdf

Appendix 1 – Assigning Package Pins

82
You can assign input and output signals to package pins in your
design using the Assign Package Pins process. This process launches
the Pinout and Area Constraints Editor (PACE) for Spartan II-targeted
designs. Using the editor, you can then assign I/O locations, specify
I/O banks, specify I/O standards, prohibit I/O locations, and create
legal pin assignments using the built-in design rule checks (DRC).
To Assign Package Pins
1) In the Sources tab, select Synthesis/Implementation from the
drop-down list.

2) Select either the top module or the associated UCF.

3) In the Processes tab, expand User Constraints.

4) Double-click Assign Package Pins.

5) The UCF associated with the top module is displayed in PACE.


A UCF is created if none exists.

6) You can assign I/O package pins for your design in the UCF in
PACE.

A grid in the left hand panel allows you to assign locations to


different the ports. A screenshot of the grid is given below .

83
Since our FPGA is already connected in circuit on the PCI card, we
have used the following pin-out diagram and table as references while
assigning the pin locations.
To assign a location, say for AD0, first look it up in the table, get the
physical pin number and from the pin-out get the PCI pin number
(P60).

84
Add-in card
connector reference

85
FPGA Pinout

86

You might also like