EDK Tutorial 1 - Buttons and Lights

Objectives

In this tutorial I'll show you how to use the Xilinx EDK to use one of the Virtex-II Pro embedded PowerPC cores to blink some LED's and use the push buttons with interrupts.

Requirements

System requirements:

To complete this tutorial you must have installed the following software on your PC:

  • Linux (Windows and Solaris may also work - not checked)
  • Xilinx EDK 8.1.02i
  • Xilinx ISE 8.1i

Hardware requirements:

In order to download the complete processor system, you must have the following hardware:

<note tip> You may also use another hardware to complete this tutorial as long as the used FPGA has a PPC405 embedded processor core included! </note>

Tutorial Steps

Start the Xilinx Platform Studio (XPS). After startup it will ask if you want to create a new project or open an existing project.

Select the Base System Builder Wizard and press ok.

tutorial1-step1.jpg

Project: select a suitable location for the new project (for example Lab1/system.xmp)

Use Repository Path: Point to the location where you have put the XUPV2 EDK Board Definition File (.xbd), Pcores & Drivers.

Press ok.

tutorial1-step2.jpg

Select I would like to create a new design

Vendor: Xilinx

Board: XUP2V

Press next.

Processor: PowerPC

Press next.

tutorial1-step3.jpg

Processor Clock Frequency: 300 MHz

Press next.

tutorial1-step4.jpg

Deselect all peripherals but not the RS232 UART.

UART Baud: 115200

tutorial1-step5.jpg

Deselect all peripherals but not the LEDs and the push buttons.

Push Buttons: Select use interrupt

Press next.

tutorial1-step6.jpg

Press next.

tutorial1-step7.jpg

The PowerPC core can use directly interfaced on-chip memory (OCM) or memory interfaced with a bus like PLB. In this tutorial we do the later case. We use memory interfaced at the PLB.

The PowerPC requires the interrupt table to be stored at a memory address which is aligned at 64KB.

Change the memory size to 64KB.

Press next.

tutorial1-step8.jpg

Deselect Memory Test

Press next.

tutorial1-step9.jpg

Press next.

tutorial1-step10.jpg

The summary shows the memory regions of the selected peripherals.

Press next and press finish in the next wizard step.

tutorial1-step11.jpg

XPS Main Window

The main window of XPS will be populated with your just created project. At the left side of the XPS is the Project tab:

  • MHS defines:
    • the used microprocessor (MicroBlaze, PowerPC)
    • peripherals and associated address space
    • used buses
    • complete connectivity of the whole system
  • MSS defines the compiler settings and the OS & library settings (may be changed under Software → Software Platform Settings):
    • UCF:
      Constraints like signal and port assignments (for example the push buttons), voltage levels, timings, and much more…
    • iMPACT Command File:
      This file will be run by iMPACT to download the bitstream to the XUP2V Board.
    • Implementations Options File:
      Defines the design flow for your project.

Lets have a look at the Applications tab:

  • Project Testapp_Peripheral is the current active project (denoted by the bold font) and will be placed into the device BRAM (program will be executed after device startup) which you can see at the icon besides the project. Theres no red cross at the upper left corner.

At the IP Catalog tab are all available IPs you may use in your project's. To use them just double-click the entry.

At the right side of the XPS main window you see the available components and their connection with the various buses.

Build and download the Testapp_Peripheral project

Lets build the Testapp_Peripheral. Click Device Configuration → Update bitstream.

The IPs will be synthesized and the projects active program will be compiled. Afterwards the compiled project will be placed into the bitstream ready for downloading:

  1. Power on your board and check the cable connection.
  2. Connect a serial cable to the XUP2V Board.
  3. Start minicom in a console.
  4. Press ctrl+a followed by an o.
  5. Select serial port setup.
  6. Select E.
  7. Set the speed to I: 115200, parity to L: None, Data to V:8, stopbits to W: 1.
  8. Press enter to accept the 115200 Baud 8N1 setting.
  9. You may save these settings to a file with Save setup as…

Check at the XUP2V Board that the dip switch SW9 is set to JTAG.

Click Device Configuration → Download bitstream to place the bitstream into the FPGA.

You should see the four LEDs going off and on. The TestApp_Peripheral output at minicom should be:

-- Entering main() --
Running GpioOutputExample() for LEDs_4Bit...
GpioOutputExample PASSED.
Running GpioInputExample() for PushButtons_5Bit...
GpioInputExample PASSED. Read data:0x1F
Runnning IntcSelfTestExample() for opb_intc_0...
IntcSelfTestExample PASSED
-- Exiting main() --

Quiet cool, eh?

Build your own application

Lets start an own sample application. The application will print the current count of push button presses over the UART and light the LED's with the associated pressed button.

Select the Applications tab in the XPS mainwindow at the left side. Select Add Software Application Project.

tutorial1-step12.jpg

