About this tutorial
This tutorial has been conceived
as an introductory lab to PowerPC and EDK tools. All the files are provided
and the process of creation of the system is explained with detail.
This tutorial is also an introduction to the ML300 platform, which is
the more complex and powerful VirtexII-Pro development platform out
there. Several issues will be solved through the tutorial and references
will be made to several Xilinx's documents. Please refer to the "links"
section of this site to get the documents or links to them.
The basic idea behind this tutorial is to build a basic embedded system
based on the PowerPC405 microprocessor, and to use it as a base for
more complex systems. Two more complex labs on PPC405 in this site are
based on this first lab. This system will allow us to display "hello
world" type information using an UART and the hyperterminal in
our workstation. Additionally, we will be able to work with the leds
on the ML300 board through the GPIO peripheral. We will also use this
project as an introduction to some basic debugging techniques using
XMD and the GNU software debugger part of the EDK tools.
A printable version of this
tutorial is available here.
The final files for this tutorial are available here.
System requirements
This tutorial was developed
using EDK 3.2.2 (the latest version up to now; September 31), on a W2K
Workstation and the ML300 development platform. The files provided respond
to these specifications, however, the tutorial is meant to be easy to
migrate to another development platform or future (and past) versions
of EDK. If you find yourself in that situation and you find any trouble,
please contact us. Also, if you success in migrating this tutorial,
please send us your comments and anything you feel can be useful for
us to improve this tutorial.
Although this is a fairly simple project, depending on the power of
your computer, the compilation can take as little as 7 minutes, or as
much as 45. On my old PIII, 450Mhz and 256 Mb of Ram, it takes around
45 minute each compilation. On my powerful PIV 2.4Ghz and 512Mb Ram
laptop, it takes 7 minutes. It's your call!. Also take in consideration
that your workstation needs a parallel port (to configure the FPGA),
a serial port (to make the connection with the hyperterminal) and a
PS2 port (to power up the parallel IV cable). Most laptops don't have
these ports anymore.
Some assumptions made
We did some assumptions in
writing this tutorial. First of all, we are assuming you do have some
basic knowledge on C, embedded systems, microprocessors, and VHDL. This
save us the need in writing some details, but again, if you find any
thing that you think should be explained in more detail, let us know!!.
We also assumed you already went through the previous tutorials on this
site. This allows us to assume you have already some familiarity with
EDK.
System Description
The specification of our
system will be composed of a hardware description and its memory map
and a software application. These three components are the base of any
embedded system.
Hardware description
A PPC405 system is considerable
more complex than a Microblaze system. There are several additional
considerations that need to be made, that is why we will include new
components with respect to the Microblaze projects we build before.
This system will include the following hardware components:
- PPC 405: The brain of
the system, the microprocessor.
- JTAGPPC_CNTRL: This JTAG
controller will allow us to do some debug on the system using XMD
and the parallel IV cable.
- PLB Bus: The processor
local bus. Remember from basic computer architecture that busses have
hierarchies in any system. In our case this is the higher hierarchy
bus, the one closer to the processor. You will usually put your primary
instruction and data memory on this bus.
- PLB_BRAM_IF_CNTRL: This
is the controller for the memory. As the name implies, it will be
attached to the PLB bus.
PLB BRAM: The memory!!
- PLB2OPB_BRIDGE: This bridge
will allow us to communicate between the PLB and the OPB bus in a
master-slave (PLB-OPB) schema. This is a one-way bridge. Therefore,
is an OPB-PLB schema is needed a opb2plb_bridge will be required.
- OPB_BUS: This is the on-the-chip-peripheral
bus. Slow and non-critical peripheral will be attached to this bus.
- OPB_GPIO: This is the
generic input-output peripheral. In this system, this will manage
the leds on the ML300 board.
- OPB_UARTLITE: A very light
UART. This will be attached to the OPB bus and will allow the system
to display a "hello world" type information just to let
us know that our creature is alive!.
- OPB_INTC: It's an interrupt
controller. Although our system is not taking advantage of interrupts
yet, it will in the near future.
- DDR_CLOCK_MODULE_REF:
This is a very important module for PPC405 system. In these systems
you will need several different clocks, for the bus, for the cpu,
for peripherals, etc. The DDR_CLOCK_MODULE takes care of these details
for you.
- PROC_SYS_RESET: The system
will typically have different types of resets (i.e chip reset, system
reset, core reset, etc). The hierarchies and other considerations
can be very messy. This module takes care of the details for you.
A basic block diagram specifying
the interconnection between these components is shown in figure 1.

Figure
1
Memory Map
The system is described by
the following memory map:

Developing the System Hardware
Let's start the fun. As usual;
go to your XPS (EDK main GUI) and create a new project using the settings
shown in figure 2. This will match with the FPGA on your ML300, but
check it anyway, just in case. Remember to not pick a path for your
directory with blank spaces on it, such at "My documents".
This will generate an error on the application.

Figure 2
Now that we have the empty
shell of the project we can start adding the components of the system.
Go to Project -> Add/Edit Cores, Peripherals dialog and add the components
in our list at the very begging of the tutorial. You can also start
setting up the address ranges for these components, according to our
memory map defined early. The final appearance of this window is shown
in figure 3.

Figure 3
The next step is to start
making the connections between these components and the busses. For
this system we only have 2 busses, the processor local bus (PLB) and
the on-the-chip-peripheral bus (OPB). So, in the same Add/Edit Cores
dialog go to the "Bus Connections" tab and configure the PPC405
as the master for these two bases. BRAM_CNTRL, GPIO and UART peripheral
are setup as slaves. The final appearance of this menu is shown in figure
4.

Figure 4
Once the bus connections
are setup, we need to specify ports, internal, external signals and
connections. In the same Add/Edit Cores dialog, go to the "Ports"
tab and use the filter in the top left to select a component at a time
and add the necessary ports.
Let's start with the PPC405 core. Here there is a difference with respect
to the Microblaze systems, the number of required ports is huge!. The
final list of ports, its connections and polarities is shown in figure
5. A comment about this: if you take a close look on the ports defined,
we are basically using the reset pins (core, chip and system), the interrupt
input, a clock input, all the JTAG pins (this is necessary for the posterior
debug) and reset request pins. The PPC405 core has much more pins that
we can use to setup different capabilities of the core. Let's start
with these ports by now. We will keep adding ports as necessary in other
tutorials.

