Tutorial Overview

In the previous example, we created a project using the BSB and all of the work related to the hardware design was done by the BSB. In this example, we will create the same simple project, but this time we will add the GPIO for the LEDs manually. This way we will learn the process of adding extra peripherals to our design and we will also better understand the hardware design features of XPS.

This tutorial contains screenshots to guide you through the entire implementation process. Click on the images to view a higher resolution.

What you will learn

As in the previous example, we will create the initial project using the BSB and add software applications. In addition, we will step through:

  1. How to add a standard IP peripheral without the BSB
  2. How to add constraints to your design to make links to external hardware (eg. LEDs)

Requirements

Before following this tutorial, you will need to do the following:

  • Buy an ML505/ML506/ML507 or XUPV5 board if you don’t already have one. Xilinx supplies the ML50x boards, but the best deal is the XUPV5 from Digilent. Click the Digilent link for more information.

Create the Basic Project

Follow these steps to create the basic project:

  1. Open XPS. From the dialog box, select “Base System Builder wizard” and OK.
  2. You will be asked to specify which folder to place the project. Click “Browse” and create a new folder for the project. Click “OK”.
     
  3. We are given the choice to create a new project or to create one using the template of another project. Tick “I would like to create a new design” and click “Next”.
  4. On the “Select Board” page, select “Xilinx” as the board vendor. Then select the board you are using (eg. “Virtex 5 ML505 Evaluation Platform”). Select “1” as the board revision. Click “Next”. (Note: If you are using the XUPV5 (ML509) board, you might find that it is not listed. Select “Virtex 5 ML505 Evaluation Platform” instead.)
     
  5. On the “Select Processor” page, we normally have a choice between using the PowerPC “hard” processor, or the Microblaze “soft” processor. Since the Virtex-5 does not contain any PowerPCs, we can only select Microblaze. Click “Next”.
     
  6. On the “Configure Microblaze” page, select the clock frequency to be 125MHz. We will use the RS232 port for debugging rather than the JTAG, so select “No debug”. Click “Next”.
     
  7. In selecting the Additional IO Interfaces, leave “RS232_Uart_1” and “DIP_Switches_8Bit” ticked and un-tick everything else.



     
  8. On the “Add Internal Peripherals” page, click “Next”.
     
  9. On the “Software Setup” page, select “RS232_Uart_1” for both STDIN and STDOUT. The Base System Builder can produce sample software applications to run on the Microblaze and test the memory and peripherals. For this project we will not need them as we will create our own. Un-tick “Memory Test” and “Peripheral Test”. Click “Next”.
     
  10. Click “Generate”.
  11. Click “Finish”.
  12. If you are using the XUPV5 (ML509) board and you selected “Virtex 5 ML505 Evaluation Platform” in step 4 above, you must select the right Virtex-5 version in the project settings. Select “Project->Project Options” and set the Virtex-5 version to “XC5VLX110T”, package “FFG1136” and speed grade “-1”.

Create a Simple Application

Now that the basic project is made, we can create a simple software application to run on the Microblaze to test the DIP switches.

  1. Select the Applications tab. You will see a software application already there called “Default: microblaze_0_bootloop”. The purpose of this application is to occupy the Microblaze in the case that there is no other software application in the design. It simply keeps the Microblaze running in an endless loop.
  2. Double click “Add Software Application”.
     
  3. For the project name type “DIPTest”. For the processor select “microblaze_0”. Click “OK”.
     
  4. From the Applications tab, right click on the software application “Default: microblaze_0_bootloop” and select “Mark to Initialize BRAMs”. The icon will now have a small red cross signifying that it will not run on the Microblaze.
  5. Right click on the software application we just created “Project: DIPTest” and select “Mark to Initialize BRAMs”. The red cross on the icon of our software application should have been removed signifying that it will run on the Microblaze.
     
  6. From the menu select File->New, then select “Text file”. Copy the following code into the new file. Save the file as “DIPTest.c” in a folder called “DIPTest” within the project folder.
#include "xparameters.h"
#include "xbasic_types.h"
#include "xgpio.h"
#include "xstatus.h"

XGpio GpioInput;

