PowerPC - ML300 Lab 3
About this Lab
In this lab we will develop
a complex system from the hardware and software point of view. All the
files are provided and the process of creation of the system is explained
with detail. This lab will use all the concepts we saw on the previous
two labs. The hardware side of this lab includes now an Ethernet core
while the software side includes additional interrupt routines for this
core and a modular/multiple files - type program is introduced as a
mean to deal with too large programs. Most of the code for this lab
was taken from the examples provided with the drivers; however some
changes need to be done in order to have this system up and running.
All system's characteristics are provided, but we will not get into
the detail on how to configure such characteristics using EDK. If you
are not familiar with EDK tools please start with the first two labs
before trying to do this one.
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, 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.
This is fairly complicated
system when compared with the previous labs. Think about working on
a PIII 512Mb RAM at minimum. 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!!.
System Description
Although this system has
a basis very similar to the first tow labs, we think it is better to
start this project from scratch since there are some noticeable changes.
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
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 internal
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.
- OPB2PLB_BRIDGE: This will
provide the other direction of communication between the PLB and the
OPB bus.this is needed
since we will add an Ethernet core that hangs from the OPB bus as
a MS (master-slave squema).
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.
- OPB_TIMER: To provide
with means to measure time and generate interrupts. This is include
just for didactical reasons.
- OPB_ETHERNET: An Ethernet
core, which is one of the real new and interesting thing to add to
our system with respect to the previous systems.
- OPB_DDR: Double Data Rate
core, which is the other important new thing with respect to the previous
labs. This core will provide the means to connect to the outside-the-chip
memory provided in the ML300 board. This is necessary because the
programs (C code) we will use in this project are too big to be stored
in the on-chip-memory provide with the Virtex-II Pro. Solution: we
will use the external memory to store the program.
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:

Note the size of the external memory we are using, it's huge!! , a good
question is: Why in the world do we need the internal memory if we already
have a huge external memory space? Well, every PowerPC system requires
having its boot section starting at 0xFFFF_FFFC. Since our external
memory is not big enough to get up to that memory position we are using
internal memory to cover that requirement. (Take a look at Programs
and Memory, page 300 of [1]). As a result our system has a non continuous
memory space.
Developing the System Hardware
Since you are familiar with
EDK this part should be a piece of cake. You need to create a new project
and add the cores specified above and configure the address space. You
also need to define the bus connections (figure 2) and the ports connections
(figure 3,4,5,6), which is kind of tedious because this is a large system.
Some parameters must also be configured (figures 7 to 14).

Figure 2

Figure 3

Figure 4

Figure 5

Figure 6

Figure 7

Figure 8

Figure 9

Figure 10

Figure 11

Figure 12

Figure 13

Figure 14
Now we need to generate our
.ucf file. This is no trivial task considering that now we need to define
the ports for the external memory and the Ethernet core. The .ucf is
provided here. Note the following:
the DDR is a big Indian-type storage; a conversion is needed and executed
in the ports connections. Also, the Ethernet core requires some specific
consideration on the *.ucf file. For more detail on why those specific
constrains are declared; take a look at the Design Constraints section
of the opb_ethernet core datasheet [2].
We are now ready to generate
the bitstream for the system (download.bit file).
Developing the Software Design
Now let's talk about the
software side. Taking the second lab as basis, we will configure our
timer and its interrupt handling routine to print information on through
the UART. The new thing is this lab is the inclusion of an interrupt
handling routine for the Ethernet core. You will see that our code is
now too big to fit into the Virtex2 Pro; that is why we are using external
memory. Another issue with this "big program" is that now
is a little bit messy to have everything in one file, so we are introducing
the partition of the program on several files or functions libraries
that can be reused or call by the main program.
As before, our code is based
on the examples provided with the drivers. We will setup the timer to
interrupt each 13-15 seconds, and we will test the Ethernet core in
loopback mode just to see if our hardware side is working. As usual,
the code is provided and commented. The first set of code can be downloaded
here.
The files provided are:
- System.c : Contains the
main program
- SetupInterruptSystem:
Contains the function SetupInterruptSystem(*Timer, *Emac) which will
basically configure the interrupt controller and make the connections
to the interrupt handling routines.
- EmacFunctions.c : Contains
a set of functions we will use to setup the Ethernet core, including
the interrupt handling routines. Note that in the case of the Ethernet
core, we need to specify routines for error handling; send and receive
interrupts.
- TimerCounterHandler.c:
Interrupt handler routine for the timer.
- System.h, SetupInterruptSystem.h,EmacFunctions.h:
Header files.
Carefull: Don't copy the
header files in the $project_path/ppc405/include directory since that
directory is deleted when you generate the libraries and compile the
source program. You need to create a directory under $project_path/code,
let say its name is also "include". Move all your headers
to that directory and specify to the compiler that it need to include
those files by going to Options/Compiler Options and add the directory
path as shown in figure 15. You also need to add all the .c files by
right clicking in the source files section of System window in the XPS
interface, as shown in figure 16.

