Zmod Base Library User Guide

1. Overview

Digilent provides a set of libraries supporting Zmod modules on both Linux and baremetal (standalone) platforms.
The Zmod Base Library implements functionality common to all Zmods. For each Zmod, separate libraries are implemented, based on Zmod Base Library.
This document describes the Zmod Base Library structure and also addresses issues common to all Zmods.
These instructions / demos are provided for the Zmods attached to an Eclypse board, still Zmods can be attached to any Zynq board having a SYZYGY connector.

The following block diagram shows the overall structure of Zmod Libraries.

The Zmod libraries run in the Zynq PS (processing system).
The Zmod is physically attached on the SYZYGY connector of the development board (Eclypse).
In the Zynq PL (FPGA) there is an IP core specific to each Zmod. This IP core can be accessed from the Zynq PS through its registers. The IP core is able to communicate with the memory over the AXI DMA data bus. Each Zmod has associated one particular instance of AXI DMA IP core.
Communication over the AXI DMA is mastered by the Zmod libraries.
The Zmod libraries contain two layers. The base layer is called Zmod Base Library and is described under this page. It mainly deals with the functionality common to all Zmods and provides the platform abstraction layer, ensuring consistent implementation for the two supported platforms (Linux, Baremetal), hiding under it all the platform related functionality.
On the higher level there is a Zmod specific library. It is based on the Zmod Base library and implements only the Zmod specific functionality and definitions.
The Zmod Libraries ensure the following objectives are met:

  • Provide a consistent API to:
    • different Zmods
    • different software platforms: Linux and Baremetal, by implementing a platform abstraction layer at Zmod Base Library level.
  • Implement at Zmod Base Library level all the functionality needed by Zmods:
    • AXI DMA
    • Flash
    • Communication with IP cores specific to each particular Zmod

The above mentioned topics are detailed and described in the next section Implementation Details.
The Zmod Base Library implementation consists of a C++ class called ZMOD Class which is the base class for inherited classes used for each particular Zmod.
Also, the Zmod Base Library implementation contains two separate folders: Linux and Baremetal.

Consult the table in the right in order to proceed to the Environment Setup section.
Download the git files indicated below in order to access the Projects Files and Demos for the two Zmods: ADC1410 and DAC1411, together with the Base library files.

Download source files:

Library and Demo files ZmodADC1410 Demo Files DAC1411 Demo Files
Base Zmod Library ZMODADC1410 Demo ZMODDAC1411 Demo

Clone the git repository containing the libraries and demos using the below command:

git clone --recursive https://github.com/Digilent/Eclypse-Z7-SW.git -b zmod_adc_dac/master

Similar command for the Zmod specific demos.

For details on the Zmod specific libraries see the following documents:

For details on the Zmod API, see the following document:


2. Implementation Details

2.1. Platform Abstraction Layer

The ZMOD Class calls Zmod IP Cores related functionality, AXI DMA related functionality and Flash related functionality which are implemented differently on Linux and Baremetal. The platform abstraction layer provides a common API for both platforms.
The Zmod folder contains these header files: reg.h, dma.h and flash.h which contain declarations for the platform dependent functions corresponding to IP Core registers, AXI DMA and Flash. The functions prototypes are common for both platforms while their implementation resides in the Baremetal and Linux folders.
The project level definition LINUX_APP ensures each function is implemented exactly once (all the Linux platform projects must define LINUX_APP).
Under the Linux and Baremetal folders there is a separate folder for each interface: reg, dma, flash, and intc (for Baremetal only).
For more details, read the functionality described below in this section.

The IP core related functionality provides access to the registers of the IP core corresponding to a particular Zmod.
This functionality allows:

  • Initialization/de-initialization of the IP core
  • Reading and writing Zmod registers.
  • Initialization and handling of the interrupts addressed by Zmod interrupt controller (only for Baremetal platform)

This functionality is platform dependent, as explained in the Platform Abstraction Layer.
The prototype of these functions is placed in the Zmod/reg.h file and is common to both Linux and Baremetal platforms. The implementation of these functions is in Zmod/linux/reg.c and Zmod/baremetal/reg.c respectively, exclusively depending on the project level definition LINUX_APP.

