cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Visitor
Visitor
10,022 Views
Registered: ‎08-18-2015

HLS Floating point operation gives error when programming xillybus ip-core

Hi, 
I am using xillybus ip core to communicate data between linux running on PS of zedboard with the ipcore on PL.Basically,I want to convert an image into grayscale.As a prototype I am sending a 4*12(48 elements) matrix from linux to PL and after performing averaging of every three pixels per row I get a grayscale value which is read back into a 4*4(16 elements) matrix.Now the problem is the code I use for averaging the pixels does not give correct values.The first column is correct but the rest of the columns are zero.
I extended the HLS demo code that comes with xillybus to write my code for averaging every three elements row wise.I suspect there is either something wrong with the way I am using floating point operations or the way I am reading or writing might be faulty.
Please, have a look at my HLS code and guide me.

#include <math.h>
#include <stdint.h>
#include "xilly_debug.h"
#include "ap_cint.h"
#include "ap_utils.h"

 

float rgb2gray(float r, float g, float b) {
float gray = (r + g + b)/3;
return gray;
}

void xillybus_wrapper(int *in, int *out) {
#pragma AP interface ap_fifo port=in
#pragma AP interface ap_fifo port=out
#pragma AP interface ap_ctrl_none port=return


float x1, x2, x3;
uint8_t res;
uint32_t i;
float y1;

 

for (i = 1; i <= 16 ;i++)
{
// Handle input data
x1 = *in++;
x2 = *in++;
x3 = *in++;

// Run the calculations
y1 = rgb2gray(x1, x2 ,x3);
res = uint8_t(y1);

 

// Handle output data
*out++ = res;

}
}

















0 Kudos
Reply
4 Replies
Visitor
Visitor
9,807 Views
Registered: ‎08-18-2015

Hi, this is me again.Just to mention that I am totally new to vivado HLS and know very little about C-based HLS.I am coding under the assumption that the C based HLS is coded just like a common c program.However, in some C code examples for hls, I have seen a lot of pointer usage which obviously means something that I don't understand.


Please, guide me as to how I should code.With the xillybus ip-core(on Zedboard) I am sending RGB values of an image,one word(4 bytes) at a time(the core accepts and transmits 32 bits at a time).Such that each byte has first three bytes as R G and B values of a pixel and the fourth byte is the R value of the next pixel.Next byte has BGRG and so on.


I unpack the words(four bytes) in the following code, and then pack them again after getting their average value (the greyscale value).
The following code is an "improved" code over the previous one.
What I think it does is:     Reads three words.Unpacks them into individual bytes, 12 in number.And then averages them.Three at a time and then packs the four bytes in a word and sends back.

When I send the following stream [1 2 7 1 2 7 1 2  7 12 7 ] the result is [3 1 5 3] while the correct result should be  [3 3 3 3].There is nothing wrong at the sending and receiving end as I have checked it and the result for a single byte [1 2 7 1] is [0 0 0 3], which seems correct.

I know there is some issue with the way I am handling data and the way the functions inputs and outputs are used in the code that I have written but I cannot figure out what.Please, help me and tell how I should write this code.

Here is the new code that I wrote.

#include <math.h>
#include <stdint.h>
#include "xilly_debug.h"
#include "ap_cint.h"
#include "ap_utils.h"

 

 

//rgb to gray function

float rgb2gray(uint8_t r, uint8_t g, uint8_t b) {
float gray = (r + g + b)/3;
return gray;
}

 

