UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Explorer
Explorer
5,124 Views
Registered: ‎07-06-2016

float operation gives 0

Jump to solution

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.

0 Kudos
1 Solution

Accepted Solutions
Scholar u4223374
Scholar
9,788 Views
Registered: ‎04-26-2015

Re: float operation gives 0

Jump to solution

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>".

0 Kudos
5 Replies
Scholar u4223374
Scholar
9,789 Views
Registered: ‎04-26-2015

Re: float operation gives 0

Jump to solution

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>".

0 Kudos
Explorer
Explorer
5,109 Views
Registered: ‎07-06-2016

Re: float operation gives 0

Jump to solution

Many thanks, it worked.

Best regards.

0 Kudos
Xilinx Employee
Xilinx Employee
5,094 Views
Registered: ‎08-17-2011

Re: float operation gives 0

Jump to solution
...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.
0 Kudos
Scholar u4223374
Scholar
5,035 Views
Registered: ‎04-26-2015

Re: float operation gives 0

Jump to solution

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.

 

 

0 Kudos
Explorer
Explorer
5,023 Views
Registered: ‎07-06-2016

Re: float operation gives 0

Jump to solution

Thanks 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.

0 Kudos