AXI Burst need support on Pynq Z1/Z2 with Vitis HLS rather than merely Vivado HLS

Hello.
I just try the blog axi4, which use axi burst to transfer data for “sqrt” operation.
This blog use Vivado HLS, rather than Vitis HLS as the axilit case they give in axilite.

I just try to redo this axi brust project by Vitis HLS (2021.2). I can export IP and use thin in Vivado (same 2021.2 version as HLS) but there would be one more port in Vivado compared to project in the blog axi4.

  1. I find one place different between Vitis HLS (I do) and Vivado HLS (in blog) in the step of automatic connection:

  2. After synthesis and generate bitstream. I find the hardware IP is different as the previous Vivado HLS one in blog axi4 on Pynq:

  3. I use the Python code (change the IP name by select the second “s_axi_sqrt”), the hardware IP will generate ‘0.0’, which is not same as the software result:

I guess it comes from the added port in Vitis HLS (2021.2) compared to the Vivado version.
Assume the HW development is right, I guess the Python code need to be rewritten.
This issue has bothered me a long time, I want to ask help for it. Thanks.

At last, let me thanks for the authors in website: Parallel Programming for FPGAs: Projects and Labs — pp4fpgas 0.0.1 documentation
They provide many detailed tutorial and help me a lot. : )

By the way, May I ask how can I improve my understanding on Pynq and use it well. I want to know how it is, rather than repeat and modify the tutorial.
If someone know where I can find the explanation on why we do it, it would be pretty valuable to me. Thanks in advance.

I upload the project I do (the source files, should come from axi blog axi4):
info{
script.tcl for HLS
design_1.tcl for Vivado (I follow the blog as well.)
Vivado HLS 2021.2, Vivado 2021.2.
OS; Win 10.
}

axi4_burst_self.zip (4.5 KB)

I added two lines in the text provide in axi4 but not in the provided zip file\ axi4_burst.zip :

#pragma HLS INTERFACE s_axilite port=in
#pragma HLS INTERFACE s_axilite port=out

and rerun the project in Vitis HLS and use the IP in the instruction of axi4. Unfortunately, the hardware interface still cannot work.
I zip all files of the project of HLS (axi4_sqrt), and Vivado (project_1) onto Google Drive axi_burst_all.zip.

The third time edition:
Now I found why it cannot work: The 2021.2 (Vivado, HLS) will generate two channels and is not same as the address as 2019.1 (Vivado, HLS):

2019.1:
image

2021.2:
image

It means the IP address for 2019.1 should not be used for 2021.2.

Now the problem become how to use these address for data transfer?:

AXI Burst is fundamental function on Pynq, hope this blog can benefits more people with same confusion as me.

Hi @AllenChenChao,

You have removed these lines from the code

#pragma HLS INTERFACE s_axilite port=in
#pragma HLS INTERFACE s_axilite port=out

These lines are used to pass the pointer to in and out. As these lines are missing a new interface is created.

Mario

Dear

Thanks for your attention and help. I use the code axi4_burst.zip provide in axi4 without the “two lines”.

I have added the two lines:

#pragma HLS INTERFACE s_axilite port=in
#pragma HLS INTERFACE s_axilite port=out

and rerun the project in Vitis HLS and use the IP in the instruction of axi4. Unfortunately, the hardware interface still cannot work:

I zip all files of the project of HLS (axi4_sqrt), and Vivado (project_1) onto Google Drive axi_burst_all.zip.

Apologies,

the lines should be

#pragma HLS INTERFACE s_axilite port=in bundle=sqrt
#pragma HLS INTERFACE s_axilite port=out bundle=sqrt

I suggest you use the register_map instead of the offset address.

ol.axi4_sqrt_0.register_map

Otherwise, you will need to check if the offset address is correct for those arguments

Additionally, I just ignore the new port in Vivado automatic connection, and make the bitstream for pynq, the hardware does not work well as the former one (I think we must choose it for corresponding control mechanism).

Hardware do not work in Pynq:

Dear, thanks for suggestion. May I ask some practical way for the data transfer between PS and PL after taking the two new pragma. After the attempt, In HW design of Vitis HLS and Vivado, they are same as in the blog of Vivado HLS and Vivado axi4.

However, when I use the python code in axi4, the HW does not work as well:

Then I tried the:

ol.axi4_sqrt_0.register_map

The Python code in axi4 cannot be used anymore. We think the register_map need extra configuration:

We make some attempt to configure it, but failed as well:

By the way I upload the new project (hls and vivado):
axi4_burst_pragma

I am not sure if Allocation
or registers work well, or how to work them well?

Hi, I redo the project in with Vivado HLS 2019.1 and Vivado 2019.1 in axi4, you guess what, the HW IP works well as the SW function:

The data address gain my attention. Does someone know how to select them?

I recheck the Vivado Project of 2019.1 (with Vivado HLS 2019.1) and 2021.2 (with Vitis HLS 2021.2).
I found the difference on IP address.

Vivado 2019.1 (with Vivado HLS 2019.1) :

Vivado 2021.2 (with Vitis HLS 2021.2):

Someone may guess the IP address, but they have already been included in the .hwh files as shown in (note: 2019.1 and 2021.2 version):

You guess what happened. I changed the 2021.2 version IP address in Vivado and the result is same:
No HW result in pynq.
There must be a mechanism for address choice. I know in Vivado 2019.1, we can check Vitis, I am not sure if it work well for 2021.2 version.

You HLS IP has a control port that you can use to start and stop the IP and set it to auto restart, and a control register.
You also have an interface for your input and output pointers.
In your original design when you omitted the two lines:

#pragma HLS INTERFACE s_axilite port=in bundle=sqrt
#pragma HLS INTERFACE s_axilite port=out bundle=sqrt

This created two separate ports for the control and the input/output pointers.

The code .write(0x20, length) etc. is assuming the registers on the interface are setup as they are in the original example.
0x20 is the register offset.

It is bad practice to hard code addresses and offsets like this as they can change. (They can change between versions, or if you change your design)

Mario suggested you use ol.axi4_sqrt_0.register_map instead. PYNQ automatically parses the HWH and determines the addresses and register offset for your design.

This allows you to set a register using its name. See example or register map here: https://www.youtube.com/watch?v=vK1cEEdKAds

If you use register_map, you can interactively check if the register exists, and that you are writing to it correctly. You also need to check the registers generated by HLS so you know what you need to write to.

Cathal

1 Like

Thanks for recommending YouTube link Using the PYNQ ‘register map’ functionality. I test register map and it works well (same result as the the way in axi4):

part of Code:

AF_interface_ip.register_map
AF_interface_ip.register_map.len = 7
length = 7
inpt = Xlnk().cma_array(shape=(length,), dtype=np.float32)
outpt = Xlnk().cma_array(shape=(length,), dtype=np.float32)
# a = [1.272, 0.675, 2.479,1.06,1.16,1.11, 1.11] # outpt[0] == 0
a = [-0.074,1.59,-2.251,0.575552,1.115450,0.657046,0.589000]   # outpt[0] == 1
np.copyto(inpt, a)
AF_interface_ip.register_map.in_r = inpt.physical_address
AF_interface_ip.register_map.out_r = outpt.physical_address
AF_interface_ip.register_map.CTRL.AP_START=1

Test Version: Vivado (HLS) 2019.1. I use it simply test register map function, I will test newer version later: )

These two links also help me:
Pynq to m_axi HLS IP
PYNQ_tutorials/hls_m_axi /hls_m_axi_example.ipynb

1 Like