The Linux implementation uses UIO mapping to access the IP registers.

The Baremetal implementation uses Xil_Out32 and Xil_In32 to access the IP registers.
The Baremetal uses the Xilinx interrupt controller XIntc. The interrupt related implementation is implemented in Zmod/intc folder.

The initialization function takes the IP base address and the IP interrupt number as parameters.

On Linux, the IP base address is stored in /sys/class/uio/uio<uio number>/maps/map<map number>/addr file. The <uio number> and <map number> are usually '0'. For Linux the IP core interrupt is not implemented, so -1 is used.

For baremetal, the IP base address and the IP interrupt number are specified in xparameters.h (in the bsp include files). For example, XPAR_AXI_ZMODADC1410_0_S00_AXI_BASEADDR and XPAR_FABRIC_AXI_ZMODADC1410_0_IRQ_OUT_INTR.

The IP core related functionality is mainly called from IP Cores Register Access Functions of ZMOD Class.


The AXI DMA related functionality provides the ability to transfer data over AXI DMA.
The functionality allows:

  • Initialization/de-initialization of the AXI DMA module.
  • To allocate/free the buffer used for data transfer.
  • To initiate one way AXI DMA transfers.
  • To inform when a transfer is complete.

This functionality is platform dependent, as explained in the Platform Abstraction Layer.
The prototype of these functions is placed in the Zmod/dma.h file and is common to both Linux and baremetal platforms. The implementation of these functions is in Zmod/linux/dma.c and Zmod/baremetal/dma.c respectively, exclusively depending on the project level definition LINUX_APP.

The Linux implementation uses libaxidma devices for each AXIDMA instance.

The Baremetal implementation uses the XAxiDma driver for each AXIDMA instance.

The initialization function takes the AXI DMA base address and the AXI DMA interrupt number as parameters.

For Linux, the AXI DMA base address can be found in the /sys/class/uio/uio<uio number>/maps/map<map number>/addr file. The <uio number> and <map number> are usually '0'.
The AXI DMA interrupt is implemented inside libaxidma, so -1 value can be provided for the AXI DMA interrupt number.

For Baremetal, the AXI DMA base address and the AXI DMA interrupt number are specified in xparameters.h file (in the bsp include files). For example XPAR_AXI_DMA_0_BASEADDR and XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR.

The Zmod implementation uses one way AXI DMA transfers (S2MM or MM2S), so the transfer direction is set in the initialization function.
The AXI DMA related functionality is mainly called from AXI DMA Transfer Functions of ZMOD Class.


The Flash related functionality provides access to the persistent memory (flash) placed on each Zmod. These functions handle calibration values.
Their functionality allows:

  • Flash module initialization/de-initialization
  • To read/write blocks of data from/to a specified address in flash.

This functionality is platform dependent, as explained in the Platform Abstraction Layer.
The prototype of these functions is placed in the Zmod/flash.h file and is common to both Linux and Baremetal platforms. The implementation of these functions is in the Zmod/linux/flash.c and Zmod/baremetal/flash.c respectively, exclusively depending on the project level definition LINUX_APP.

The Linux implementation uses /dev/i2c-0 device.

The Baremetal implementation uses XIicPs driver.

The initialization function takes the Flash base address as a parameter.

For Linux, the Flash base address can be found in the /sys/bus/i2c/devices/i2c-<i2c number>/name file by parsing its content for the address. The <i2c number> is usually '0'. For example, the content of /sys/bus/i2c/devices/i2c-0/name is “Cadence I2C at e0005000”, e0005000 being the needed Flash base address.

For Baremetal Flash base address is specified in xparameters.h (in the bsp include files). For example XPAR_PS7_I2C_1_BASEADDR.

The initialization function also requires the address of slave I2C device corresponding to the Zmod connector.
For Eclypse, the addresses of slave I2C devices are: 0x30 (corresponding to ZMOD A connector) and 0x31 (corresponding to ZMOD B connector). The Flash related functionality is mainly called from Calibrations Functions of ZMOD Class.


2.2 ZMOD Class

