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
1,030 Views
Registered: ‎11-11-2015

Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Dear all,

I am trying to implement a moving average filter in HLS. I have already
developed the Matlab model in fixed point and the Fixed point model is
developed with the help of fi & fimath functions present in matlab in the
following manner.

 

fi(data, signedness(T/F),DataWidth,FractionWidth,'fimath',F); where
F  =     fimath('OverflowAction','Saturate','RoundingMethod','Nearest'); 

Similarly I have coded the algorithm in cpp for the correspoding HLS design
with the following fixed point format

ap_fixed<DataWidth,IntegerWidth, AP_RND, AP_SAT>

using AP_RND for rounding and AP_SAT for saturation ( which I believe
corresponds to the Rounding and Overflow method I used in Matlab).

When I compare the results of Matlab and HLS cpp , I find that in case of
addition , substraction and multiplication the results matches bittrue but
when I perform division (/) which is not a power of 2, the results are very
similar but not bittrue.

I would like to know if the mismatch in fixed point division of HLS and Matlab
is a known issue or else something is wrong in the way I am doing the
computation..

Thanks in advance

Regards

0 Kudos
1 Solution

Accepted Solutions
Xilinx Employee
Xilinx Employee
801 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

@rcst201427420m,

Couple of ideas for workarounds - the obvious one, if you're okay with switching the rounding mode: just make Matlab truncate the result.

If you require rounding to positive infinity, do the division with one extra bit, then cast to the proper type in a separate step. I've tested it with the example numbers you provided, and it seems to work, but I only have the one data point. You should double check it with your testbench.

typedef ap_fixed<30,11,AP_RND,AP_SAT> ACC_T_PLUS_ONE_BIT;
...
    ACC_T_PLUS_ONE_BIT acc_new = acc;
    ACC_T mov_avg_val = acc_new/15;
...
	ap_int<30> test = acc_new.range(29,0);
    cout << "acc = " << acc_new.to_double() << " or 0x" << hex << test << endl;
Nicholas Moellers

Xilinx Worldwide Technical Support
10 Replies
Xilinx Employee
Xilinx Employee
978 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hey @rcst201427420m,

I'm curious if you could tell us more about the nature of the mismatch.

It's not necessarily an issue that the two results are different if they're still correct. But I am having trouble wrapping my mind around how we could have a difference when - at least on the HLS side - It can be thought of as integer division and keeping track of the decimal. Actually, that is a possible reason for the discrepancy: If Matlab uses floating point division under the hood, that would make sense.

Just double checking - you are properly casting your literals to the fixed point type? I.e., ap_fixed<W,I> a = (ap_fixed<W,I>) 0.25;

 

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos
Scholar u4223374
Scholar
964 Views
Registered: ‎04-26-2015

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

It's possible that Xilinx and Mathworks are using slightly different definitions - in particular, should "round to nearest" with -0.5 give you -1.0 or 0.0? Depends whether you round by magnitude or not.

 

As @nmoeller has said, if you can provide an example where they differ and provide the full binary/hex string for each, it should be easy to check - even doing binary division by hand is not all that difficult unless you're working with hundreds of bits.

0 Kudos
957 Views
Registered: ‎11-11-2015

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hi Nicholas & @u4223374,

Thanks for your reply. Please find the code snipped in the attachment section. One image shows what is happening on the HLS side while the other shows what happens in Matlab side. The values of HLS variable mov_avg_val should be same as Matlab variable stdFilter_Scale_fi but the results differ slightly.The images will provide more information about the mismatch.

I must add that not all the values are different . While I am performing this division operation some values match bittrue with the matlab  results and some values does not match , like the one shown in the example. 

Looking forward to your response.

Regards

Bhaskar

HLS_part_new.png
Matlab_part.png
0 Kudos
Xilinx Employee
Xilinx Employee
920 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

@rcst201427420m,

ap_fixed data types should be casted to double using their to_double() member function. Shouldn't be an issue, but we should eliminate the possibility:

cout << ... << mov_avg_val.to_double() << endl;
cout << ... << acc.to_double() << endl;

But also, to check if your values are "bittrue", you should be checking the bit representation of the ap_fixed data types, not the floating point representation of the ap_fixed number. Something like the following, stolen from this forum post should be what you want on the HLS side:

ap_uint<29> Result=0;
Result = mov_avg_val.range(28,0);
cout << hex << Result << " ";

I would recommend you print mov_avg_val, acc, and also save the value WINDOW_LEN-1 as a fixed type, so we can see all the binary numbers involved in the division. Otherwise, I'd be inclined to blame integer to floating point conversion.

@u4223374 - It looks like both Matlab and HLS are set to round to positive infinity.

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos
835 Views
Registered: ‎11-11-2015

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hi Nicholas,

Thanks for your support. I have made the changes that you recommended. Please find the code snipped and the result in the attachment section. It seems the hex value of the result in HLS side still differs from matlab. Is there a way , I can get both the HLS and matlab output to be the same for this division??

And finally, Wish you a very Happy New Year.

Regards

Bhaskar

 

HLS_Merged.png
MatlabMerged.png
0 Kudos
Xilinx Employee
Xilinx Employee
808 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hey @rcst201427420m,

Happy New Year!

I've got good news and bad news. The good news is that we can now divide out 0x14df38 by 0xf by hand and see what the answer should be. Answer: 0x16436 with a remainder of 0xe or 0b1110. Hardware would only calculate the MSB of this which is 1. The definition of the AP_RND quantization mode is "round to positive infinity", or more specifically, add the MSB of the remainder to the number. Which should give us 0x16437, which is the answer that Matlab gave. Which brings us to the bad news, which is it looks to me like you've found a rounding bug in HLS fixed point division. But maybe that now gets us some more good news, which is now this can be reported to the engineering team.

Thanks for finding and reporting this issue.

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos
Xilinx Employee
Xilinx Employee
802 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

@rcst201427420m,

Couple of ideas for workarounds - the obvious one, if you're okay with switching the rounding mode: just make Matlab truncate the result.

If you require rounding to positive infinity, do the division with one extra bit, then cast to the proper type in a separate step. I've tested it with the example numbers you provided, and it seems to work, but I only have the one data point. You should double check it with your testbench.

typedef ap_fixed<30,11,AP_RND,AP_SAT> ACC_T_PLUS_ONE_BIT;
...
    ACC_T_PLUS_ONE_BIT acc_new = acc;
    ACC_T mov_avg_val = acc_new/15;
...
	ap_int<30> test = acc_new.range(29,0);
    cout << "acc = " << acc_new.to_double() << " or 0x" << hex << test << endl;
Nicholas Moellers

Xilinx Worldwide Technical Support
773 Views
Registered: ‎11-11-2015

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hi Nicholas,

Thanks for your reply. I tried your second solution. It worked for all the values in my test vector.

Thanks !!

Regards

Bhaskar

0 Kudos
Xilinx Employee
Xilinx Employee
758 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hey @rcst201427420m,

That's awesome, glad to hear it!

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos
Xilinx Employee
Xilinx Employee
705 Views
Registered: ‎09-05-2018

Re: Xilinx HLS fixed point division vs Matlab fixed point division

Jump to solution

Hey @rcst201427420m,

For what it's worth, I've been informed that the tool is behaving per spec when it truncates the result of the division.

So really that just means that my "workaround" is actually just the recommended way to do division with rounding, i.e., use one extra bit and then cast.

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos