Digilent ARTY Z7 Dev Board - Review

Table of contents

RoadTest: Digilent ARTY Z7 Dev Board

Author: cmelement14

Creation date:

Evaluation Type: Development Boards & Tools

Did you receive all parts the manufacturer stated would be included in the package?: True

What other parts do you consider comparable to this product?: The Parallella Board, snickerdoodle, Z-turn Board, etc.

What were the biggest problems encountered?: Example projects don't get updated for newer versions of Vivado.

Detailed Review:

Digilent Arty Z7 Dev Board Review



First of all, thank Randall Scasny() for organizing this Digilent ARTY Z7 Dev Board road test and Digilent for offering the road test kit. I am very grateful for being selected for the road test.


First Impression


The board is packed in a compact and neat cardboard package.



An extra protection foam is very thoughtful for protecting components and exposed connector pins.



PCB layout is well designed and quality is very good.





Demo Software


Digilent provides 3 example projects which are all created in Vivado 2016.4. I tried to exercise all three examples in Vivado 2018.2, but I only got one example work, i.e. XADC demo after upgrading the IPs used by the project.


However, after installing Vivado 2016.4, I was able to successfully complete the other two example projects. It would be very helpful if Digilent can update demo projects for newer versions of Vivado suites.


Using Python on ARTY Z7 Dev Board through PYNQ


PYNQ is an open-source project from Xilinx® that makes it easy to design embedded systems with Xilinx Zynq® Systems on Chips (SoCs). Even though ARTY Z7 Dev Board isn't one of the official development boards supported by PYNQ. However, it has very similar hardware components as the official PYNQ-Z1 board has. Probably the biggest difference between them is PYNQ-Z1 has a microphone while ARTY Z7 Dev Board doesn't.


MicroSD Card Setup

