Sometimes we have an .ngc file from CORE Generator (or some other source) that we would like to bring into EDK as a peripheral. This project is a simple example of integrating a blackbox design into a peripheral generated by the Peripheral Wizard. We will first create a blackbox multiplier using the Xilinx CORE Generator and then we will use the generated .ngc file in our peripheral.

The multiplier will take in two 16 bit unsigned inputs and have a 32 bit unsigned output. A single 32 bit write to the peripheral will contain the two 16 bit inputs, separated by the lower and higher 16 bits. A single 32 bit read from the peripheral will contain the result from the multiplication of the two 16 bit inputs. Instead of registers, we will use a read and write FIFO for the interface with the software application. In this way, the peripheral write FIFO can be loaded with a number of multiplications to perform, and the results can be pushed into the read FIFO for the software application to retrieve at its convenience. Practically, this design does not serve much purpose, but it is a simple demonstration of integrating blackbox designs into peripherals.

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: Integrating a Blackbox into a Peripheral

Create the Basic Project

Follow these steps to create the basic project:

  1. Open XPS and from the dialog box, select “Base System Builder wizard” and OK.
  2. Create a new folder for the project and select it using “Browse”. In “Advanced Options” tick “Use repository paths” and select the “C:\XUPV2P\lib” folder using “Browse”. Click “OK”.
  3. Tick “I would like to create a new design” and click “Next”.
  4. 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. Tick “PowerPC” and click “Next”.
  6. Select all clock frequencies to be 100MHz. Select “No debug”. Click “Next”.
  7. In selecting the Additional IO Interfaces, leave “RS232_Uart_1” ticked and un-tick everything else.

  8. When Adding Internal Peripherals, select 64KB for the “plb_bram_if_cntlr_1” and click “Next”.
  9. Select “RS232_Uart_1” for both STDIN and STDOUT. Un-tick “Memory Test” and leave “Peripheral Test” ticked. Click “Next”.
  10. Click “Generate”.
  11. Click “Finish”.
  12. Tick “Start using Platform Studio” and click “OK”.

Create the Multiplier Peripheral

Follow these steps to create the multiplier peripheral.

  1. Select from the menu “Hardware->Create or Import Peripheral”. Click “Next”.
  2. Select “Create templates for a new peripheral” and click “Next”.
  3. We must now decide where to place the files for the peripheral. They can be placed within this project, or they can be made accessible to other projects. Select “To an XPS project”. Click “Next”.
  4. Type “my_multiplier” for the peripheral name. Click “Next”.
  5. Select “On-chip Peripheral Bus” (OPB) and click “Next”.
  6. The Peripheral Wizard can generate our VHDL template to include many different features. We will only need “FIFO”. Tick that option, un-tick everything else and click “Next”.
  7. For the FIFO Service settings, leave the defaults ticked: Include read FIFO, Include write FIFO, Use packet mode, Use vacancy calculation. Choose 32-bits for the width of the FIFOs, and choose a depth of 512.
  8. On the “IP Interconnect” page we can customize our connection to the OPB but we will leave everything as is for simplicity. Click “Next”.
  9. On the “Peripheral Simulation Support” page, we can specify if we want the wizard to create a simulation platform for our peripheral. Click “Next” without ticking the option to generate.
  10. After the “Peripheral Implementation Support” page, the wizard will generate all the template files for us. Tick “Generate ISE and XST project files” and “Generate template driver files”. Click “Next”.
  11. Click “Finish”. Now our templates are created.

Create the Multiplier with CORE Generator