Enter a suitable application name (like ButtonsAndLights). Press next.

  1. Right click at Project: TestApp_Peripheral and deselect Mark to initialize BRAMs.
  2. Right click at Project: ButtonsAndLights and select Mark to initialize BRAMs.
  3. Expand the Project: ButtonsAndLights.
  4. Right click Sources and select Add Existing files ….
  5. Download the file buttonsandlights.c and select it in the file dialog.

Click Device Configuration → Download bitstream to recreate the bitstream with this new project and place the bitstream into the FPGA.

At the minicom you see the push buttons pressed count. If you press a button an associated LED will light on. The center button drives all LEDs.

Lets have a look at the source code:

#include "xparameters.h"
#include "stdio.h"
#include "xbasic_types.h"
#include "xintc.h"
#include "xgpio.h"
#include "xexception_l.h"
 
#define BTN_RIGHT 0x0001
#define BTN_LEFT 0x0002
#define BTN_DOWN 0x0004
#define BTN_UP 0x0008
#define BTN_CENTER 0x0010
 
static volatile unsigned int button_count = 0;
static XIntc InterruptController;
static XGpio Buttons, Lights;

The function button_pressed is an interrupt service routine. If the user push a button the interrupt service routine will be invoked. We count the number of button presses (not debounced). We read the pressed button's into the pressed variable and decode the button states. The single LED's will be put on or off.

void button_pressed(void *callback) {
        unsigned int *count = (unsigned int *)callback;
        Xuint32 pressed, light = 0;
 
        XGpio_InterruptClear(&Buttons, XGPIO_IR_CH1_MASK);
 
        if (count != NULL)
                (*count)++;
 
        pressed = XGpio_DiscreteRead(&Buttons, 1);
        if (~pressed & BTN_LEFT)
                light |= 1;
        if (~pressed & BTN_RIGHT)
                light |= 2;
        if (~pressed & BTN_DOWN)
                light |= 4;
        if (~pressed & BTN_UP)
                light |= 8;
        if (~pressed & BTN_CENTER)
                light |= 0x0F;
 
        XGpio_DiscreteWrite(&Lights, 1, ~light);
 
}

In the main function the ISR for the button's interrupt is registered. Afterwards the global Exception (Interrupt) handling of the PPC will be activated.

int main (void) {
 
        print("-- Entering ButtonsAndLights main() v1.9 --\r\n");
        XExc_Init();
        XExc_RegisterHandler(XEXC_ID_NON_CRITICAL_INT, (XExceptionHandler)XIntc_DeviceInterruptHandler, (void *) XPAR_OPB_INTC_0_DEVICE_ID);
        XIntc_Initialize(&InterruptController, XPAR_OPB_INTC_0_DEVICE_ID);
        XIntc_Start(&InterruptController, XIN_REAL_MODE);
 
        XIntc_Connect(&InterruptController, XPAR_OPB_INTC_0_PUSHBUTTONS_5BIT_IP2INTC_IRPT_INTR, 
                                (XInterruptHandler) button_pressed, (void*) &button_count);
        XIntc_Enable(&InterruptController, XPAR_OPB_INTC_0_PUSHBUTTONS_5BIT_IP2INTC_IRPT_INTR);
 
 
        XExc_mEnableExceptions(XEXC_NON_CRITICAL);
 
        if (XGpio_Initialize(&Buttons, XPAR_PUSHBUTTONS_5BIT_DEVICE_ID) != XST_SUCCESS) {
                printf("Failed to initalize the buttons.\r\n");
        } else {
                XGpio_SetDataDirection(&Buttons, 1, 0xFFFFFFFF);
                XGpio_InterruptClear(&Buttons, XGPIO_IR_CH1_MASK);
                XGpio_InterruptEnable(&Buttons, XGPIO_IR_CH1_MASK);
                XGpio_InterruptGlobalEnable(&Buttons); 
        }
 
        if (XGpio_Initialize(&Lights, XPAR_LEDS_4BIT_DEVICE_ID) != XST_SUCCESS) {
                printf("Failed to initalize the LEDs.\r\n");
        } else {
                XGpio_SetDataDirection(&Lights, 1, 0x00000000);
                /* Switch all leds off */
                XGpio_DiscreteWrite(&Lights, 1, 0x0F);
        }
 
        XExc_mEnableExceptions(XEXC_NON_CRITICAL);
 
        printf("Started up.\r\n");
 
 
        /* Never exit tho main function */
        while(1) {
                printf("=> Button pressed %u times.\r", button_count);
        }
 
        print("-- Exiting main() --\r\n");
 
        return 0;
}

I hope you had fun with this short tutorial!

 
fpga/edk_tutorial_1.txt · Last modified: 2009/09/16 19:51 (external edit)
Recent changes RSS feed Creative Commons License Valid XHTML 1.0 Valid CSS Driven by DokuWiki
© 2006 - 2010 H. Gregor Molter - SecretLab.de