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.
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
-
Learn more about
IBM cores,
ASICs, design methodology, and more.
-
Learn more about the
PowerPC
405 embedded core.
Discuss
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.





