-4

i try to split a HLS stream which is incoming from the interface. This stream contains a data stream and a user stream with control signals (startFrame, stopFrame, startLine, etc).

I want to use an xf::cv kernel (in this example threshold). The threshold module needs the data stream, which I want to extract from the incoming stream and reconstruct it after processing.

In my C simulation this is working fine, but I can't synthesize it to VHDL code, i just facing the error message

ERROR: [HLS 214-208] The ap_axis|ap_axiu|qdma_axis|hls::axis data types must only be used for AXI-Stream ports in the interface. 'data_stream_out' is not an AXI-Stream and/or is not a port in the interface

So I can't create a sub stream like that. But I need to keep the streaming because the module will be part of a larger set of video processing modules.

With a correct streaming type in the interface, the synthesis is working, for sure, but i need to keep the interface like it is.

So I need to access the Data part of the stream, which has the correct type for AXIvideo2xfMat.

Here is my current minimal example (which is simulating well, but does fails at synthesis)

typedef struct video_struct {
    ap_axiu<PIXEL_WIDTH, 1, 1, 1> Data;
    ap_uint<4> User;
} video_if_t;

typedef hls::stream<video_if_t> stream_t;

void mat2mat_proc(stream_t& stream_in, stream_t& stream_out, dim_t height, dim_t width){
#pragma HLS INTERFACE axis register both port = stream_in
#pragma HLS INTERFACE axis register both port = stream_out

    xf::cv::Mat<XF_8UC1, HEIGHT_MAX, WIDTH_MAX, XF_NPPC1> imgInput(height, width);
    xf::cv::Mat<XF_8UC1, HEIGHT_MAX, WIDTH_MAX, XF_NPPC1> imgOutput(height, width);

    hls::stream<Data_t> data_stream_in("data_stream_in");
    hls::stream<Data_t> data_stream_out("data_stream_out");

#pragma HLS STREAM variable=data_stream_in depth=2
#pragma HLS STREAM variable=data_stream_out depth=2
#pragma HLS DATAFLOW

    extractDataStream(stream_in, data_stream_in, height, width);
    xf::cv::AXIvideo2xfMat(data_stream_in, imgInput);
    xf::cv::Threshold<XF_THRESHOLD_TYPE_BINARY, XF_8UC1, HEIGHT_MAX, WIDTH_MAX, XF_NPPC1>(imgInput, imgOutput, 128, 255);
    xf::cv::xfMat2AXIvideo(imgOutput, data_stream_out);
    reconstructStream(data_stream_out, stream_out, height, width);
}

void extractDataStream(stream_t& stream_in, hls::stream<Data_t>& data_stream_in, dim_t height, dim_t width){
    video_if_t streamBuff;
    for(int i = 0; i < height * width; i++){
#pragma HLS PIPELINE II=1
        streamBuff = stream_in.read();
        data_stream_in.write(streamBuff.Data);
    }
}

void reconstructStream(hls::stream<Data_t>& data_stream_out, stream_t& stream_out, dim_t height, dim_t width){
    video_if_t streamBuff;
    Data_t dataOut;
    for(int i = 0; i < height * width; i++){
#pragma HLS PIPELINE II=1
        dataOut = data_stream_out.read();
        streamBuff.Data = dataOut;
        // Set User_t as needed
        streamBuff.User = 0;
        stream_out.write(streamBuff);
    }
}

Like i already mentioned is the problem, that it is not allowed to create sub-streams inside of modules.

    hls::stream<Data_t> data_stream_in("data_stream_in");
    hls::stream<Data_t> data_stream_out("data_stream_out");

Any suggestions, how i can avoid this?

2
  • how is the namespace xf provided? what provides it? Commented Sep 27, 2024 at 18:07
  • The xf namespace is part of the vitis vision library from xilinx/amd. This is the fpga optimized opencv library Commented Sep 27, 2024 at 20:12

1 Answer 1

0

Your example is incomplete, it does not define the type Data_t, from which you cannot create a stream. However, from streambuff.Data = dataOut; it can be assumed that Data_t is ap_axiu<PIXEL_WIDTH, 1, 1, 1>. In that case, you came across the same problem as I did when I tried to create a stream directly from ap_axiu - the error HLS 214-208. There is a workaround to use the type inherited from ap_axiu. For example, using the type definition for Data_t assumed above, create stream from Word_t:

struct Word_t : Data_t {
    Data_t() {
        data = 0;
        keep = 0;
        last = 0;
        id   = 0;
        user = 0;
    }

    template<class T>
    Word_t & operator=(const T & other) {
        data = other.data;
        keep = other.keep;
        last = other.last;
        id   = other.id;
        user = other.user;
        
        return *this;
    }
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.