Home | Microprocessor | Labs Index |XUP-UNM V1000 Project|Workshops | Links & Datasheets | General Educational Material


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:

 

    • 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.

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.



alnz | UNM - XUP