This is the base class for individual Zmod classes (for example ZMODADC1410 class or ZMODDAC1411 class). It implements the functionality common to all Zmods and all the functionality needed to access hardware resources, abstracting these details from the derived classes. It implements the following function members:

2.2.1. ZMOD Class Constructor / Destructor

The ZMOD class constructor initializes the hardware interfaces. It takes the following parameters:

The ZMOD class destructor calls the destroy functions for the hardware interfaces, also freeing the dynamically allocated calibration data.


2.2.2. IP Cores Register Access Functions of ZMOD Class

The ZMOD class provides initialization of the IP core related module, and access to IP core registers.
To access IP core related functionality, the ZMOD class calls functions from the platform abstraction layer (see IP Core Related Functionality).
Thus read/write register and read/write register field functions are provided, both in signed and unsigned versions: readReg, writeReg, readRegFld, writeRegFld, readSignedRegFld and writeSignedRegFld.
A register's bit field designates a number of contiguous bits inside an IP core register and is defined as a triplet of IP core register address, start bit, and end bit. Some register's bit fields can be common to all ZMODS (defined in the base class header file zmod.h) or specific to an individual Zmod (defined in the specific library header file, ZMODADC1410/zmodadc1410.h for example). The register's bit fields definitions can be found on each specific Zmod library user guide.
The ZMOD class also provides functions that allow sending and receiving commands to / from the chip on the specific ZMOD (for example sending commands to the ADC device on the ZmodADC1410 or to the DAC device on the ZmodDAC1411): sendCommand and receiveCommand functions.


2.2.3. AXI DMA Transfer Functions of ZMOD Class

To access AXI DMA related functionality, the ZMOD class calls functions from the platform abstraction layer (see AXI DMA Related Functionality).
The ZMOD class provides initialization and one way AXI DMA transfer functions.
Also, ZMOD class provides data buffer allocation / de-allocation functions: allocDMABuffer and freeDMABuffer.
The setTransferSize function allows setting the AXI DMA transfer size (in bytes).
The startDMATransfer function starts an uni-directional (one way) AXI DMA transfer.
The isDMATransferComplete function informs when a transfer is complete.


2.2.4. Calibration Functions of ZMOD Class

To access the flash memory functionality, ZMOD class calls functions from the platform abstraction layer (see Flash Related Functionality).
The ZMOD class provides flash initialization and flash transfer functions.
These functions are used to manage calibration values specific to each Zmod. They are computed during the Zmod manufacturing process and are stored in the Zmod persistent memory (flash) at specific addresses.
The meaning of the content stored in flash memory is specific to each Zmod type, still there are common features:

  • One set of calibration values is stored in the flash memory as an array of bytes, the first being a Zmod specific ID and the last being a checksum of previous bytes.
  • Each Zmod stores in its flash memory two sets of calibration values: one set is called user calibration and can be modified by user, the other is called factory calibration and can never be modified.
  • At manufacturing process each Zmod is calibrated. The values are saved as factory calibration and are also copied under user calibration.
  • The user calibration values are used (by the Zmod libraries) to calibrate the Zmod.
  • The user can decide at any time to restore the factory calibration by copying the values from factory calibration to the user calibration area.

The initCalib function initializes the calibration related data. It is normally called from the classes derived from ZMOD class, providing as parameter the Zmod ID and the length of the calibration area. The function allocates an array of bytes that will be used as calibration image. The classes derived from ZMOD class will interpret this image as specific calibration structure.
The readUserCalib function reads from flash an array of bytes from the flash address corresponding to the user calibration. The length of this array is the length of the calibration area. It returns specific errors if the first byte is different than the expected Zmod ID and if the last byte does not match the checksum of the previous bytes.
The restoreFactoryCalib function reads an array of bytes from the flash address corresponding to the factory calibration and writes the array of bytes to the flash address corresponding to the user calibration.
The writeUserCalib function writes an array of bytes to the flash address corresponding to the user calibration. Prior to writing, it fills the first byte with the Zmod ID and it computes the checksum on the last byte of the array of bytes to be written.


3. Library Usage

3.1. Delivery Structure