Follow these steps to generate the Multiplier.

  1. Leaving XPS running and your project open, from the “Start” menu, open Xilinx CORE Generator.
  2. Select “File->New Project”.
  3. Click “Browse” and select an appropriate location for a Coregen project. Within a Coregen project, you can create several cores that don’t necessarily relate to each other. Just select the folder where you normally place your projects, for example “C:\XUPV2P\Projects”. Click “OK”.
  4. CORE Generator will ask you if you want to create the “coregen” folder. Click “OK”.
  5. You will be asked for the specifications of the FPGA you are using. Under the “Part” tab, select these options: Family “Virtex2P”, Device “xc2vp30”, Package “ff896”, Speed grade “-7”. Click “OK”.
  6. When you have created your Coregen project, click on the “View by Function” tab to get a list of cores that you are able to generate.
  7. Open “Math Functions->Multipliers” and double-click on “Multiplier”.
  8. A dialog box should open to allow you to select the features of the Multiplier you want. For “Multiplier Type” select “Parallel Multiplier”. Select “Unsigned” for both port inputs and give them a width of 16 bits.
  9. Click “Finish”. Your Multiplier core will be generated and CORE Generator will display a list of all the generated files. Close this window, and close CORE Generator.

Modify the Peripheral

When we create a peripheral with read and write FIFOs, the Peripheral Wizard generates code in the user_logic.vhd file that loops the data from the write FIFO to the read FIFO. This makes it easy to test for the first time because one can write data to the peripheral and verify that it was received by reading back the same data. In our case, the loop-back design reduces the number of modifications we need to make because we want to do the same thing, only we want to first pass the data through the multiplier before putting it through to the read FIFO. Now we will add code in our peripheral template to instantiate a multiplier core and connect it to the read and write FIFOs.

  1. Select from the menu “File->Open” and look in the project folder.
  2. Open the folders: “pcores\my_multiplier_v1_00_a\hdl\vhdl”. This folder contains two source files that describe our peripheral “my_multiplier.vhd” and “user_logic.vhd”. The first file is the main part of the peripheral and it implements the interface to the OPB. The second file is where we place our custom logic to make the peripheral do what we need it to do. This part is instantiated by the first file.
  3. Open the file “user_logic.vhd”. We will need to modify this source code to instantiate the multiplier and connect it to the read and write FIFOs.
  4. Find the line of code that says “–USER signal declarations added here” and add the following lines of code just below.
component multiplier_v9_0
  port (
    clk: IN std_logic;
    a: IN std_logic_VECTOR(15 downto 0);
    b: IN std_logic_VECTOR(15 downto 0);
    p: OUT std_logic_VECTOR(31 downto 0));
end component;
  1. Find the line of code that says “–USER logic implementation added here” and add the following lines of code just below.
multiplier_0 : multiplier_v9_0
  port map (
    clk => Bus2IP_Clk,
    a => WFIFO2IP_Data(16 to 31),
    b => WFIFO2IP_Data(0 to 15),
    p => IP2RFIFO_Data);
  1. Find the line of code that says “IP2RFIFO_Data <= WFIFO2IP_Data;” and comment it out (or delete it). Now, the read FIFO will be loaded with data from the multiplier.
  2. Save and close the file.

Import the Peripheral

Now we will use the Peripheral Wizard again, but this time using the import function.

  1. Select from the menu “Hardware->Create or Import Peripheral” and click “Next”.
  2. Select “Import existing peripheral” and click “Next”.
  3. Select “To an XPS project”, ensure that the folder chosen is the project folder, and click “Next”.
  4. For the name of the peripheral, type “my_multiplier”. Tick “Use version” and select the same version number that we originally created. Click “Next”. It will ask if we are willing to overwrite the existing peripheral and we should answer “Yes”.
  5. Now we are asked about the files that make up our peripheral. As usual we tick “HDL source files” and in this case, to include our .ngc file, we will also tick “Netlist files”. Now click “Next”.
  6. Select “Use existing Peripheral Analysis Order file (*.pao)” and click “Browse”. From the project folder, go to “pcores\my_multiplier_v1_00_a\data” and select the “my_multiplier_v2_1_0.pao” file. Click “Next”.
  7. On the HDL analysis information page, click “Next”. The wizard will mention if any errors are found in the design.
  8. On the Bus Interfaces page, tick “OPB Slave” and click “Next”.
  9. On the SOPB: Port page, click “Next”.
  10. On the SOPB: Parameter page, click “Next”.
  11. On the “Parameter Attributes” page, click “Next”.
  12. On the “Port Attributes” page, click “Next”.
  13. Now we should arrive at the “Netlist Files” page where we are asked to locate any netlist files or black-box components that are instantiated in our peripheral. Click “Select Files” and navigate your way to the Coregen project folder “coregen” that you created using CORE Generator earlier. You will find a file called “multiplier_v9_0_mult_gen_v9_0_xst_1.ngc”. Rename this file to “multiplier_v9_0.ngc”, then select the file and click “Open”. The file should now be listed on the “Netlist Files” page. Click “Next”.
  14. Click “Finish”.