void xillybus_wrapper(int *in, int *out) {
#pragma AP interface ap_fifo port=in
#pragma AP interface ap_fifo port=out
#pragma AP interface ap_ctrl_none port=return

 

//variable declarations
int x1, x2, x3;
float y1,y2,y3,y4;
int res;
uint8_t bytes[12];

 

// Handle input data
x1 = *in++;
bytes[0] = (x1 >> 24) & 0xFF;
bytes[1] = (x1 >> 16) & 0xFF;
bytes[2] = (x1 >> 8) & 0xFF;
bytes[3] = x1 & 0xFF;
x2 = *in++;
bytes[4] = (x2 >> 24) & 0xFF;
bytes[5] = (x2 >> 16) & 0xFF;
bytes[6] = (x2 >> 8) & 0xFF;
bytes[7] = x2 & 0xFF;
x3 = *in++;
bytes[8] = (x3 >> 24) & 0xFF;
bytes[9] = (x3 >> 16) & 0xFF;
bytes[10] = (x3 >> 8) & 0xFF;
bytes[11] = x3 & 0xFF;


// Run the calculations
y1 = rgb2gray(bytes[0], bytes[1] ,bytes[2]);
y2 = rgb2gray(bytes[3], bytes[4] ,bytes[5]);
y3 = rgb2gray(bytes[6], bytes[7] ,bytes[8]);
y4 = rgb2gray(bytes[9], bytes[10] ,bytes[11]);

 

//truncate floats into uint8 types and pack them in an int
res = (uint8_t(y4) << 24) | (uint8_t(y3) << 16) | (uint8_t(y2) << 8) | uint8_t(y1);

 

// Handle output data
*out++ = res;
//*out++ = x2;
//*out++ = x3;
}




 

 

0 Kudos
Reply
Advisor
Advisor
9,730 Views
Registered: ‎04-26-2015

I'm not sure that this is the best way to go about it. Better to just transfer one pixel (three bytes) at a time, and leave the remaining byte unused (or use it to set transparency, which is the normal purpose). That drastically simplifies the code.

 

Have you put this through C simulation, or just gone straight to the FPGA? C simulation is great, and you can do a lot of debugging there to sort out what's going on.

 

With that said, I think your problem is simply that you're reading the stream in the wrong order. The data is (apparently) being packed into the stream in a small-endian manner, so the first byte (1) gets put into the least significant byte of the first word (ie x1[7:0]), the second byte (2) gets put into x1[15:8], the third byte (7) gets put into x1[23:16], and the fourth byte (1) gets put into x1[31:24]. Then it's being read out as big-endian, so that bytes[0] = x1[31:24] = 1, bytes[1] = x1[23:16] = 7, etc. The end result is that "bytes" looks like this:

 

1,7,2,1,2,1,7,2,7,2,1,7

Then the sums of each section are 10, 4, 16, and 10. Dividing each by three (and converting back to integer) yields the result you've got (3,1,5,3).

 

Simply reading them out in little-endian will yield the correct result.

Observer
Observer
1,998 Views
Registered: ‎09-13-2017

hello,

 

I am trying to find derivative (difference) of an image in PL part using xillybus IP core. For prototyping, i created a 16x1 matrix and tired to send it to PL using xillybus IP core. I'm sending this whole at once (16 elements) and separating the bytes in HLS. Here comes my problem. I'm sending the following data

sent data= [99, 176, 96, 109, 106, 97, 43, 188, 111, 161, 98, 180, 55, 156, 155, 149]

 

and output from fpga is:

received data= [12, 51, 45, 100, 7, 155, 149, 0,  0,  0,  0,  0,  0,  0,  99,  0]

 

Problem: incorrect results and Order of the bytes splitted  is not correct

 

I followed your demo and tried to read data in Little Endian but still wrong results

I monitored sending end and found that data sent successfully. Here is my Host program.

 

http://txt.do/djttn

 

I suspect there is some issue where i separate bytes from integer input in HLS. Here in HLS program,

 

http://txt.do/djtr1

 

I noticed an interesting fact that

                                                                      byte[0]=99 (that's correct),

byte[1]=106( which is 5 point in sent data),

byte[2]=111 (9th point of sent data stream)

 byte[3]=55 (13 th point of sent data stream)

all of these are the first index point of respective nibble.

 

Please have a look at my problem and guide me. thanks

 

 

Tags (2)
0 Kudos
Reply
Observer
Observer
1,995 Views
Registered: ‎09-13-2017

P.S line124 in Host program "Mat frame,frameG;" remained uncommented. This should be commented.
0 Kudos
Reply