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

 


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.


 


alnz | UNM - XUP