int main (void) {

  Xuint32 status;
  Xuint32 DataRead;
  Xuint32 OldData;

  // Initialize the GPIO driver so that it's ready to use,
  status = XGpio_Initialize(&GpioInput,
                         XPAR_DIP_SWITCHES_8BIT_DEVICE_ID);
  if (status != XST_SUCCESS)
    return XST_FAILURE;
  // Set the direction for all signals to be inputs
  XGpio_SetDataDirection(&GpioInput, 1, 0xFFFFFFFF);

  // Initialize the old data register
  OldData = 0xFF;

  while(1){
    // Read the state of the DIP switches
    DataRead = XGpio_DiscreteRead(&GpioInput, 1);

    // Send the data to the UART if the settings change
    if(DataRead != OldData){
      xil_printf("DIP Switch settings: 0x%2X\r\n", DataRead);
      OldData = DataRead;
    }
  }
  return 0;
}
  1. In the “Project:DIPTest” tree, right click on “Sources” and select “Add existing files”. Select the “DIPTest.c” file that we just created and click “OK”.
     
  2. Right click on the “Project: DIPTest” application and select “Generate Linker Script” and click “Generate”.
     
  3. Select “Software->Generate Libraries and BSPs” from the menu.
  4. We can now download our hardware description and software application to the FPGA. Select “Device Configuration->Download bitstream”. When the application is running and Hyperterminal is open, the DIP switch settings should be seen. Change the DIP switches to see the UART message change.

The simple C program that we added to this project simply reads the DIP switch settings and sends a message with that data to the UART.

Add the GPIO for the LEDs

Now we will manually add the second GPIO for the LEDs.

  1. In the IP Catalog tab, open the “General Purpose IO” tree.
  2. Right click on “XPS General Purpose IO” and select “Add IP”.
     
  3. In the “System Assembly View” using the “Bus Interface” filter, you will see the new GPIO instance called “xps_gpio_0”. Click on the instance and rename it to “LEDs_8Bit”. XPS automatically modifies the “system.mss” and “system.mhs” files to include the new IP details.
  4. Connect the instance to the PLB bus by opening the “LEDs_8Bit” tree and selecting “mb_plb” for the “SPLB” bus connection.
     
  5. Double click on the “LEDs_8Bit” instance. We can modify the instance parameters using this dialog box. Type “8” for the “GPIO Data Channel Width” and click OK.
     
  6. Select the “Ports” filter and open the “LEDs_8Bit” tree.
  7. The “GPIO_IO” net should display “No Connection”. Click on “No Connection” and type “fpga_0_LEDs_8Bit_GPIO_IO” to give the net a name.
     
  8. Click the net again to bring down the drop-down menu and select “Make External”. The newly created net should now be in the “External Ports” tree. XPS automatically modifies the “system.mhs” file to include the new external port.
  9. Select the “Addresses” filter.
  10. Click the “LEDs_8Bit” size drop-down menu and select 64K. Then click “Generate Addresses”. XPS automatically reconfigures the memory map and gives the LEDs GPIO a base address and a high address. It also automatically modifies the “system.mhs” file to update the IP address details.

We have now created an instance of the GPIO peripheral in our design.

Modify the Constraints (.UCF) File

The remaining details to include in the hardware description are the external pin connections of the LEDs. This is specified in the “system.ucf” file which is up to the user to modify according to the external hardware configuration (ie. How the FPGA pins are wired up on the ML505 board). Follow these steps to modify the constraints file:

  1. Click the Project tab, open the “Project files” tree and double click the UCF file to open it.
     
  2. Find the comment “## IO Devices constraints” and add the following lines of code below it:
#### Module LEDs_8Bit constraints

