AR# 60837

Vivado CIP - Create or Import Peripheral wizard demo using AXI IP with Interrupt


This Answer Record demonstrates the flow to add a Custom AXI IP with interrupt support.

It also covers how to modify the generated HDL code, and how to create a useable device driver API.


Step 1: Create the Hardware platform.

In this example the KC705 is used, and a simple MicroBlaze system was created as shown below:


Use the Run Connection Automation to connect the clocks, and reset:



Step 2: Create the Custom IP.

To create the IP, click Tools > Create and Package IP.., and select Create a new AXI4 peripheral:

Name the IP. This will be the name seen in the IP catalog:

Then add the Interrupt support:


Click View Summary and Finish to create the IP.

This will create all of the HDL code, and an example driver that will be used later in this demo.


Step 3: Add the IP to the HW system

Use the Add IP icon in the block design to add the new IP:



Add the IP (and because this is a MicroBlaze, add an Interrupt controller IP) and a UART lite. 

Use the Run Connection Automation to connect the system:


Step 4: Investigate the IP.

To investigate, simulate, or modify the new IP, right click on the IP and select Edit in IP Packager:

This will open a Vivado project and all of the IP source files will be added. Because we added interrupt support, we can see the S_AXI_INTR

In this demo, we will be concentrating on the interrupt section. In the HDL code, the interrupt is simulated by a counter. 

This can be seen on the lines below:

Here, the interrupt will occur if the 16 bit counter counts to 10, then stops. 

The counter is clocked using the ACLK that drives the AXI, so if this is 100Mhz, this interrupt will occur very quickly. 

This can be adjusted to a bigger timer value and to generate an interrupt on roll-over:

Save any changes. To verify, we can synthesize the design.

Note: Before re-packaging the IP, open the S_AXI_INTR and see the AXI address decoding information as in the below example. 

This will be used to create a custom driver.


Next Review and Package the IP, by clicking on the Re-Package Button


In the project, Reset Output Products, and Re-Generate Output Products, and Generate the Top level HDL wrapper.

Step 5: Implement the Design and Export to SDK

Step 6: Modify the driver to add interrupt API.
The driver that is delivered with the CIP does not have any interrupt API to enable or ACK the interrupt.

However, this can be easily added using the address decoding information that we obtained from the S_AXI_INTR HDL code:

Here, we can see that the following:
  • Global Interrupt enable:  3'h0, which is 000 on axi_araddr[4:2], and 0x00000000 on the 32 bit AXI interface
  • Interrupt enable:               3'h1, which is 001 on axi_araddr[4:2], and 0x00000004 on the 32 bit AXI interface
  • Interrupt Stat:                     3'h2, which is 010 on axi_araddr[4:2], and 0x00000008 on the 32 bit AXI interface
  • Interrupt ACK:                    3'h3, which is 011 on axi_araddr[4:2], and 0x0000000C on the 32 bit AXI interface
  • Interrupt Pending:             3'h4, which is 100 on axi_araddr[4:2], and 0x00000010 on the 32 bit AXI interface
Using this information we can create our own API to enable and ACK the custom IP.
To add this API, open the <IP_name>.h file in the driver folder of your custom IP and add the function calls near the end of the file (before the #endif):

void MYIP_WITH_INTERRUPT_EnableInterrupt(void * baseaddr_p);
void MYIP_WITH_INTERRUPT_ACK(void * baseaddr_p);

Next, open the <IP_name>.c and create the API to enable and ACK all interrupts on the custom IP:
void MYIP_WITH_INTERRUPT_EnableInterrupt(void * baseaddr_p)
  Xuint32 baseaddr;
  baseaddr = (Xuint32) baseaddr_p;
   * Enable all interrupt source from user logic.
  MYIP_WITH_INTERRUPT_mWriteReg(baseaddr, 0x4, 0x1);
   * Set global interrupt enable.
  MYIP_WITH_INTERRUPT_mWriteReg(baseaddr, 0x0, 0x1);
void MYIP_WITH_INTERRUPT_ACK(void * baseaddr_p)
  Xuint32 baseaddr;
  baseaddr = (Xuint32) baseaddr_p;
  * ACK interrupts on MYIP_WITH_INTERRUPTS.
  MYIP_WITH_INTERRUPT_mWriteReg(baseaddr, 0xc, 0x1); 

Step 7: Build the BSP using a custom driver

Next, we add the custom driver. To do this, go to Xilinx Tools > Repositories, and in the Local Repositories, point to the folder containing the drivers folder:

Click Rescan Repositories, and Apply, and Click OK to exit.

Next, build the BSP, File > New > Board Support Package

Select Finish.

Verify that the driver is detected. This can be seen in the drivers > microblaze_0 tab:

Note: if the custom driver is not seen, ensure that the path is correct in the repository

Step 8: Create the Application

Now that the API has been created, and the driver is added, we can create our simple application. 

To add the application, go to File > New > Application Project:


Use the existing BSP. Select Next, and choose an Empty Application and Finish.

Next, right click on the src folder in the project explorer hierarchy and select New > Source File:

Name your source file <file name>.c and OK. Below is a simple application example that can be used to test the interrupt on the custom IP.

This registers the interrupt, enables the interrupts on the interrupt controller, and uses the API created above to enable interrupts on the custom IP. 

These is a simple handler, that will also ACK the interrupt using the API created above:

#include "myip_with_interrupt.h"
#include "stdio.h"
#include "xil_io.h"
#include "xintc_l.h"
#include "xparameters.h"
#define MYIP_WITH_INTERRUPT 0x44a10000
volatile int count = 0;
void handler()
   xil_printf("interrupt %d \n\r", count);
int main()
   (XInterruptHandler)handler, XPAR_INTC_SINGLE_BASEADDR);
   xil_printf("Wait for Interrupts.... \n\r");
   while(count < 10);
AR# 60837
Date 08/31/2017
Status Active
Type General Article