Abstract: The tutorial provides a brief overview of available input/output peripherals (IOPs) and their relation with multiplexed input/output (MIO) and extended MIO (EMIO) in Zynq 7000. After that, a comprehensive detail of general purpose input/output (GPIO), which is one of the available IOPs in Zynq 7000, and its programming via MIO and EMIO is explained. Lastly, the GPIOs are implemented by making use of Vivado and Zedboard as a software and hardware platform respectively.
To facilitate the learners, this tutorial is sub-divided into three parts:
- A theoretical overview of IOPs and detailed version of GPIO with their relations with MIO/EMIO,
- Implementation of GPIO via MIO on Zedboard, and Vivado,
- Implementation of GPIO via EMIO on Zedboard and Vivado.
Part 1: Implementation of GPIO via MIO and EMIO in All Programmable SoC (AP SoC) Zynq 7000
The IOPs (e.g., USB, UART, I2C and so on) can interact with Zynq 7000 SoC via either MIOs or EMIOs. The processor system (PS) part of Zynq 7000 has many built-in IOP controller with each controller provides its own driver available in the form of C code, enabling the users to integrate the external IOPs with PS without any extra overhead. In the following tutorials, we will be using these drivers to configure external IOPs. It is important to note that these controller are only available in PS part, so IOPs can only communicate with this part of Zynq 7000 SoC. If someone is interested in using IOPs in programmable logic (PL) part of Zynq 7000 SoC, he shall design the pertaining accelerator or can used Xilinx accelerator in PL. PS of Zynq directly can interact with the external IOPs via MIO. The MIO pins however are limited in number. Xilinx also provides its solution by introducing EMIO pins. So, EMIO can be used to exploit IOP controllers available in PS to make direct communication between PS and PL or to interact with the external IOPs via PL in case if all the MIO pins are occupied. The available IOP controllers in PS of Zynq are shown in the following figure.
GPIO: General purpose input/output (GPIO) ,shown in red dotted rectangle in the above figure, is one of the IOPs supported by Zynq 7000. According to Wikipedia “GPIO is an uncommitted digital signal pin on an integrated circuit or electronic circuit board whose behavior—including whether it acts an input or output—is controllable by the user at run time. GPIOs have no predefined purpose and are unused by default”. It is cleared from the definition of GPIOs that their functions and IO directions are fully configurable. Their application includes but not limited to monitor and control the other circuitry. They can be used to implement low data rate communication standards (e.g., 12C, UART, SPI, etc.). In Zynq 7000, PS can use GPIO to monitor or control the signals in PL and in external world via EMIO and MIO respectively.
The GPIO peripheral provides a software with observation and control of up to 54 device pins via the MIO module. It also provides access to 64 inputs from the Programmable Logic (PL) and 128 outputs to the PL through the EMIO interface. The GPIO is organized into four banks of registers that group related interface signals.
Each GPIO can be independently and dynamically programmed as input, output, or interrupt sensing. Software can read all GPIO values within a bank using a single load instruction, or write data to one or more GPIOs (within a range of GPIOs) using a single store instruction. The GPIO control and status registers are memory mapped at base address 0xE000_A000 [ug585].
- Bank0: 32-bit bank controlling MIO pins[31:0]
- Bank1: 22-bit bank controlling MIO pins[53:32]
- Bank2: 32-bit bank controlling EMIO signals[31:0]
- Bank3: 32-bit bank controlling EMIO signals[63:32]
Functional Description of GPIO banks: All the registers used to configure GPIO bank(s) (bank0 and bank1) are shown in the following figure and the functions of the registers are summarized as follows:
- DATA_RO enables software to observe the value on the device pin,
- DATA allows all 32 bits data to write at one time,
- MASK_DATA_LSW and MASK_DATA_MSW enable any combination of up to 16 LSB or MSB bits to write respectively,
- DIRM control the direction of the respective bank (e.g., when DIRM[x]==0, the output driver is disabled), OEN enables the outputs ( e.g., when OEN[x]==0, the output driver is disabled),
- INT_MASK (read only) shows which bits are currently masked or enabled,
- 1 to any bit of INT_EN register enables/unmasks that signal for interrupts,
- 1 to any bit of INT_DIS register masks that signal for interrupts,
- INT_STAT register shows if an interrupt event has occurred or not. Writing a 1 to a bit in this register clears the interrupt status for that bit.
- INT_TYPE register controls whether the interrupt is edge sensitive or level sensitive
- POLARITY register controls whether the interrupt is active-Low or active High (or falling-edge sensitive or rising-edge sensitive).
- If INT_TYPE is set to edge sensitive, then INT_ON_ANY register enables an interrupt event on both rising and falling edges. This register is ignored if INT_TYPE is set to level sensitive.