Figure 15

Figure 16
Open the EmacFunctions.c
file and take a look at the LoopbackFrame function. This function will
send a frame (of size 200) and wait until both, send and receive are
completed. To check the completion it is using to boolean variables:
SendDone and RecvDone. Our code is a little bit different to the example
provide with the driver (the example can be found in your EDK installation
directory: EDK\sw\iplib\drivers\emac_v1_00_c\examples); we just changed
the while condition to actually wait for both, SendDone and RecvDone
to have the XTRUE (1) value and in the meanwhile, print a dot through
the hyperterminal; just for debugging.
Programming the FPGA, Debugging
and playing around with EDK tools
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:
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.
Ready? well, now compile
the source files to get the executable.elf file. Now, how do we deliver
the executable file (program) to the FPGA? Since we are using external
memory from 0x0000_0000 to 0x0FFF_FFFF and the program is stored begging
at 0x0 (this means that the program is stored in the external memory),
the "Update bitstream" action will not add the executable
file to the bitstream as before (Labs 1 and 2). There are several ways
to deliver the program data to the memory. One way is to generate and
ACE file, copy it to a flash memory and use the ACE system in the ML300
to deliver the program to the PPC405. Another way, is to download the
program to the memory using the XMD. We will use this second way because
we find it more fun and because it's kind of fast if you want to be
changing repeatedly and frequently your program (typical when you are
in the debug process).
So, use Impact as before to program the hardware (to download the bitstream
to the FPGA). The system is now programmed into the FPGA but no program
is in memory, the PPC405 is stopped. Go to XMD and type ppcconnect,
you will get a window similar to the one in figure 17. Now type rrd
to read the values in the registers. What is the value of the PC (program
counter)? Does it agrees with what we said before about the PPC405 having
the boot section starting at 0xFFFF_FFFC?.
Now, type the following:
pwd % to check
in which directory you are at.
cd ppc405/code % to change to the ppc405/code directory
dow executable.elf % now we are downloading the executable
file to the external memory
rst % to reset the system, just in case.
run % to start running the program

Figure 17
Check the hyperterminal window,
you should get a text similar to figure 18.

Figure
18
Nice, our loopback test seems
to be ok. Now let's complicate it a little bit more. Let see if we can
assign a MAC address and an IP address to the Ethernet core and access
it from the outside world in a network. Remember that we are not using
an operating system, but we do need some kind of IP stack to be able
to speak IP protocol in a network environment. The XilNet library provided
with EDK will give us the functions we need.
To specify the compiler that
XilNet will be use, we need to modify manually the system.mss file adding
the following lines:
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = xilnet
PARAMETER LIBRARY_VERSION = 1.00.a
PARAMETER DEVICE_TYPE = Ethernet
PARAMETER emac_type = emac
END
This will generate a /net
directory into the ppc405/include directory where the required libraries
will be stored. To use this library in your application you need to
include the following headers:
#include "xilsock.h"
#include "xilnet_config.h"
More information on this
library can be found at [1] (chapter 25).
This is nice. But we will
not do it this way!! ;-) . Go and copy the xilnet library (from your
EDK installation directory: EDK\sw\edklib\sw_services\xilnet_v1_00_a\src),
both; headers and .C files into a directory we will call xilnet in our
project directory: $project_path/code/include/xilnet for the headers
and $project_path/code/xilnet for the .C files. Why? Because we will
modify these libraries.
Now, get the new code here. The
system.c files has been slightly modify to configure a MAC and an IP
address; also, the loopback test has been removed and the only thing
the main program does is to generate a count in the hyperterminal and
display fancy lights using the gpio leds.
Neither SetupInterruptSystem.c nor TimerCounter have modifications.
The EmacFunctions does have some modifications, namely the SendFrame
and RecvHandle functions. Take a look at the comments on the .C file,
we are basically adding xilnet functions to have access to a TCP/IP
stack.
Get the Xilnet files from here.
We modify some lines (commented out) on the eth.c file (function xilnet_eth_recv_frame)
because it seems to have some trouble. (It basically made our program
hang)
We are now set and ready. Connect the system to an Ethernet hub and
ping it from a nearby workstation (of course, the IP address given to
our system must be valid in the network!!), our system should reply
the ping packet without problems.
As a bonus question: can you think of a way to make our system display
which ip address is pinging it?
If you find any typo/error
in this tutorial or if you have any comment that can help to improve
it, please send us an email!.
References:
[1] Embedded System Tools Guide. Embedded Development Kit (EDK v3.2.2,
May 21, 2003).
[2] Ethernet Media Access Controller (EMAC), Product Specification (DS435,
v1.22)
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.