Net fpga_0_LEDs_8Bit_GPIO_IO_pin<0> LOC = AE24;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<0> IOSTANDARD=LVCMOS18;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<0> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<0> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<0> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<1> LOC = AD24;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<1> IOSTANDARD=LVCMOS18;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<1> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<1> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<1> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<2> LOC = AD25;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<2> IOSTANDARD=LVCMOS18;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<2> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<2> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<2> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<3> LOC = G16;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<3> IOSTANDARD=LVCMOS25;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<3> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<3> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<3> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<4> LOC = AD26;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<4> IOSTANDARD=LVCMOS18;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<4> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<4> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<4> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<5> LOC = G15;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<5> IOSTANDARD=LVCMOS25;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<5> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<5> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<5> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<6> LOC = L18;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<6> IOSTANDARD=LVCMOS25;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<6> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<6> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<6> DRIVE=2;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<7> LOC = H18;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<7> IOSTANDARD=LVCMOS25;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<7> PULLDOWN;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<7> SLEW=SLOW;
Net fpga_0_LEDs_8Bit_GPIO_IO_pin<7> DRIVE=2;

 

Modify the Software Application

Now the hardware definitions are complete and we must modify the software application to test the hardware.

  1. Create a new software application called “LEDTest” and create a new folder for it called “LEDTest” in the project directory.
  2. From the menu select File->New and copy the code below into the new file. Save the file as “LEDTest.c” in the “LEDTest” folder.
#include "xparameters.h"
#include "xbasic_types.h"
#include "xgpio.h"
#include "xstatus.h"

XGpio GpioOutput;
XGpio GpioInput;

int main (void) {

  Xuint32 status;
  Xuint32 DataRead;
  Xuint32 OldData;

  // Clear the screen
  xil_printf("%c[2J",27);

  // Initialize the GPIO driver so that it's ready to use,
  status = XGpio_Initialize(&GpioOutput,
                                 XPAR_LEDS_8BIT_DEVICE_ID);
  if (status != XST_SUCCESS)
    return XST_FAILURE;
  // Set the direction for all signals to be outputs
  XGpio_SetDataDirection(&GpioOutput, 1, 0x0);

  // Initialize the GPIO driver so that it's ready to use,
  status = XGpio_Initialize(&GpioInput,
                         XPAR_DIP_SWITCHES_8BIT_DEVICE_ID);
  if (status != XST_SUCCESS)
    return XST_FAILURE;
  // Set the direction for all signals to be inputs
  XGpio_SetDataDirection(&GpioInput, 1, 0xFFFFFFFF);

  OldData = 0xFFFFFFFF;
  while(1){
    // Read the state of the DIP switches
    DataRead = XGpio_DiscreteRead(&GpioInput, 1);

    // Send the data to the UART if the settings change
    if(DataRead != OldData){
      xil_printf("DIP Switch settings: 0x%2X\r\n", DataRead);
      // Set the GPIO outputs to the DIP switch values
      XGpio_DiscreteWrite(&GpioOutput, 1, DataRead);
      // Record the DIP switch settings
      OldData = DataRead;
    }
  }
}
  1. Add the “LEDTest.c” file into the “Project: LEDTest” source files by right-clicking on “Source” and selecting “Add Existing Files”.
  2. Select “Mark to Initialize BRAMs” for the “Project: LEDTest” application and deselect it for the “Project: DIPTest” application.
  3. Generate the linker script for the “Project: LEDTest” application.

Download and Test the Project

  1. Open a Hyperterminal window with the required settings. For the correct settings, see Hyperterminal Settings.
  2. Turn on the ML505 board.
  3. We can now download our hardware description and software application to the FPGA. From the XPS software, select “Device Configuration->Download Bitstream”.

The simple C program that we added to this project simply reads the DIP switch settings and sends a message with that data to the UART. It also writes the same values to the LEDs. When the application is running and Hyperterminal is open, the DIP switch settings should be seen on the LEDs and on the Hyperterminal screen. Change the DIP switches to see the message change.

After a few changes in the DIP switches, the Hyperterminal output should look similar to the screen shot below:

The project folder for this tutorial can be downloaded in a compressed ZIP file DIP2LED2-EDK10-1.zip
. Right-click on the link and select “Save Link As”.

In the next tutorial, Create a Peripheral Using the Peripheral Wizard, we develop our own custom peripheral for reading the DIP switches and writing to the LEDs.

Jeff is passionate about FPGAs, SoCs and high-performance computing, and has been writing the FPGA Developer blog since 2008. As the owner of Opsero, he leads a small team of FPGA all-stars providing start-ups and tech companies with FPGA design capability that they can call on when needed.

Facebook Twitter LinkedIn