The base library and demos are delivered as a 2019.1 Xilinx Vivado SDK workspace and the structure is presented below:

    • Folder ZmodADC1410_Demo_Linux contains the Linux demo project. Under src folder there are the following linked folders:
      • Folder zmodlib links to WORKSPACE_LOC\zmodlib.
        The structure of zmodlib is detailed in the below paragraph.
      • A main file implementing the Linux demo
    • Folder ZmodADC1410_Demo_Baremetal contains the Baremetal project. Under src folder there are the following linked folders:
      • Folder zmodlib links to WORKSPACE_LOC\zmodlib.
        The structure of zmodlib is detailed in the below paragraph.
      • A main file, specific to the baremetal app
    • One folder ZmodADC1410_Demo_Baremetal_bsp corresponding to the Baremetal project bsp.
    • Folder ZmodDAC1411_Demo_Linux contains the Linux demo project. Under src folder there are the following linked folders:
      • Folder zmodlib links to WORKSPACE_LOC\zmodlib.
        The structure of zmodlib is detailed in the below paragraph.
      • A main file implementing the Linux demo
    • Folder ZmodDAC1411_Demo_Baremetal contains the Baremetal project. Under src folder there are the following linked folders:
      • Folder zmodlib links to WORKSPACE_LOC\zmodlib.
        The structure of zmodlib is detailed in the below paragraph.
      • A main file, specific to the Baremetal app
    • One folder ZmodDAC1411_Demo_Baremetal_bsp corresponding to the Baremetal project bsp.

Under each of the above described demos, the zmodlib folder can be found, having the following structure:

  1. ZMOD Base Class sources: zmod.cpp, zmod.h
  2. Platform dependencies common includes: reg.h, dma.h and flash.h. These headers expose the IP core register access, DMA, and flash functions that are dependent on the platform (Linux or Baremetal). These functions will be implemented in the source files contained in the platform dependencies folders (Linux and Baremetal) shown below.
  3. Platform dependencies folders:
    • Linux - contains separate folders that implement Linux platform related functionality (functions listed in platform dependencies common includes mentioned above) on Linux platform.
    • Baremetal - contains separate folders that implement Baremetal related functionality (functions listed in platform dependencies common includes mentioned above) on Baremetal platform.
  4. For each Zmod, the folder containing its library. For example:
    • Folder ZmodADC1410 contains:
      • ZmodADC1410 sources: zmodadc1410.cpp, zmodadc1410.h
    • Folder ZmodDAC1411 contains:
      • ZmodADC1411 sources: zmoddac1411.cpp, zmoddac1411.h

3.2. Environment Setup

This section contains the steps for setting the environment for Baremetal project setup and Linux project setup for both Zmod ADC and Zmod DAC. Depending on the user needs, one can either use the projects we deliver in their own development process or use the libraries in their projects. If the second case is considered, the user should apply the below described settings to his project, in order to be able to build it.

3.2.1 Import Library and Demo Projects

The steps below need to be followed in order to obtain a complete SDK workspace and to be able to build and run any of the projects, in either Linux or Baremetal platforms.

3.2.1.1 Linux Environment Project Setup

The ZmodADC1410_Demo_Linux and ZmodDAC1411_Demo_Linux are run from Xilinx SDK.
This step by step tutorial roughly follows the How to debug Linux Application in SDK 2019.1 by Xilinx, with some changes due to our Debian 10 rootfs.

The following steps are for the Eclypse Z7 board. If a Zmod ADC is used, it should be attached to the Eclypse Z7's ZMOD A port. If a Zmod DAC is used, it should be attached to the Eclypse Z7's ZMOD B port.

3.2.1.1.1 Download the library
  • Download the git repository containing the libraries and demos using the below command:
git clone --recursive https://github.com/Digilent/Eclypse-Z7-SW.git -b zmod_adc_dac/master

NOTE: If you choose to download the repository as ZIP, the folder zmodlib will not be populated and you will have to populate it manually.

