Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

- Community Forums
- :
- Forums
- :
- Software Development and Acceleration
- :
- HLS
- :
- float operation gives 0

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

Highlighted

joseer

Voyager

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-15-2016 07:07 AM

5,335 Views

Registered:
07-06-2016

Hi,

I'm trying to do a simple division between two integers and I'm having a zero as a result instead a float (Iuf and Ivf variables):

void VTransform(short Iu, short Iv, short *Ialpha, short *Ibeta) { int iuOverRoot3, ivOverRoot3, tempIBeta; float Iuf,Ivf; short Iunormalized,Ivnormalized; Iuf=(Iu/4095); Ivf=(Iv/4095); *Ialpha =(short) (Iuf * 32768); *Ibeta=(short) (Ivf * 32768); }

I added the library "hls_math.h" hoping that it will solve the problem but I'm having the next error:

"#error C++ is required to include this header file"

Anyone knows why?

Thanks.

1 Solution

Accepted Solutions

Highlighted

u4223374

Advisor

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-15-2016 07:12 AM

9,999 Views

Registered:
04-26-2015

That's 100% correct C behaviour. If you divide an integer by an integer, you get an integer. Integer division rounds towards zero, so if your expected value is less than 1, you'll just get zero.

Try this:

Iuf=(Iu/4095.0f); Ivf=(Iv/4095.0f);

Having one variable as a float will force C to do a floating-point divide.

For the HLS math library you need to be using C++, not C. This should be as simple as renaming all the files from "*.c" to "*.cpp", and changing any instances of "uintX" to "ap_uint<X>".

5 Replies

Highlighted

u4223374

Advisor

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-15-2016 07:12 AM

10,000 Views

Registered:
04-26-2015

That's 100% correct C behaviour. If you divide an integer by an integer, you get an integer. Integer division rounds towards zero, so if your expected value is less than 1, you'll just get zero.

Try this:

Iuf=(Iu/4095.0f); Ivf=(Iv/4095.0f);

Having one variable as a float will force C to do a floating-point divide.

For the HLS math library you need to be using C++, not C. This should be as simple as renaming all the files from "*.c" to "*.cpp", and changing any instances of "uintX" to "ap_uint<X>".

Highlighted

joseer

Voyager

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-15-2016 07:40 AM

5,320 Views

Registered:
07-06-2016

Many thanks, it worked.

Best regards.

Highlighted

herver

Xilinx Employee

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-15-2016 01:38 PM

5,305 Views

Registered:
08-17-2011

...short Iu, short *Ialpha, float Iuf, Iuf=(Iu/4095); *Ialpha =(short) (Iuf * 32768);

as @u4223374 rightfully pointed to you the issue and the floating point computation will give you the correct result.

However for this testcase, isn't "*Ialpha=Iu/4095*32768" mostly equivalent to *Ialpha=Iu*8 for most small values and you don't really need to use floating points but just a shift by 3?

if you care about really 8.001953601953602 (which makes a difference for large numbers over 1000) then what about 32766/4096 simplified as 4097/512- once again the usual programming tricks "multiply and shift" is easier than full divide. Moreover, multiply by 4097 is not even a difficult multiplication, that's just shift and add too.

i hope this makes some sense ;-)

- Hervé

SIGNATURE:

* New Dedicated Vivado HLS forums* http://forums.xilinx.com/t5/High-Level-Synthesis-HLS/bd-p/hls

* Readme/Guidance* http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

* Please mark the Answer as "Accept as solution" if information provided is helpful.

* Give Kudos to a post which you think is helpful and reply oriented.

SIGNATURE:

* New Dedicated Vivado HLS forums* http://forums.xilinx.com/t5/High-Level-Synthesis-HLS/bd-p/hls

* Readme/Guidance* http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

* Please mark the Answer as "Accept as solution" if information provided is helpful.

* Give Kudos to a post which you think is helpful and reply oriented.

Highlighted

u4223374

Advisor

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-19-2016 01:30 AM

5,246 Views

Registered:
04-26-2015

Regarding @herver's point:

In certain cases, HLS will even do it automatically:

#include "ap_int.h" ap_uint<5> runDivision(ap_uint<8> x) { ap_uint<5> result = x/5; return result; }

Produced HDL code:

module runDivision (

ap_start,

ap_done,

ap_idle,

ap_ready,

x_V,

ap_return

);

parameter ap_const_lv18_19A = 18'b110011010;

parameter ap_const_lv32_B = 32'b1011;

parameter ap_const_lv32_F = 32'b1111;

input ap_start;

output ap_done;

output ap_idle;

output ap_ready;

input [7:0] x_V;

output [4:0] ap_return;

wire [7:0] mul_fu_30_p0;

wire [17:0] mul_fu_30_p2;

wire [17:0] mul_fu_30_p00;

assign ap_done = ap_start;

assign ap_idle = 1'b1;

assign ap_ready = ap_start;

assign ap_return = {{mul_fu_30_p2[ap_const_lv32_F : ap_const_lv32_B]}};

assign mul_fu_30_p0 = mul_fu_30_p00;

assign mul_fu_30_p00 = x_V;

assign mul_fu_30_p2 = (mul_fu_30_p0 * $signed('h19A));

endmodule //runDivision

(using a total of zero LUTs, zero FFs, one DSP48).

And, simplified:

module runDivision ( x, ap_return ); input [7:0] x; output [4:0] ap_return; wire [17:0] mulOut; assign mulOut = (x * $signed('h19A)); assign ap_return = mulOut[15 : 11]; endmodule //runDivision

Presumably HLS has calculated that this will guarantee correct outputs for every valid input - which is a pretty nifty thing for the software to do all by itself. Some Xilinx engineer must have been pretty pleased with himself/herself after getting that working.

Unfortunately, for a much more basic situation (converting a multiply by 4097 into a shift and add) HLS does not seem to be quite so smart. It'll default to using a DSP slice for any multiplication unless it's multiplying by a constant power of two - even, as I've found, when both inputs are only 2-bit wide. The RESOURCE directive provides a suitable workaround (with core Mul_LUT) and presumably this does actually get optimised as appropriate.

Highlighted

joseer

Voyager

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-19-2016 04:59 AM

5,234 Views

Registered:
07-06-2016

Thanks u4223374 and herver, yes it really makes sense, you are right about the conversion, but in this case being Iu an ADC input, I did this conversion just to check the right voltage values given by the external hardware, as a debug purposes.

Indeed on the final code that will be optimized.

Thanks again for the help.

Best regards.