This IP-Core and software driver enables the PS to control individual input/output signals inside the PL. The core functionality of the AXI GPIO IP-Core is vendor provided:

A software wrapper for the vendor IP-core and driver is implemented to facilitate a consistent interface with other UltraZohm IP-Cores. Only a small subset of the capabilities is implemented in the wrapper to simplify the usage and focus on common use cases.


  • Variable number of I/O between 1 and 32

  • I/O numbering is zero-based (first signal is bit 0 / LSB)

  • All input or all output is recommended for simplicity

  • Output or input configurable on a per-pin basis is supported

  • Only one channel (dual channel mode of the IP-Core is not supported)

  • No interrupt support

  • Static partitioning of pins using the pins gpio_oi_o for outputs and gpio_oi_i for inputs is possible

  • Refer to AXI GPIO product guide if dynamic IO (i.e., changing inputs to outputs and vice versa during run-time) is required (i.e., correct handling of 3-state buffer)

  • The number of pins is configurable

  • If the bitmask functions access more pins than are available, the spare bits are ignored

  • If the pin-wise function accesses more pins than are available, an assertion is triggered



Using the Pin-wise functions requires one AXI4-lite read/write (takes approx. \(1\,\mu s\)) per function call. If multiple pins have to be set, using the bitmask-based functions improves speed significantly (one AXI4-lite read/write for all 32 pins)

typedef struct uz_axi_gpio_t uz_axi_gpio_t

Define to set all I/O of the AXI-GPIO IP-Core to OUTPUT direction.


Define to set all I/O of the AXI-GPIO IP-Core to INPUT direction.

struct uz_axi_gpio_config_t

Config struct for driver instance of AXI GPIO.

Public Members

uint32_t base_address

Base address of the IP-Core instance to which the driver is coupled

uint16_t device_id

Device ID of the IP-Core instance to which the driver is coupled

uint32_t number_of_pins

Number of I/O pins of the AXI GPIO instance between 1-32

uint32_t direction_of_pins

Bitmask for the direction of the GPIO. 1 is input, and 0 is output. Use UZ_AXI_GPIO_DIRECTION_ALL_OUTPUT and UZ_AXI_GPIO_DIRECTION_ALL_INPUT defines.

uz_axi_gpio_t *uz_axi_gpio_init(struct uz_axi_gpio_config_t config)

Initializes an instance of the AXI GPIO driver.

  • config – Config struct for the AXI GPIO


uz_axi_gpio_t* Pointer to an instance of the driver

void uz_axi_gpio_write_pin_zero_based(uz_axi_gpio_t *self, uint32_t pin_number, bool value)

Set the state of the specified pin_number to true (high) or false (low)

  • self – Pointer to driver instance

  • pin_number – Number of the pin to be set (zero-based)

  • value – State of the pin

bool uz_axi_gpio_read_pin_zero_based(uz_axi_gpio_t *self, uint32_t pin_number)

Reads the state of the specified pin_number and returns them with true (high) or false (low)

  • self – Pointer to driver instance

  • pin_number – Number of the pin to be set (zero-based)





void uz_axi_gpio_write_bitmask(uz_axi_gpio_t *self, uint32_t bitmask)

Writes the state of all IOs of the AXI GPIO core using a bitmask.

  • self

  • bitmask – Bitmask to be written indicating true (high) or false (low)

uint32_t uz_axi_gpio_read_bitmask(uz_axi_gpio_t *self)

Reads the state of all IOs of the AXI GPIO core and returns them with true (high) or false (low) as a bitmask.

  • self – Pointer to driver instance




Example using two AXI GPIO in a loopback example, i.e., one AXI GPIO is configured as an output which are fed to the other AXI GPIO instance which is configured as an input. The example loops and flips all bits in each iteration by reading the input AXI GPIO and feeding back the flipped bitmask to the output AXI GPIO. Additionally, the bit 0 is flipped in each iteration.


Fig. 167 Two AXI GPIO instances and one system ILA in loopback configuration.

Listing 182 Code for configuration structs of AXI GPIO. Add to, e.g., top of main.c for testing.
 1 #include "xparameters.h"
 2 // Base addresses and device ID are from xparameters:
 5 //
 6 #include "IP_Cores/uz_axi_gpio/uz_axi_gpio.h"
 8 struct uz_axi_gpio_config_t output_config={
 9             .base_address=XPAR_UZ_USER_AXI_GPIO_0_BASEADDR,
10             .device_id=XPAR_UZ_USER_AXI_GPIO_0_DEVICE_ID,
11             .number_of_pins=16,
12             .direction_of_pins=UZ_AXI_GPIO_DIRECTION_ALL_OUTPUT
13 };
15 struct uz_axi_gpio_config_t input_config={
16             .base_address=XPAR_UZ_USER_AXI_GPIO_1_BASEADDR,
17             .device_id=XPAR_UZ_USER_AXI_GPIO_1_DEVICE_ID,
18             .number_of_pins=32,
19             .direction_of_pins=UZ_AXI_GPIO_DIRECTION_ALL_INPUT
20 };
22 uint32_t output_bitmask=0xaaaa5050U;
Listing 183 Code for init and bit-flipping of AXI GPIO. Add to, e.g., main state machine after initialization but before interrupt initialization.
1 uz_axi_gpio_t* output_gpio=uz_axi_gpio_init(output_config);
2 uz_axi_gpio_t* input_gpio=uz_axi_gpio_init(input_config);
4 while(1){
5     uz_axi_gpio_write_bitmask(output_gpio,~output_bitmask);
6     output_bitmask=uz_axi_gpio_read_bitmask(input_gpio);
7     uz_axi_gpio_write_pin_zero_based(output_gpio, 0U, false);
8     output_bitmask=uz_axi_gpio_read_bitmask(input_gpio);
9 }

Driver and test implementation

The software driver is a wrapper around the vendor-provided driver. Relevant files:

These files are added to be mocked to the test directory vitis/software/Baremetal/test/support. Specifically, xgpio.h is added from the embeddedsw repository and modified. The include #include "xgpio_l.h" inside xgpio.h is deleted to break the dependency of xgpio.h to other vendor provided modules. This works since xgpio.h is never used directly but only mocked.

In addition to the commonly used base address in the software driver that directs the driver to the memory address of the AXI interface of the IP-Core, the Device id is required. The Device id is defined in xparameters.h alongside the base address and numbers the different instances of the AXI GPIO IP-Core.