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!

AR# 55127

Description

In my HLS design, I am trying to do a simple 17 by 42 bit multiplication where I expect the XST tools to produce 2 DSPs.

However, I am getting 4 DSPs.

How can I accomplish 2 DSP multiplication?

Solution

The following code snippet is an example of how to do a wide mult using the minimum number of DSPs for the best timing performance.

This would take place of a simple A = B*C multiplication.

#include "wide_mult.h"
// Uncomment to do mult with a single '*' operator
//#define USE_OPERATOR
// Uncomment this and run 'csim' to see that without casting upper product
// before shift design doesn't work correctly, because the expression
// 'tmp_a * y' has a width of (A_TOTAL_WIDTH + (B_TOTAL_WIDTH - 17)) = 42
// which is not adjusted to the necessary 59 bits before the LSH operation,
// (due to C semantics). This behavior is documented on pp 334-335 of UG902.
//#define NOCAST_FAULT

void wide_mult(in_a_t in_a, in_b_t in_b, out_p_t& out_p)
{
#ifndef USE_OPERATOR
ap_uint<17> x = in_b.range(16,0);
ap_int<B_TOTAL_WIDTH - 17> y = in_b.range(B_TOTAL_WIDTH - 1, 17);// >> 17;
// effectively cast bits of in_a to an integer - does not affect ap_int<> case
ap_int<A_TOTAL_WIDTH> tmp_a = in_a.range(A_TOTAL_WIDTH -  1, 0);
#ifndef NOCAST_FAULT // cast below is necessary to ensure msbs are not lost during shift
ap_int<P_TOTAL_WIDTH> tmp_p = tmp_a * x + (ap_int<P_TOTAL_WIDTH>(tmp_a * y) << 17);
#else
ap_int<P_TOTAL_WIDTH> tmp_p = tmp_a * x + (/*ap_int<P_TOTAL_WIDTH>*/(tmp_a * y) << 17);
#endif
// Effectively casts the integer product back into fixed point
// n.b. For ap_fixed<> I/O for this simple case the widths (W & IW; total and
// integer) were chosen to be the natural product width, i.e. the sum of the
// operand widths. For cases where the product widths are not simply the sum
// of the operand widths, scaling (shifting) of tmp_p before assigning to
// out_p.range() may be necessary.
out_p.range(P_TOTAL_WIDTH - 1,0) = tmp_p;
#else
out_p = in_a * in_b;
#endif
}

AR# 55127
Date 03/05/2015
Status Active
Type General Article
Devices
• Spartan-6
Page Bookmarked