3.2.1.1.2 Download the SD Card Image
  • Download the latest eclypse-debian-buster-armhf-rfs.img_X.X.zip Petalinux image from the Eclypse Z7 git repository Releases and extract it on your PC.
    • You need to expand the Assets section to see the files.
  • Write the image to an SD card:
    • Linux: in a terminal window use the following command:
      dd if=/path/to/extracted/image/eclypse-debian-buster-armhf-rfs.img of=/dev/(sdX or mmcblkX}  && sync
    • Windows: use Rufus or Win32DiskImager.
  • Connect the board to your Ethernet network.
  • Insert the SD card and boot the board. On first boot, the rootfs partition will resize to fill the SD card then reboot.
  • Open a Terminal and connect to the board via its USB-UART interface (labeled PROG).
  • Login with username: eclypse and password: eclypse.

3.2.1.1.3 Add Vivado SDK workspace location
  • The downloaded workspace contains demo applications for both Linux and Baremetal.
  • Open Vivado SDK 2019.1 and assign the workspace location to the project download location.
  • If you want to use the demo projects, open the desired Linux or Baremetal demo project. The projects are already configured and ready to be used, except the Linux project where SYSROOT environment variable must be set according to Add SYSROOT Environment Variable section.


3.2.1.1.4 Import library to Vivado SDK
  • File → Import

  • Select General → Existing Projects into Workspace → Next

  • Select the project download location


3.2.1.1.5 Add SYSROOT Environment Variable in SDK
  • Download the latest eclypse-debian-buster-armhf-sysroot_X.X.tar.xz (.zip for Windows ) sysroot from the Eclypse Z7 git repository's Releases page and extract it on your PC (the location of the extracted folder will be later used as the path for the SYSROOT Environment Variable)
    Note: You need to expand the Assets section from github to see the eclypse-debian-buster-armhf-sysroot_X.X.tar.xz and .zip files.
    Windows only: When prompted whether to replace existing files, choose to replace.
  • In the SDK Project Explorer, right click on the application project you wish to run, then click “C/C++ Build Settings”
  • In the “C/C++ Build” group, select the “Environment” category
  • Add the SYSROOT variable pointing to the location where eclypse-debian-buster-armhf-sysroot rootfs folder can be found. For example “/home/cosmin/Documents/eclypse-debian-buster-armhf-sysroot”
    Windows: The SYSROOT environment variable if exists must be Deleted then reAdded to the list, rather than Editing the existing variable.
  • Click OK and wait for the Project to build


3.2.1.1.6 Find the Board IP Address
  • In the UART Terminal connected to the board, log in with the username/password combination eclypse/eclypse
  • Run the following command:
ip a
  • Copy the IP address of the board, example: 10.0.0.168


3.2.1.1.7 Establishing Connection to the Board
  • In the SDK Target Connections panel, open the Linux TCF Agent folder
  • Right click on Linux Agent [default] and click Edit
  • Enter the board IP address into the Host section
  • Click Test Connection to make sure that SDK can communicate with the TCF-agent on the board
  • Click OK


3.2.1.1.8 Run the Demo Project
  • To run the demo application, right-click on Project name → Run as → Launch on Hardware(System Debugger)


3.2.1.2 Baremetal Project Setup

3.2.1.2.1 Download the library
  • Download the demo project with the below command:
git clone --recursive https://github.com/Digilent/Eclypse-Z7-SW.git -b zmod_adc_dac/master

NOTE: If you choose to download the repository as ZIP, the folder zmodlib will not be populated and you will have to populate it manually.


3.2.1.2.2 Add Vivado SDK workspace location
  • The downloaded workspace contains demo applications for both Linux and Baremetal.
  • Open Vivado SDK 2019.1 and assign the workspace location to the project download location.
  • If you want to use the demo projects, open the desired Baremetal demo project. The projects are already configured and ready to be used.


3.2.1.2.3 Import library to Vivado SDK
  • File → Import

  • Select General → Existing Projects into Workspace → Next

  • Select the project download location


3.2.1.2.4 Vivado SDK Project Explorer
  • The ZmodADC1410_Demo_Linux and ZmodDAC1411_Demo_Linux projects must be closed or deleted from Project Explorer (right-click on project name→ Close Project or Delete)


