top of page

MicroZed Chronicles: Using Python to Extract ILA Data

As we look at how to debug our systems, one commonly used approach is to implement an ILA within the design for system observation in the wave viewer.

Sometimes the information in the ILA provides all we need to know about design issues, however, this is not always the case. For more complex debugging, it can be ideal to use an ILA to capture real-world data and store it into a file which can be processed further. Depending on where we put the ILA, we can use the information contained in the file in several different ways.


  1. ILA monitors output data – This can be used for checking against the test bench to demonstrate the correctness of the model instantiated against the verified behavior.

  2. ILA monitors input data – This can be used to input data into a test bench module to try to identify the observed issues with real-world data. Of course, the timing of signals as observed in the hardware can also be replicated in this case as well.  


Both of these approaches are very powerful in our development, verification, and validation. When working with the ILA, we may be more familiar with the waveform view, however, we can easily save the ILA information as a CVS file by using the command below.

write_hw_ila_data ila_file.csv [upload_hw_ila_data hw_ila_1] -csv

 This will save the CSV file into the current working directory of Vivado (run the pwd command in the tcl window to determine this if unsure).


We can also save the ILA using the File->Export-> Export ILA Data. This will open a dialog asking which ILA you wish to export, the location of the exported data, and data format.

For this example, I have taken the LFSR created in last week’s blog and added in a simple block design which provides a clock and connects an ILA to the Fibonacci and Galois outputs. The ILA can then be opened in Vivado and the CSV exported

By taking a look at the ILA CSV data within a txt file, we will see that the information is presented clearly. The first column shows the sample in the buffer and the second column shows the sample in the window.


The sample buffer will count sequentially for each of the samples in the buffer regardless of if windows were configured in the triggering. The second sample count in the window will count from 0 to the window size before repeating.


For example, if we have a 1024 sample buffer configured for 4 windows, the sample in the window count will count between 0 and 255 four times, while the sample in the buffer count increments linearly from 0 to 1023.


The third element is the trigger. This is set to 1 to indicate when the trigger occurred in the sample window. This can be seen in the window below which shows a 1 in the third column when the trigger value is seen (in this case 0x00 the start of the LFSR sequence).

The remaining columns report the hex values of the Fibonacci, Galois, and clock wizard locked signal.


As in our previous blog, we wrote out the LFSR sequences into a text file and can compare the results of the text file against the ILA CSV with a little Python.

import csv
csv_file = '<location>iladata_trig.csv'
text_file = '<location>fibonacci.txt'

with open(csv_file, newline='') as csvfile:
    reader = csv.reader(csvfile)
    # Skip the top two rows of the CSV File

    Fibonacci_hw_values = []
    # Store Fibonacci Sequence
    for i, row in enumerate(reader):
        if i < 256:

Fibonacci_tb_values = []

# Open test bench text file
with open(text_file, 'r') as file:
    for line in file:
        # Strip newlines and any whitespace around the value
        value = line.strip()

non_matching_in_a = []
non_matching_in_b = []

Fibonacci_tb_values = [item.lower() for item in Fibonacci_tb_values]

for item in Fibonacci_tb_values:
    if item not in Fibonacci_hw_values:

for item in Fibonacci_hw_values:
    if item not in Fibonacci_tb_values:

print("Non-matching in HW:", non_matching_in_a)
print("Non-matching in TB:", non_matching_in_b)


In Python we can open both files and read them into Python lists; one from the test bench text file and the other from the CSV file. Once the two lists are populated, we can do a simple comparison, however, be careful of the cases between the two lists. My initial results are below.

The ILA stores values in upper case while the test bench writes them out in lower case. We can remedy this very easily by converting the case of one of the lists. This, however, shows that an error is flagged properly, if there is one.  

Of course, running the Python script shows how we can work with the data from the ILA using the Python CSV package. It is very simple if we want to extract a column of data and generate a text file. The test bench could apply to a simulation.


Over the last few weeks, we’ve learned how to use the Analog Discovery to stimulate our devices under test using Python and also how to export data from an ILA and use it in Python. Both are very useful skills when bringing systems up on the bench.


Note: if we are using Versal devices, there is a Python interface we can use for controlling the Versal ILA called ChipScoPy. We will explore this in a future blog.


Workshops and Webinars

If you enjoyed the blog why not take a look at the free webinars, workshops and training courses we have created over the years. Highlights include

Embedded System Book   

Do you want to know more about designing embedded systems from scratch? Check out our book on creating embedded systems. This book will walk you through all the stages of requirements, architecture, component selection, schematics, layout, and FPGA / software design. We designed and manufactured the board at the heart of the book! The schematics and layout are available in Altium here   Learn more about the board (see previous blogs on Bring up, DDR validation, USB, Sensors) and view the schematics here.


bottom of page