Figure 5
Let's check the ports of
the DDR_CLOCK_MODULE. This module will get the clock from outside the
FPGA (from the board's crystal) and will provide us with clocks for
the cpu, the busses and peripherals. The final configuration is shown
in figure 6. This is also something different with respect to the Microblaze
labs where we used a single clock signal for the whole system.
In the case of the busses, only two ports are necessaries, the clock
and the reset, for both, the OPB and the PLB bus. The ports for the
GPIO are mapped to external pins as well as the ports for the UARTLITE.
Consider additionally to setup a port called uart1_rst mapped internally
to ground. This is a signal that is not available on the UARTLITE core,
but we need to take care of it since that RS232 signal is actually connected
to the FPGA. Take a look in the answer database of Xilinx's support
site to the record 16632. This issue is explained there.
The INT_CNTRL has two ports connected, one to receive the UART interrupt
and the other to connect to the PPC405 core. These last settings are
shown in figure 6.

Figure 6
PROC_SYS_RESET ports required
and its configuration is shown in figure 7. This module will basically
take as input the reset signal from the board (outside the FPGA) and
generate the reset signals for all the internal components of the system.

Figure 7
Now we need to setup some
parameters. In the same Add/Edit Cores dialog go to the "Parameters"
tab and use the filter in the top left to select the components and
add parameters. We will setup parameters for the UARTLITE, the PLB2OPB_BRIDGE,
the PROC_SYS_RESET and the PLB bus. The parameters to be configured
are shown in figure 8. UARTLITE parameters are straight forward (the
clock frequency is setup to the PLB bus clock given by the DDR_CLOCK_MODULE),
as well as the PLB bus and the PROC_SYS_RESET module. In the case of
the PLB2OPB_BRIDGE is not that trivial. We need to configure three different
address ranges. There is not really a need for this, this will basically
give as some flexibility but it will cost us additional FPGA resources
for the address decoding. This kind of address configuration can be
useful when we want to setup some peripheral addresses in between different
buses address ranges. So, let's setup these three ranges just for the
sake of practicing and for future needs (last lab on this site)




Figure 8
That's it for components
configurations. Click on the OK button and XPS will show your brand
new system. We are almost done. The next step is to generate a netlist
of the hardware specification. There are two different ways to do this.
You can export your design to ProjNav and use ISE 5.2 to compile it
or you can let EDK do that for you in a transparent way; that's what
we are going to do. In XPS go to Options/Project Options, select the
"Hierarchy and Flow" tab and configure the implementation
tool flow as XPS (Xflow) and Synthesis tool as ISE XST as is shown in
the following figure 9.

Figure 9
Now; in XPS go to Tools/Generate Netlist. You will see a call to a script
named "xflow"; this is basically calling the compiler in ISE
5.2 to compile your hardware. It is important to have the ISE tools
and environment variables correctly installed. This is going to take
a while.
Once this is done, we proceed to generate the bitstream, but for this,
we first need to add a *.ucf file with the constraints an pins maps
needed. We will talk about timing constraints later; let's first talk
about pin mappings. The ML300 board is a very complete and nice piece
of work, but is also a bit complicated. However, we do have all the
documentation needed. First of all, the schematics provided with the
ML300 kit are very useful to understand the basic pins and connectors
connections. Most of the connectors are on the ML300_CPU board. However,
most of the leds and pins that can be used to test inputs and outputs
are on the ML300_PWR_IO board. A good reference to find the FPGA pins
connected to the different connectors and peripherals on the ML300 board
is [3] provided with the ML300 kit. The UCF file is also provided in
this tutorial, take a look at it and try to confirm the pins assigned
for the GPIO and UART using the documentation just mentioned.
The UCF file must go on the directory call "DATA" in the project
directory. Its name must be "system.ucf". Once the file is
there, in XPS go to Tools/Generate Bitstream. This will generate a file
called "system.bit" which contains your hardware design in
"FPGA language".
The bitstream generation will also provide you with some timing analysis
results. Check that there is probably some constraints (originated from
our main timing constraints in the UCF file about the clock of the system)
that will no be fulfill. To solve this, uncomment the lines on the UCF
files (read the UCF file, everything is well commented). This will relax
a bit the timing constraints for some path of the design and after a
new bitstream generation, all warnings and errors related to timing
should be gone. Now our hardware section is done.
Developing the Software
Design
This is the next major portion
of the project. First of all, we need to specify the driver level we
will use with our different peripherals. The architecture of the device
drivers supports three different levels: Layer 0, 1 and 2.The idea for
these different layers is to allow the user to select specific features
and size of the software running on the system. Remember we are trying
to design embedded systems, this implies a custom system for a specific
application; therefore, we need the ability of select the exact features
we want and if it's possible; save some space in memory. We will see
more about it when playing with the application. All the drivers provided
with EDK support multiple instances of a device. Take in consideration
that Layer 1 and Layer 0 are OS independent.
As you can image, layer 0 is the low level drivers, it is designed for
small systems, typically for internal memory on an FPGA. No error checking
is provided, and it will only provide primary device features. More
information on this topic can be found on Chapter 6 of [1] and a device
driver summary on [2].
Go to XPS and double click on "uartlite_0" to open the peripheral
Options dialog box shown in figure 10 a. You will usually find 2 available
drivers level per peripheral, 0 and 1. Set the UARTLITE to level 0.
Do the same for GPIO, but in this case, set the driver level to 1 as
shown in figure 10 b.

Figure 10 a

Figure 10b
Next we need to configure
STDIN and STDOUT. The idea is to map functions like printf, scanf and
so forth to an I/O peripheral in our design. Double click on ppc405
and setup the STDIN and STDOUT to our UARTLITE as shown in figure 11.

Figure 11
The C code for this lab is
provided. Take a look at it and the comments included. Whenever you
are planning to use a driver to manage a specific peripheral, you need
to go to the Xilinx Drivers documentation (Start -> Programs ->
Xilinx Embedded Development Kit -> EDK Documentation) and check for
the struct declaration. This was the case for the XGPIO struct used
in the code provided, for instance.
Now we need to compile our program and add it to the bit file generate
for the hardware specification. You must realize that the program you
are about to compile will go directly into the internal memory provided
by the BRAM block in the hardware specification. This means that the
size does means as we will see later.
Before compile, let's setup our compiler options: In XPS go to Options/Compiler
options, in the "Environment" tab set the OS as "Standalone"
and the "Core Clk Freq" as 300. In our case we are using a
standalone configuration because we are not using any operating system
and the driver levels we are using are 0 and 1; not 2. Now go to the
"Optimization" tab and in "Debug options" make sure
to mark the "Create symbols for debugging" option. This will
allow us to do some debug on our code later. The last thing to take
care of is on the "Details" tab. We need to specify a "Program
Start Address" and a Stack Size. Set the stack size to 0x2000 and
the program start address to the base address defined for our memory
bank: 0xFFFF_0000. This is important. We are telling the compiler in
which memory position the program will be written. If we miss this configuration
is very likely that our program will not be recorded in the right position
(probably 0x0) and the microprocessor will not have access to it. Check
figure 12 for these settings.



Figure 12
Now we are ready. In the
XPS go to Tools/Generate Libraries, to copy and generate the libraries
needed. What we need is going to be defined based on the peripherals
we are using and the driver levels configured before. A complete set
of directories will be created on the project directory and a bunch
of files copied.
Once this is done, we need to compile our source programs. First create
a directory named "code" under the project directory, copy
the C file provided and then do a left click on "PPC405/Sources"
at the left panel (System tab) and choose "Add files" options.
Select the C file with our code. Now, in XPS go to Tools/Compile Program
Sources. This is going to create an file called "executable.elf"
under the directory PPC405_0/code in the project directory. This is
the actual machine language file with our program.
Here is a comment, in XPS go to Tools/Get Program Size and take a look
at the size of your program and compare it with the size of your memory.
Now, instead of using "printf" in the C code, use the function
"xil_printf"; compile the code and get the size of the program
again. Any difference? Of course there is a different. "xil_printf"
is a much smaller function. As this, there is a bunch of smaller functions
defined. Go take a look at [1] for more information.
The last thing to do is to add this file into our hardware bit file
to download everything together to the FPGA. This is done by going to
Tools/Update Bitstream. This will generate a file called "download.bit"
into the "Implementation" directory, which now contains everything
needed to have our project up and running in the ML300 board.
Programming the board
To program the board we will
use the Parallel IV cable provided with the ML300 kit and the tool "Impact"
from ISE 5.2 tools. So, go launch Impact and follow the wizard:
- Operation Mode Selection:
Configure Devices
- Configure Devices: Boundary-Scan
mode
- Boundary-Scan Selection:
Automatically connect to cable and identify Boundary-Scan chain.
Impact will detect two devices, which is normal, since the first device
in the chain correspond to the ACE system, and the second is the FPGA.
Go and assign the file download.bit that we just created to the FPGA
and program it. Now we are ready to play a little bit.
Debugging and playing around
with EDK tools and the ML300 board.
Let's connect to the processor
using XMD. In XPS go to Tools/XMD; a console-type window will open.
Type in "ppcconnect" and you should see something similar
to figure 13.

Figure
13
This means we
are in. By typing "help" you can take a look to the different
commands. More detail can be found at [1]. For instance, let's read
and write some memory positions or registers. Type in:
rrd % it will show
you the values on all cpu registers
rwr r1 0xFFFF % it will write the word 0xFFFF in the register
1.
rrd % to check that we actually wrote in the register.
We can also check that our
program is in memory. Let's first check our program and the memory positions
it is using; in the XMD console window go to the directory where the
executable file is stored by using common CMD commands. Once there type:
powerpc-eabi-objdump -d
executable.elf > objdump.txt
This will dump the executable
into a text file called objdump.txt. Open the text file and look at
the information on it. You will see that the first memory position used
is 0xFFFF_0000 (remember we configured this before), and you can actually
check what hexadecimal values are stored at that position. Check it
by typing:
mrd 0xFFFF0000 16
% to read 16 words from memory position 0xFFFF0000
Let's now play with GPIO.
If you take a look at the datasheet of the GPIO core, there are two
main register associated with it. The GPIO_DATA (@ GPIO base address)
and the GPIO_TRI (@ the GPIO base address + 0x4). The first one can
be used to write or read data, and the second one will defined whatever
or not, the GPIO is an output or and input.
Let's go to the XMD and type:
mwr 0x60008004 0x0
% we are writing 0x0 in the GPIO_TRI making GPIO outputs
mwr 0x60008000 0xFF % we are writing 0xFF in the data register.
The first 8 leds should light up!
You can keep playing writing
different values on the data register.
Enough playing around, let's
go to the GNU debugger, in the XPS go to Tools/Software Debugger. A
window similar to figure 14 will open. Click on the "Run"
icon. The debugger will download the executable to the FPGA again and
it will give options to go step by step, on the C source or the assembly
source. All this can also be done using the XMD console. For you to
be convinced of this, type "ver" on the XMD console. This
will habilitate the verbose mode. All operations on the Software debugger
will generate info on the XMD console. Take a look at the commands.

Figure
14
Well, our application should
be running by now. In your workstation (connected with a serial DB9
cable to the serial port 1 of the ML300) open the hyperterminal and
configure it to 9600 bauds, 8 bits of data, stop bit 1, no parity and
Control Flow setup to None. You should see now a count up like the one
in figure 15.

Figure
15
Our first basic PPC405 lab is done. This will be useful as a base project
for more complex labs. A good technique to build these systems is to
progressively add components and test its performance. It is not a good
idea to build a big system from scratch directly.
If you find any typo/error in this tutorial or if you have any comment
that can help to improve it, please shoot us an email!.
References
[1] Embedded System Tools
Guide. Embedded Development Kit (EDK v3.2.2, May 21, 2003).
[2] Device Driver Summary provided with the ML300 platform.
[3] ML300 Documentation.
Disclaimer:
This document, the contents
and the sample code, is provided AS IS without any expressed or implied
warranty. By providing this design, code, or information as one possible
implementation of this feature, application or standard, we are not
making representation that this implementation is free from any claims
of infringement, and you are responsible for obtaining any rights you
may require for your implementation.