When you include .ngc files in a peripheral design as we just did, the Peripheral Wizard does some things behind-the-scenes that are important to know. Firstly, it makes a copy of the .ngc file and places it in the “pcores\my_multiplier_v1_00_a\netlist” folder (if that folder doesn’t exist, it creates one). Secondly, it creates a file called “my_multiplier_v2_1_0.bbd” in the “pcores\my_multiplier_v1_00_a\data” folder with the following contents:

## Filename:          C:\XUPV2P\Projects\Multiplier5\pcores-
## Description:       Black Box Definition
## Date:              Mon Feb 11 16:53:42 2008 (by Create a-
nd Import Peripheral Wizard)


Finally, the Peripheral Wizard adds these two lines to the “my_multiplier_v2_1_0.mpd” file in the “pcores\my_multiplier_v1_00_a\data” folder:


The multiplier peripheral should now be accessible through the “IP Catalog->Project Repository” in the XPS interface.

Create an Instance of the Peripheral

Follow these steps to create an instance of the peripheral in the project.

  1. From the “IP Catalog” find the “my_multiplier” IP core in the “Project Repository” group. Right click on the core and select “Add IP”.
  2. From the “System Assembly View” using the “Bus Interface” filter, connect the “my_multiplier_0” to the OPB bus.
  3. Click on the “Addresses” filter. Change the “Size” for “my_multiplier_0” to 64K. Then click “Generate Addresses”.

Now we have an instance of the multiplier peripheral in our project and our hardware design is complete.

Modify the Software Application

Now all we need to do is modify the software application to test our multiplier peripheral.

  1. From the “Applications” tab, open “Sources” within the “Project: TestApp_Peripheral” tree. Open the “TestApp_Peripheral.c” source file.
  2. Replace all the code in this file with the following source and save the file.
#include "xparameters.h"
#include "xbasic_types.h"
#include "xstatus.h"
#include "my_multiplier.h"

Xuint32 *baseaddr_p = (Xuint32 *)XPAR_MY_MULTIPLIER_0_BASEADDR;

int main (void) {
  Xuint32 i;
  Xuint32 temp;
  Xuint32 baseaddr;

  // Clear the screen

  // Check that the peripheral exists
  XASSERT_NONVOID(baseaddr_p != XNULL);
  baseaddr = (Xuint32) baseaddr_p;

  xil_printf("Multiplier Test\n\r");

  // Reset read and write packet FIFOs to initial state

  // Push data to write packet FIFO
  for(i = 1; i <= 4; i++ ){
    temp = (i << 16) + i;
    xil_printf("Wrote: 0x%08x \n\r", temp);
    MY_MULTIPLIER_mWriteToFIFO(baseaddr, temp);

  // pop data out from read packet FIFO
  for(i = 0; i < 4; i++){
    temp = MY_MULTIPLIER_mReadFromFIFO(baseaddr);
    xil_printf("Read:  0x%08x \n\r", temp);

  // Reset the read and write FIFOs

  xil_printf("End of test\n\n\r");

  // Stay in an infinite loop
  1. Save and close the file.

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. From the XPS software, select “Device Configuration->Download Bitstream”.

The Hyperterminal output should look as shown in the image below:

Remember, those numbers are in hexadecimal so 0x10 = 16!

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

For an example of integrating a black-box FIFO into a peripheral, see Creating an Aurora Transceiver. In this tutorial, we create an Aurora peripheral to allow serial communication at 1.5Gbps between two XUPV2P boards connected by a SATA cable.

In the next tutorial, Integrating a VHDL Design into a Peripheral, we show how to integrate a custom VHDL design into the Peripheral Wizard templates.

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