PYNQ: PYTHON PRODUCTIVITY

Vitis HLS wrong ap_axiu tdata size

I am implementing a really simple multiplier IP in Vitis HLS 2020.2. I am following step by step the tutorial on the PYNQ documentation (Overlay Tutorial — Python productivity for Zynq (Pynq) v1.0)

I basically copy-pasted the code of the multiplier from the documentation, the code is the following (pretty straight forward):

#include <ap_int.h>
#include <ap_axi_sdata.h>

typedef ap_axiu<32,1,1,1> stream_type;

void mult_constant(stream_type* in_data, stream_type* out_data, ap_int<32> constant) {
#pragma HLS INTERFACE s_axilite register port=constant
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE axis port=in_data
#pragma HLS INTERFACE axis port=out_data
    out_data->data = in_data->data * constant;
    out_data->dest = in_data->dest;
    out_data->id = in_data->id;
    out_data->keep = in_data->keep;
    out_data->last = in_data->last;
    out_data->strb = in_data->strb;
    out_data->user = in_data->user;

}

The main problem is that when I synthesize my code, my streams are synthesized with tdata equal to 8, which is obviously wrong.

Any idea of what is going on? I also read the documentation of Vitis HLS, and the typedef is correct (at least as far as i know), and the code is basically copy pasted from the PYNQ documentation.

Dear Mattias, I am currently introducing myself and my students to the Vitis & PYNQ framework. In my opinion is the tutorial outdated. After the transition from Vivado HLS to Vitis HLS some data structures behave probably differently.

After digging through the documentation I prepared a short guide for the multiplier with the streaming interface. It contains data structures recommended by the docs and also links to the docs which may guide you:

Tutorial slides

Code

2 Likes

This is amazing! Thank you so much, it works fine!

I wanted to ask you (if possible) a little extra help. I am learning how to use these tools for my MSc thesis, the main idea was to start from that tutorial to “incrementally” test different things that I need.

The default code of the tutorial works perfectly, now I made a slight change in the IP axis interface, in particular i declared the axis type as:
typedef ap_axis<20,0,0,0> pkt_t;

I am doing this to test/experiment with IPs that are not directly compatible with the axis DMA interface.

To solve this problem I am using an axis data width converter and the complete scheme is the following:


With the DMA configured in the following way:

The Python code in PYNQ is the same that you provided (i’m omitting the imports and overlay setup) with minor changes:

from pynq import allocate
import numpy as np

in_buffer = allocate(shape=(20,), dtype=np.uint32)
out_buffer = allocate(shape=(20,), dtype=np.uint32)

for i in range(20):
    in_buffer[i] = i

multiply.register_map.multiplier = 3

dma.sendchannel.transfer(in_buffer)
dma.recvchannel.transfer(out_buffer)
dma.sendchannel.wait()
dma.recvchannel.wait()

out_buffer

It works “fine”, however I noticed that my output is wrong for some inputs and I can’t understand why:

PynqBuffer([ 0,  3,  6,  9, 12, 15, 18, 21,  8, 27, 30,  1, 36, 39, 10, 45,
            48,  3, 54, 57], dtype=uint32)

For some number it makes the wrong multiplication. Could you help me figuring out why? I think it’s something related with the data width conversion

Hi @leuko,

Thank you for the informative slides. Have you successfully implemented any Vitis vision library function using Vitis HLS in the AXI Stream mode?

no :frowning: