UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 60837

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

Description

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.

Solution

Step 1: Create the HW platform.

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

AR60837_mb_config.png


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

AR60837_mb_system.png

 

Step 2: Create the Custom IP.

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

AR60837_CIP.png

 

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

AR60837_CIP_with_interrupt.png




Then add the Interrupt support:

AR60837_add_interrupt.png

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:

AR60837_add_ip.png

 

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:

AR60873_block_design.png





 

Step 4: Investigate the IP.

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

AR60837_edit_ip.png



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

AR60837_source_view.png

 

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

This can be seen on the lines below:

AR60837_counter.png



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:

AR60837_hdl_mod.png




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.

AR60837_address_decode.png


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

AR60837_review_and_package.png

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:
 
AR60837_address_decode.png


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, 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 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:

AR60837_repository.png

 

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

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

AR60683_bsp.png

 

Select Finish.

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

AR60837_driver_detect.png

 

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:

AR60837_interrupt_application.png

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:

AR60837_new_source.png



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 ACK the interrupt using the API created above also.

#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()
{
   count++;
   xil_printf("interrupt %d \n\r", count);
   MYIP_WITH_INTERRUPT_ACK(MYIP_WITH_INTERRUPT);
}
int main()
{
  microblaze_enable_interrupts();
 
   XIntc_RegisterHandler(XPAR_INTC_SINGLE_BASEADDR,XPAR_AXI_INTC_0_MYIP_WITH_INTERRUPT_0_IRQ_INTR,
   (XInterruptHandler)handler, XPAR_INTC_SINGLE_BASEADDR);
 
   XIntc_MasterEnable(XPAR_INTC_SINGLE_BASEADDR);
 
   XIntc_EnableIntr(XPAR_INTC_SINGLE_BASEADDR, XPAR_MYIP_WITH_INTERRUPT_0_IRQ_MASK);
 
   MYIP_WITH_INTERRUPT_EnableInterrupt(MYIP_WITH_INTERRUPT);
 
   xil_printf("Wait for Interrupts.... \n\r");
   while(count < 10);
}
 
AR# 60837
Date Created 05/27/2014
Last Updated 06/24/2014
Status Active
Type General Article
Tools
  • Vivado Design Suite - 2014.1