Level: Intermediate Lewin Edwards (sysadm@zws.com), Design Engineer, Freelance
22 Feb 2007 Explore both the hardware and software sides of a complete Virtex4 project. In this second and final installment of the Xilinx hijinx series, you add and remove device cores from your project, interconnect project components, build the bitstream, integrate it with C code, and download the entire thing to the FPGA.
The previous article explored the ML403 evaluation
board and FPGAs in general and gave you a very slight taste of the
Platform Studio user interface. In this concluding episode, it's time to
get down and dirty and start poking actual bitstreams and code onto the
board. We'll explore what you can -- and cannot -- accomplish with the
ML403 as shipped.
However, you always need to walk before you can run, and the first step is to understand how to build and run your code. Configuring a
system entirely from scratch is a fairly involved process. Believe it or
not, this is actually a feature, not a bug. At the "hardware" level (or,
the HDL code), you need to be able to define how many of each peripheral
your FPGA will contain, to which processor they will connect (remember
that you can instantiate up to two PowerPC®s inside the Virtex4!), to which
internal bus they will connect, and where they lie in the processor's
address space.
Because of the startling complexity of building a system from the ground
up, I'm not going to attempt to explain it in this article; I will simply modify
one of the samples shipped with the EDK in order to demonstrate what's
necessary in terms of initial system setup. If you want to learn about how
to build FPGA systems from nothing, I suggest you start with a very simple
functional example; for example, implement an AND gate or something equally
trivial, map its signals to I/O pins, and build your understanding from
that point. You don't need any hardware or costly software to do this;
just download the free WebPACK edition of ISE and the free Xilinx edition
of Modelsim, and play around in simulation.
For this little walkthrough, however, start by making a local, writable
copy of the samples directory off the EDK CD-ROM. A word of warning: EDK
-- or perhaps more accurately, the underlying GNU toolchain -- does not
handle spaces in filenames at ALL. This means that if you're running on Microsoft®
Windows®, you can't put design files on your desktop (since, by default,
your desktop directory will be C:\Documents and Settings\<user
name>\Desktop); the same comment applies to My Documents. To avoid this
problem, start by copying the entire reference_systems directory from the
EDK CD-ROM to C:\. By the way, this whitespace issue isn't an inherent
limitation of the GNU toolchain; it's more a function of the EDK GUI
wrapper, which doesn't recognize and correctly escape embedded whitespace
in filenames when it passes these filenames to the external cygwin-hosted
utilities.
Now, launch Xilinx Project Studio and at the first dialog, select Open
A Recent Project, then click OK. Browse to
c:\reference_systems\EDK_Projects\ml403_emb_ref_ppc and open the
system.xmp file you will find there. While it's loading, connect up your
ML403 board. I suggest you connect at least the serial port through nullmodem
to your computer or some other terminal (configure the terminal for 9600,
8 data bits, no parity, one stop bit), and the VGA port to a spare
monitor. Once the board powers up and you see the welcome menu, don't
select anything -- loading some of the examples there will change the I/O
mappings and the steps you'll do later won't work.
After the project finishes loading into Project Studio, you'll see a
tree-format browser of hardware components in the left pane and a
graphical illustration of the design flow in the right pane. (The
illustration is actually a handy image map; you can click on hot spots in
the picture to view a help file on topics of interest.)
The default system configuration includes a bunch of peripherals: an
interrupt controller, 16550-compatible UART, a dual PS/2 device controller
to handle the mouse and keyboard ports, and much more. Since this is a
more or less fully configured system, I'll use it as the basis for
this experiment. Ideally, all you should need to do at this point in order
to build and download the complete hardware description is to select
Download from the Tools menu.
Unfortunately, when you do this, XPS will check the dependencies and try
to build the bitstream before downloading it. During this process, you'll
see several messages like the following, and the build will fail with the error
"MDT -- platgen failed with errors!":
ERROR:MDT - opb_uart16550 (opb_uart16550_0) -
C:\reference_systems\ml403_emb_ref_ppc\system.mhs:324 - invalid license
or no license found!
INFO:coreutil - Valid license for feature opb_iic_v1 not found.
You may use the customization GUI for this core but you will
not be able to generate any implementation or simulation files.
Contact Xilinx to obtain a full license for this LogiCORE. For more
information please refer to www.xilinx.com/ipcenter/ipevaluation/
FLEXlm Error: No such feature exists (-5,21)
The reason for this difficulty is that many of the cores provided with EDK
are commercial; they cost money. You can see the three affected cores on
the left-hand side of Figure 1 -- they're the ones that show up with a
$ icon in the System tree.
Figure 1
Note that you can obtain evaluation versions of most of the commercial
cores from Xilinx, but they are quite limited. You could also explore free
third-party cores from sources such as opencores (see Resources), but some adaptation will definitely be
necessary to connect these cores to Xilinx bus IP.
As an immediate workaround to the build issue, you could simply delete the
three offending cores by right-clicking each and selecting Delete.
This leaves you with a system that would build successfully, but would be
quite irksome to use. You can live without Ethernet and IIC, but the UART
is really vital for debugging, if nothing else; you need to fix this.
Luckily, Xilinx offers a free "uartlite" core, which you can easily add.
Simply right-click in the System pane and select Add/Edit Cores...
You'll be presented with the dialog shown in Figure 2:
Figure 2
(As a side note, the prefix "plb" refers to the Processor Local Bus, while
"opb" refers to the On-Chip Peripheral Bus).
To add your new peripheral, scroll down the list on the right-hand side and
find opb_uartlite, select it and click Add. This imports the
peripheral, but at this stage it's just a disembodied piece of hardware
floating around inside the FPGA (EDK won't let you build it like this).
You need to connect the peripheral to a bus so that the processor can talk
to it, and assign it a slice of the PowerPC's address space so the
processor knows where to find it; you also need to tell the router how to
connect its signals to other peripherals or physical chip pins. All of
these functions are assigned on the Bus Connections tab, shown in Figure 3:
Figure 3
From left to right, the three white columns represent the On-chip
Peripheral Bus, Processor Local Bus, and Device Control Register bus. Note
that there are several other possible buses in a Xilinx design; other
buses can be added from the list in the upper right of this dialog.
Each peripheral instance is represented by a line in the table; the three
cells to the right of the peripheral's instance name represent the
relationship that instance has to the corresponding bus (master, slave or
master + slave).
If you scroll down to the entry for opb_uartlite_0 sopb, which you
just added, you'll see that it has no connections (all three bus squares
are blank). The only connection you can make with this device is a slave
connection on the OPB; click in the leftmost white bus square to establish
this connection (a lowercase 's' will appear in the box).
Now you need to define where the UART lives in the PowerPC's address space; do this on the Addresses tab, as shown in Figure 4:
Figure 4
Scroll to your UART's line, and enter 0xA0000000 in the Base Address field
(this was the default address for the 16550 UART you just deleted, so you
know it's a safe place to put the lite UART). In the Size drop-down list,
select the smallest value (256) -- the lite UART actually has only four
32-bit registers, and hence only requires 16 bytes of address space, so
256 bytes is plenty.
Incidentally, I didn't divine that second number by any magical means. If
you click on the Parameters tab of the dialog in Figure 4, select
the peripheral of interest from the drop-down list at the upper right
(note: This list only shows peripherals you have instantiated in the
design.), and click Open PDF Doc, you'll be able to read the full
datasheet for the IP core in question. You can find these PDFs in
C:\EDK\hw\XilinxProcessorIPLib\pcores (assuming you installed EDK to the
default target directory).
Penultimately, you need to map the UART's ports -- in this case, the
transmit and receive data lines -- to external ports and connections
inside the FPGA. This is carried out in the Ports tab, shown in Figure 5:
Figure 5
To establish the desired mappings, scroll down the right-hand list to find
opb_uartlite_0 and click RX, then click Add. A
new line for this signal will appear in the left-hand list. All you need
to do is select the appropriate connection from the drop-down list in the
Net Name column; in this case, uart_RX. Do the same thing
for the TX line, except that of course it's mapped to the "uart_TX" net.
The Interrupt line in the peripheral needs to be mapped to the signal
"uart_intr." This will not appear in the drop-down list (only externals
appear in the drop-down list within the internal connection table); after
adding Interrupt to the list of internal connections, you need to
single-click on that line, then click Connect and
manually type in uart_intr. (This signal is
multiplexed with a bunch of other interrupts; look in the drop-down list
inside the Connect button and you'll see a line that begins "uart_intr
& ps2_1_intr & ... .")
Since you deleted some peripherals, you also need to delete the external
port connections to which they mapped their output ports, otherwise you'll
get an error about a signal having no driver. The specific list of ports
to be deleted in this case is: phy_rst_n, phy_tx_data, phy_tx_en,
phy_tx_er, iic_scl_int_O, iic_scl_int_T, iic_sda_int_O, iic_sda_int_T,
iic_intr, ethernet_intr. The easiest way to get rid of these is to edit
the system.mhs file; look in the System tree, under Project Files, and
double-click the MHS file to open it. All of these except the last two can
be removed by simply commenting out the appropriate PORT lines; to get rid
of the interrupts, locate this line:
PORT Intr = uart_intr & ps2_1_intr & ps2_2_intr & iic_intr &
ac97_play_intr & ac97_record_intr & sysace_intr & phy_mii_int &
usb_hpi_int & ethernet_intr
and replace it with:
PORT Intr = uart_intr & ps2_1_intr & ps2_2_intr & ac97_play_intr &
ac97_record_intr & sysace_intr & usb_hpi_int
You can now also experiment with the Parameters tab; this allows you to
tweak the configuration of each instance of a core. In the case of the
UART, there's not a lot to configure apart from the baud rate and framing
details.
You have now assembled a complete design; if you're thus inclined, you can
now build and download the bitstream. Warning: This takes a long time and
you can carry out the steps in the next part of this article without doing
any bitstream building. If you insist on trying this, please note that the
build process will give you an error parsing synthesis.sh -- this appears
to be a conflict with current versions of cygwin. When you hit this error,
open a command prompt and run the following:
cd C:\reference_systems\EDK_Projects\ml403_emb_ref_ppc\synthesis
xst -ifn system_xst.scr
Then retry the build operation and it will complete successfully. (This
problem is not documented on Xilinx's Web site, so it might be an error
specific to the particular versions of EDK/ISE and Cygwin I am using --
however, I have reproduced it on two different computers, so be wary!)
How do you get software into this structure? The usual method is to include
a tiny program inside a piece of block RAM (BRAM) within the FPGA
bitstream. This tiny program is a bootloader that will initialize the
attached memory controllers, possibly load the main program from some
external source, and jump to it. For the sake of brevity, we won't
actually design a program that performs those functions; instead, we'll
look at how to build and load one of the sample programs inside this
project.
In the main XPS window, click the Applications tab and you'll see
the tree shown in Figure 6:
Figure 6
Note the top item (ppc405_0_bootloop). This is a dummy do-nothing program
used when you're developing the software for your design. The idea is that
you include this "halt and wait" code in the BRAM so you can configure the
FPGA, then attach a debugger and download the code you want to run. When
your software engineers have developed a working bootloader, you can roll
it into your XPS project and select it as the default contents to be
loaded into BRAM. You then build a final, shippable bitstream which gets
burned onto your platform flash, or whatever method your design uses to
configure the FPGA. At power-on, the FPGA is configured with that
bootloader built in, and the CPU core's power-on reset process will start
the bootstrap process.
We want to experiment with a nice simple example, so right-click on
button_led_test and select Make project active. Right-click
it again and select Build Project. You'll see three errors; the
first two remind you that stdin and stdout were originally directed to the
16550 UART, which doesn't exist. Return to the System pane and edit the
system.mss file, which defines the operating system environment in your
design. Locate this stanza:
Listing 1
BEGIN OS
PARAMETER OS_NAME = standalone
PARAMETER OS_VER = 1.00.a
PARAMETER PROC_INSTANCE = ppc405_0
PARAMETER stdin = opb_uart16550_0
PARAMETER stdout = opb_uart16550_0
END
|
Change the stdin and stdout lines to reference opb_uartlite_0. Also locate
the following stanza and comment out the entire thing, since you don't have
Ethernet support in your design:
Listing 2
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = xilnet
PARAMETER LIBRARY_VER = 2.00.a
PARAMETER emac_instname = opb_ethernet_0
PARAMETER no_of_tcp_conns = 5
PARAMETER no_of_udp_conns = 5
END
|
Finally, you want to load the driver for the lite UART. To achieve this,
simply add the following stanza to system.mss:
Listing 3
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = uartlite
PARAMETER LIBRARY_VER = 1.00.b
PARAMETER HW_INSTANCE = opb_uartlite_0
END
|
You can find all the drivers and their API documentation in
C:\EDK\sw\XilinxProcessorIPLib\drivers. Unfortunately, there's a problem
with the uartlite driver: the directory is named for Version 1.00b, but
the files inside it are named for Version 2.1.0. The simplest way around
this is to go into the 1.00b data directory and make copies of the .mpd
and .pao files in there. Change the filename of each of these copies to
opb_uartlite_v1_00_b.* and the hardware dependency checks in your build
will be OK. This environment problem was likely injected by the IP updates
that Xilinx requires you to install before you start using EDK;
take heed from this that there are probably other cores with the same
lurking problem. Fortunately, the naming convention can easily be deduced
and the problem fixed simply by looking at the filenames and version
numbers.
 | |
At this point your build should have gotten as far as trying to compile
button_led_test.c, where it would have encountered a bunch of errors.
These errors are caused by the fact that this sourcefile references
xuartns550_l.h, which is part of the (deleted) 16550 driver. Patching this
program to work with the lite UART driver is relatively trivial if you
look at the API documentation for uartlite, so simply comment out
all the lines with errors so you can get to loading the code onto the
board. (While you're in there, note in passing how the program imports the
GPIO base address from xgpio_l.h -- this is dynamically updated by EDK if
you shuffle around the base address of the peripheral.)
After you comment out all the offending lines and build the executable,
you'll wind up with button_led_test.elf in
C:\reference_systems\EDK_Projects\ml403_emb_ref_ppc\ppc405_0\code. You're
almost there! Ensure that the JTAG adapter is attached, and select XMD
from the Tools menu. Since this is probably the first time you ran it,
you'll be asked to configure the settings; the only thing you should need
to change here is JTAG Cable Type -- click the USB
radio button. Click Save.
XMD will start a command-line session with the project directory as the
current working directory. Type cd
ppc405_0/code and press Enter. Now type dow
button_led_test.elf to download the program, and run to run it. You'll see the following output on the
debugger:
Listing 4
XMD% dow button_led_test.elf
section, .text: 0xffff0000-0xffff038c
section, .boot0: 0xffff26d0-0xffff26e0
section, .boot: 0xfffffffc-0x00000000
section, .rodata: 0xffff038c-0xffff03a6
section, .sdata2: 0xffff03a8-0xffff03a8
section, .data: 0xffff03a8-0xffff0698
section, .fixup: 0xffff0698-0xffff06ac
section, .got2: 0xffff06ac-0xffff06cc
section, .sdata: 0xffff06cc-0xffff06d0
section, .bss: 0xffff06d0-0xffff26d0
Downloaded Program button_led_test.elf
Setting PC with program start addr = 0xfffffffc
PC reset to 0xfffffffc, Clearing MSR Register
XMD% run
PC reset to 0xfffffffc, Clearing MSR Register
Processor started. Type "stop" to stop processor
RUNNING>
|
You've now downloaded and started your first PowerPC program inside an
FPGA. Pressing any of the buttons on the five-way joystick area will cause
the LED adjacent to the appropriate button to illuminate.
All of the above looks fearsomely complex when it's written out in detail
and you're seeing it for the very first time, but when you understand the
design flow and spend a couple of days experimenting to find the toolchain
idiosyncrasies, you'll find that it's really a very simple system for
manipulating highly complex FPGA structures. The EDK hides the majority of the
annoying dependency handling from you rather neatly, though as you've
seen, it is sometimes necessary to bypass the GUI and get down into the
actual source files for the FPGA side of things.
Resources Learn
-
See the Xilinx ML403 Evaluation Platform Demos and Reference Designs for
direct download links for several reference designs that run on the ML403.
-
Opencores has a large number of free
HDL cores for various functions.
-
cygwin
and
minGW
both help to make a Windows environment more UNIX®-like. cygwin is governed
mainly by the GPL, while minGW is mainly in the public domain --
note that the word 'mainly' is used here to warn you that some components
in each
of the collections are exceptions to this overgeneralization.
-
Keep abreast of all the Power Architecture-related
news that's fit to print: subscribe to IBM microNews.
Get products and technologies
Discuss
About the author  | |  |
Lewin A.R.W. Edwards works for a Fortune 50 company as a wireless security/fire safety device design engineer. Prior to that, he spent five years
developing x86, ARM and PA-RISC-based networked multimedia appliances at
Digi-Frame Inc. He has extensive experience in encryption and security
software and is the author of two books on embedded systems development.
He can be reached at sysadm@zws.com.
|
Rate this page
|