User manual
Tutorial: Using the logic estimator
To simplify the Handel-C code required to implement this adder tree, we will declare a 2-dimensional
array, as wide and deep as the adder tree required for the specified number of taps in the FIR filter. This
can be pictured as below:
reg reg reg reg reg reg reg reg
regregregregregregregreg
regregregregregregregreg
regregregregregregregreg
REPRESENTATION OF ADDER TREE IN HANDEL-C HARDWARE
The adder tree above has redundant logic, as only some of the adders and registers have valid data
entering them - these are shaded. The logic which is not shaded is redundant, and when DK is compiling
this code for EDIF, the optimization stages will remove the redundant logic. Relying on the optimizer to
do this allows you to write simpler Handel-C code; the code for the adder tree is shown below:
macro expr TreeElements = ((Taps + 1) / 2) + (((Taps + 1) / 2) % 2);
macro expr TreeDepth = log2ceil(Taps);
// load the first layer of adder tree with multiplier results
par(i = 0; i < NumberMults; i++)
{
AddTreeRegs[0][i] = FirPtr->Coeffs[i] * adjs(AddLayer[i],ResultWidth);
}
// perform all additions in adder tree
par(i = 1; i < (TreeDepth); i++)
{
par(j = 0; j < TreeElements; j += 2)
{
AddTreeRegs[i][j / 2] = AddTreeRegs[i-1][j] + AddTreeRegs[i-1][j + 1];
}
}
// Send output of adder tree out of the FIR filter
FirPtr->Output = AddTreeRegs[TreeDepth-1][0];
In the code above, the macro expressions are used to determine the depth and width of the adder tree
"rectangle", allowing for odd and even numbers of inputs. The first layer of the adder tree is loaded with
the results of the multipliers. There are then two nested replicated
par{} blocks, which index through
the depth and with of the rectangle of adder tree registers, producing the hardware shown in the diagram
above. The final result comes from the last layer in the rectangle, from the right-most element, as shown
in the diagram above.
www.celoxica.com
Page 121