3.2.1.2.5. Run the demo project
  • Make sure the board is connected to your PC and it is powered on.
  • Make sure the jumpers are set accordingly.
  • Program the board: Xilinx → Program FPGA

  • Run the demo application: right-click on project name → Run as → Launch on Hardware(System Debugger)


3.2.2 Create New Project/Use libraries in your project

This use case is needed when an SDK workspace is created by the user. The steps below need to be followed in order to obtain a complete SDK workspace and to be able to build and run any of the projects, in either Linux or Baremetal platforms.

3.2.2.1 Linux Environment Project Setup

It is assumed that Zmod and specific folders for Zmods (ZmodADC1410 for example) are placed in the SDK workspace root folder, as provided by Digilent (see Delivery Structure).

  • Create a new application project.
  • Under src folder, right click option, select New / Folder
  • Select Advanced
  • Link to alternate location (Linked Folder)
  • Variables… → Select WORKSPACE_LOC → Extend… → Select zmodlib folder

3.2.2.1.2 Add “--sysroot” Project Setting
  • In the Project Explorer, right click on the project name, select “C/C++ Build Settings”
  • In the “C/C++ Build” group, select “Settings” category
  • Select “ARM v7 Linux g++ linker”/”Miscelaneous” node
  • In the Linker Flags field add
    --sysroot=${SYSROOT}

3.2.2.1.3 Define LINUX_APP
  • In the Project Explorer, right click on the project name, select “C/C++ Build Settings”
  • In the “C/C++ Build” group, select “Settings” category
  • Select “ARM v7 Linux g++ compiler”/”Symbols” node
  • Add LINUX_APP definition (using the ‘+’ button)

3.2.2.1.4 Add SYSROOT Environment Variable in the SDK
  • Download the latest eclypse-debian-buster-armhf-sysroot_X.X.tar.gz sysroot from Releases and extract it on your PC
    • You need to expand the Assets section of the git page to find the file mentioned above
  • In the Project Explorer, right click on the project name, select “C/C++ Build Settings”
  • In the “C/C++ Build” group, select “Environment” category
  • Add SYSROOT variable pointing to the location where Petalinux sysroot can be found. For example “/home/cosmin/Documents/eclypse-debian-buster-armhf-sysroot”

Note: In Petalinux 2019.1 in order to build the sysroot image is necessary to run the following command:

petalinux-build -c build-sysroots

3.2.2.1.5 Define Libraries and Library Directories
  • In the Project Explorer, right click on the project name, select “C/C++ Build Settings”
  • In the “C/C++ Build” group, select “Settings” category
  • Select “ARM v7 Linux g++ linker”/”Libraries” node
  • Add the following library in the “Libraries (-l)” list:
    • uio
  • Add the following directories in the “Library search path (-L)” list:
    • ${SYSROOT}/usr/lib
    • ${SYSROOT}/lib

3.2.2.1.6 Define Include Directories
  • In the Project Explorer, right click on the project name, select “C/C++ Build Settings”
  • In the “C/C++ Build” group, select “Settings” category
  • Select “ARM v7 Linux g++ compiler”/”Directories” node
  • Add the following directories:
    • ${SYSROOT}/usr/include
    • ${CWD}/../../zmodlib/Zmod
    • ${CWD}/../../zmodlib/ZmodADC1410


3.2.2.2 Baremetal Project Setup

It is assumed that Zmod and specific folders for Zmods (ZmodADC1410 for example) are placed in the SDK workspace root folder, as provided by Digilent (see Delivery Structure).

  • Create a new application project.
  • Under src folder, right click option, select New / Folder
  • Select Advanced
  • Link to alternate location (Linked Folder)
  • Variables… → Select WORKSPACE_LOC → Extend… → Select zmodlib folder

3.2.2.2.2 Define Include Directories
  • In the Project Explorer, right click on the project name, select “C/C++ Build Settings”
  • In the “C/C++ Build” group, select “Settings” category
  • Select “ARM v7 g++ compiler”/”Directories” node
  • Add the following directories:
    • ${CWD}/../../zmodlib/Zmod
    • ${CWD}/../../zmodlib/ZmodADC1410