Given the hardware similarity, the PYNQ-Z1 image (current version is 2.3) can be used for ARTY Z7 Dev Board (as long as you don't exercise the microphone relate function). To make your own PYNQ Micro-SD card:

  1. Download the appropriate PYNQ image for your board
  2. Unzip the image
  3. Write the image to a blank Micro SD card (minimum 8GB recommended)

For detailed instructions on writing the SD card using different operating systems, see Writing the SD Card Image.

To set up ARTY Z7 for using Python, you just need to follow the instructions in PYNQ-Z1 Setup Guide. Note: Even though the Firefox is mentioned as one of supported browsers in the guide, I couldn't make it pass through the login window as shown below. Thus I recommend use Chrome. PYNQ image provides a built-in Jupyter Notebook web application through which you can interactively run Python code as well as make notes. As described in the guide, you can type either or http://pynq:9090 (depends on you use static IP or DHCP) into your Chrome browser's address box to access the Jupyter Notebook. The login window will show up. Both default username and password are "xilinx" (obviously without double quotes).


Once you successfully login, the following page will show up. Each folder and its subfolders contain lots of Jupyter Notebook files (.ipynb). You can run each notebook just by clicking on the filename.


For example, under /base/trace folder, there's a notebook called trace_analyzer_i2c.ipynb.


If you click on the file, the following page will show up.



Python Example on ARTY Z7 Dev Board

Like many built-in examples require external daughter boards (such as PMOD, Arduino) to make it work, the above I2C trace analyzer example requires a Pmod TMP2 sensor which I don't have. Thus I modify the above example notebook and make it work with any I2C device (minor code changes may be required). Below is screen shot of my modified notebook and the actual notebook file is attached at the end of this review.


Decoding Generic I2C Transactions using Trace Analyzer


This notebook is a modified version of the built-in datatrace_analyzer_i2c.ipynb example in PYNQ-Z1 image under /home/xilinx/jupyter_notebooks/base/trace. It shows how to use the trace analyzer to capture and analyze generic I2C transactions. Unlike the built-in example which only works with the Pmod TMP2 sensor, the code in this notebook can be directly used as an example for any I2C devices.

Since I don't have a Pmod TMP2 sensor, an I2C device called FM24CLXX FRAM Board(the small blue PCB board shown below) is used instead. PYNQ-Z1 image has built-in class Pmod_TMP2 supporting the Pmod TMP2 sensor. However, FM24CLXX FRAM Board doesn't have built-in support. We have to use the generic I2C class Pmod_IIC.


Connect I2C Device to PMOD Port

You can connect your I2C device to the top row or bottom row pins on either PMODA or PMODB port. On the top side of Arty-Z7 PCB board, they are marked as JA and JB connector respectively. As described in the section Pmod of PYNQ document, only pins 2 & 3 or 6 & 7 have pull-up resistors which make them suitable for I2C interfaces. Since only one I2C peripheral is implemented in each IOP, only one I2C device can be connected to a PMOD port. In other words, you cannot simultaneously connect one I2C device to the top row and another one to the bottom row of a PMOD port.

In my case, I connect my FM24CLXX FRAM Board to the top row pins of PMODA port as shown in the picture below. That means I will use pin 2 & 3 of PMODA port. If you use a different port/row, you need to make corresponding code changes in the code example below. For instance, if you use PMODB port, you need to change overlay.trace_pmoda to overlay.trace_pmodb. If you connect your I2C device to the bottom row rather than the top row, you need to change Pmod_IIC(overlay.PMODA, 2, 3, ...) to Pmod_IIC(overlay.PMODA, 6, 7, ...). Please refer to class Pmod_IIC document for more details.

Note: When you connect your I2C device to PMOD port, please make sure align VCC(3.3V) and GND pins to the correct orientation. Otherwise, you may permanently damage your device.


Step 1: Downloading the overlay

The trace analyzer for all the interfaces are exposed from the base overlay.

from pynq.overlays.base import BaseOverlay

overlay = BaseOverlay('base.bit')
trace_analyzer = overlay.trace_pmoda

Step 2: Setup the trace analyzer

The I2C controller on PMODA interface runs at 100KHz, it is recommended to oversample the transactions (capturing more than 2 samples per logic level). Hence here we set the sampling frequency to 400KHz.

It takes little time to capture the samples, therefore we set the number of analyzer samples to the maximum (64K samples).

trace_analyzer.setup(frequency_mhz=0.4, num_analyzer_samples=65535)

Step 3: Prepare the I2C device

We plug the FM24CLXX FRAM Board to the top row pins of PMODA port on the board. The I2C address of the memory chip FM24CL16B on this board is 0x50. You I2C device may have a different I2C address so you need to modify the following code as required.

from pynq.lib.pmod import Pmod_IIC

sensor = Pmod_IIC(overlay.PMODA, 2, 3, 0x50)

Step 4: Play with the I2C device

We will program the first three bytes of the memory chip FM24CL16B with the following content: 11, 22 & 33 in sequence and verify them by reading them back.

start_addr = 0x0
num_bytes_read = 3

# Program three bytes from start_addr address
sensor.send([start_addr, 11, 22, 33])

# Read them back
readings = sensor.receive(num_bytes_read)

print('Byte(s) from address {0} is {1}.'.format(start_addr, readings))

Byte(s) from address 0 is [11, 22, 33].

Step 5: Run the trace analyzer

We change the content of the first byte to 0x55 (i.e., 85), then start the trace analyzer, followed by the sensor reading the the first byte back. The trace analyzer should capture the I2C transcations of reading back the content.

start_addr = 0x0
num_bytes_read = 1

# Modify the content
sensor.send([start_addr, 0x55])

readings = sensor.receive(num_bytes_read)

print('Byte(s) from address {0} is {1}.'.format(start_addr, readings))

Byte(s) from address 0 is [85].

After the trace analyzer has been stopped, we can call analyze() method to prepare all the captured samples into lanes of data. We can ignore the returned values for now because we want to see the sigrok decoded transactions as well.

_ = trace_analyzer.analyze()

Step 6: Analyzing and decoding

The next following cells utilize the sigrok decoders. The decoders are slightly modified, so decoded transactions can be aligned with the captured samples.

The next cell set protocol and the signal probes.

Fore more information, please read https://sigrok.org/wiki/Sigrok-cli

                            probes={'SDA': 'D3', 'SCL': 'D2'})

Sigrok can also show the information about a specified protocol.


ID: i2c

Name: I²C

Long name: Inter-Integrated Circuit

Description: Two-wire, multi-master, serial bus.

License: gplv2+

Annotation classes:

- start: Start condition

- repeat-start: Repeat start condition

- stop: Stop condition

- ack: ACK

- nack: NACK

- bit: Data/address bit

- address-read: Address read

- address-write: Address write

- data-read: Data read

- data-write: Data write

- warnings: Human-readable warnings

Annotation rows:

- bits (Bits): 5

- addr-data (Address/Data): 0 1 2 3 4 6 7 8 9

- warnings (Warnings): 10

Required channels:

- scl (SCL): Serial clock line

- sda (SDA): Serial data line

Optional channels:



- address_format: Displayed slave address format ('shifted', 'unshifted', default 'shifted')


I²C (Inter-Integrated Circuit) is a bidirectional, multi-master

bus using two signals (SCL = serial clock line, SDA = serial data line).

After protocol and probes have been set, we can call the decode() method. The path to the saved samples, the starting and ending sample numbers, and the path to the decoded file have to be specified.

Note: It is recommended not to set too large number for samples to decode. A very large number of decoded samples may lead to very slow rendering of the waveform display, possibly hanging the system.

In this example, we only decode 1000 samples. In general, it is okay to decode less than 4000 samples at a time. Users can decode more than 4000 samples, but displaying the waveforms will become very slow.

If users want to check various parts of the entire trace of samples, users can set the starting and ending positions repeatedly and rerun this cell.

start_position, stop_position = 1, 1000
waveform_lanes = trace_analyzer.decode('pmod_i2c_trace.csv', 
                                       start_position, stop_position,

Step 7: Waveform display

Let's polish the waveform for better display. We will add footer and header to the waveform dictionary.

For more information: http://wavedrom.com/tutorial.html

waveform_dict = {'signal': waveform_lanes, 
                 'config': {'hscale': 1},
                 'foot': {'tock': start_position},
                 'head': {'text': ['tspan', {'class': 'info h3'}, 
                                   'Pmod I2C Transactions']}}

The next cell will display the waveform. Users can use scrollbar to check the I2C transactions. The Pmod TMP2 sensor has the I2C base address 0x4B.

The next cell will take a few seconds to render the waveform.

from pynq.lib.logictools.waveform import draw_wavedrom



from pprint import pprint

[{'begin': 725, 'command': 'Start', 'end': 725},

{'begin': 728, 'command': 'Address read: 50', 'end': 757},

{'begin': 761, 'command': 'ACK', 'end': 765},

{'begin': 765, 'command': 'Data read: 55', 'end': 797},

{'begin': 797, 'command': 'NACK', 'end': 801}]


The above Wavedrom rendered waveform cannot show the full capture in one page because of the limitation of the render engine. To give the full picture of the I2C transcation captured by the trace analyzer, I hooked up an external logical analyzer and the capture shows below.image

Step 8: End

Users can reset the trace analyzer; this will clear all the saved files (*.csv, *.pd, etc.).

If users want to use a different setup, reset() method also has to be called.







Work To Do


My original plan for this road test was to implement a RISC-V processor, i.e., Freedom E310 in the program logic (PL). There's an implementation for Arty A7 board and I'd like to migrate it to this road test board Arty z7-20. After solving a lot of tools and design issues, I encountered the dead end of the migration: on z7-20 board, DDR memory cannot be routed through EMIO to PL. To make a workaround solution, significant modification will be required, which seems not feasible for this road test. I will continue working on this and update this review when I get it done.





Digilent Arty z7 board is a low cost, well designed and good quality development boards for Zynq-7000 SoC. It's very easy to use. Two HDMI ports makes it very suitable for video/vision applications. If Digilent provided more demo projects and kept them updated for the latest version of design tool, that would be more helpful for users.

  • Charles,


    That is a great review and thank you for explaining the differences between the boards. I think your article will be found and read by many wanting to know the very same thing. Well done  



  • Hi Rod,


    As you requested, I added some review of using Python on this kit. Hope you like it. Should you have any question, please let me know.



  • Added Python experiment. If you're interested in something else, please let me know.

  • As with many "ongoing reviews" there doesn't seem to have been much going on since your original review.

  • Hi Rod,


    Thanks for your comments. I haven't experimented on Python programming w/ Arty z7-20, but definitely it's an interesting thing to do. I will try it out and update this post shortly. Yes, this report will be an ongoing review and I am planning to post more along with experiments I will conduct on this kit. Stay tuned.



  • Hi Charles,


    Did you get to experiment with the Python programming - I'm interested to know what you made of that capability, as I have a similar FPGA board.


    When I tested out the Arty S7 board I too ran into issues with tutorial examples not including the exact board revision for my setup and consequently the configuration file was incorrect. The trouble was as a novice I was initially unable to make those config adjustments. Luckily one of the Github sources was updated during my roadtest to include the examples I required.


    In my opinion that was a very short roadtest report, but I see you plan on adding to it at a later date ( so I look forward to reading those updates).