Manually Add a Peripheral to a Project


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. You can click on the images to view a higher resolution when necessary.

Are you using EDK 10.1?

Try the updated version of this tutorial based on the Virtex-5 FPGA on the ML505 board: Manually Add a Peripheral to a Project

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. In “Advanced Options” tick “Use repository paths” and select the “C:\XUPV2P\lib” folder using “Browse”. 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. Select “XUP Virtex II Pro Development System” as the board name. Select “C” as the board revision. Click “Next”.  
  5. On the “Select Processor” page, we have a choice between using the PowerPC “hard” processor, or the Microblaze “soft” processor. Tick “PowerPC” and click “Next”.  
  6. On the “Configure PowerPC” page, select all clock frequencies to be 100MHz. 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 DIPSWs_4Bit ticked and un-tick everything else.  
  8. On the “Add Internal Peripherals” page, select 64KB for the plb_bram_if_cntlr_1 and 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 PowerPC 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. Once the project is generated, a dialog box will appear to ask what we want to do next. Tick “Start using Platform Studio” and click “OK”.

Create a Simple Application

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

  1. Select the Applications tab. You will see a software application already there called Default: ppc405_0_bootloop. The purpose of this application is to occupy the PowerPC in the case that there is no other software application in the design. It simply keeps the PowerPC running in an endless loop.
  2. Double click “Add Software Application”.  
  3. For the project name type “DIPTest”. For the processor select ppc405_0. Click “OK”.  
  4. From the Applications tab, right click on the software application Default: ppc405_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 PowerPC.
  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 PowerPC.  
  6. From the menu select File->New and 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_DIPSWS_4BIT_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%X\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 opb_gpio 3.01b and select “Add IP”.  
  3. In the “System Assembly View” using the “Bus Interface” filter, you will see the new GPIO instance called opb_gpio_0. Click on the instance and rename it to LEDs_4Bit. XPS automatically modifies the system.mss and system.mhs files to include the new IP details.
  4. Connect the instance to the OPB bus by opening the LEDs_4Bit tree and selecting “opb” for the “SOPB” bus connection.  
  5. Double click on the LEDs_4Bit instance. We can modify the instance parameters using this dialog box. type 4 for the “GPIO Data Bus Width” and click OK.  
  6. Select the “Ports” filter and open the LEDs_4Bit tree.
  7. The GPIO_IO net should display “No Connection”. Click on “No Connection” and type fpga_0_LEDs_4Bit_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_4Bit 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 XUPV2P 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_4Bit constraints

Net fpga_0_LEDs_4Bit_GPIO_IO_pin<0> LOC=AC4;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<0> IOSTANDARD = LVTTL;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<0> SLEW = SLOW;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<0> DRIVE = 12;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<1> LOC=AC3;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<1> IOSTANDARD = LVTTL;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<1> SLEW = SLOW;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<1> DRIVE = 12;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<2> LOC=AA6;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<2> IOSTANDARD = LVTTL;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<2> SLEW = SLOW;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<2> DRIVE = 12;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<3> LOC=AA5;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<3> IOSTANDARD = LVTTL;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<3> SLEW = SLOW;
Net fpga_0_LEDs_4Bit_GPIO_IO_pin<3> DRIVE = 12;

 

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_4BIT_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_DIPSWS_4BIT_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%X\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 XUPV2P 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 EDKTutorial.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.


See also