Distributed Arithmetic (DA) is a widely used technique for implementing sum-of-products computations without the use of multipliers. Designers frequently use DA to build efficient Multiply-Accumulate Circuitry (MAC) for filters and other DSP applications.
The main advantage of DA is its high computational efficiency. DA distributes multiply and accumulate operations across shifters, lookup tables (LUTs), and adders in such a way that conventional multipliers are not required.
The coder supports DA in HDL code generated for several single-rate and multirate FIR filter structures for fixed-point filter designs. (See Requirements and Considerations for Generating Distributed Arithmetic Code. )
This section briefly summarizes of the operation of DA. Detailed discussions of the theoretical foundations of DA appear in the following publications:
Meyer-Baese, U., Digital Signal Processing with Field Programmable Gate Arrays, Second Edition, Springer, pp 88–94, 128–143.
White, S.A., Applications of Distributed Arithmetic to Digital Signal Processing: A Tutorial Review. IEEE ASSP Magazine, Vol. 6, No. 3.
In a DA realization of a FIR filter structure, a sequence of
input data words of width
W is fed through a parallel
to serial shift register. This feedthrough produces a serialized stream
of bits. The serialized data is then fed to a bit-wide shift register.
This shift register serves as a delay line, storing the bit serial
The delay line is tapped (based on the input word size
to form a
W-bit address that indexes into a lookup
table (LUT). The LUT stores the possible sums of partial products
over the filter coefficients space. A shift and adder (scaling accumulator)
follow the LUT. This logic sequentially adds the values obtained from
A table lookup is performed sequentially for each bit (in order of significance starting from the LSB). On each clock cycle, the LUT result is added to the accumulated and shifted result from the previous cycle. For the last bit (MSB), the table lookup result is subtracted, accounting for the sign of the operand.
This basic form of DA is fully serial, operating on one bit
at a time. If the input data sequence is
wide, then a FIR structure takes
W clock cycles
to compute the output. Symmetric and asymmetric FIR structures are
an exception, requiring
W+1 cycles, because one
additional clock cycle is required to process the carry bit of the
The inherently bit serial nature of DA can limit throughput.
To improve throughput, the basic DA algorithm can be modified to compute
more than one bit-sum at a time. The number of simultaneously computed
bit sums is expressed as a power of two called the DA radix.
For example, a DA radix of 2 (
2^1) indicates that
a one bit-sum is computed at a time. A DA radix of 4 (
indicates that a two bit-sums are computed at a time, and so on.
To compute more than one bit-sum at a time, the coder replicates the LUT. For example, to perform DA on two bits at a time (radix 4), the odd bits are fed to one LUT and the even bits are simultaneously fed to an identical LUT. The LUT results corresponding to odd bits are left-shifted before they are added to the LUT results corresponding to even bits. This result is then fed into a scaling accumulator that shifts its feedback value by two places.
Processing more than one bit at a time introduces a degree of
parallelism into the operation, which can improve performance
at the expense of area. The
lets you specify the number of bits processed simultaneously in DA.
The size of the LUT grows exponentially with the order of the
filter. For a filter with
N coefficients, the LUT
2^N values. For higher-order filters,
LUT size must be reduced to reasonable levels. To reduce the size,
you can subdivide the LUT into several LUTs, called LUT
partitions. Each LUT partition operates on a different
set of taps. The results obtained from the partitions are summed.
For example, for a 160 tap filter, the LUT size is
W is the word size of the LUT data. You can
achieve a significant reduction in LUT size by dividing the LUT into
16 LUT partitions, each taking 10 inputs (taps). This division reduces
the total LUT size to
Although LUT partitioning reduces LUT size, the architecture uses more adders to sum the LUT data.
DALUTPartition property lets you specify
how the LUT is partitioned in DA.
The coder lets you control how DA code is generated using the
(or equivalent Generate HDL dialog box options). Before using these
properties, review the following general requirements, restrictions,
and other considerations for generation of DA code.
The coder supports DA in HDL code generated for the following single-rate and multirate FIR filter structures:
direct form (
direct form symmetric (
direct form asymmetric (
Generation of DA code is supported only for fixed-point filter designs.
The data path in HDL code generated for the DA architecture is optimized for full precision computations. The filter casts the result to the output data size at the final stage. If your filter object is set to use full precision data types, numeric results from simulating the generated HDL code are bit-true to the output of the original filter object.
If your filter object has customized word or fraction lengths, the generated DA code may produce numeric results that are different than the output of the original filter object.
DA ignores taps that have zero-valued coefficients and reduces the size of the DA LUT accordingly.
For symmetric and asymmetric FIR filters:
A bit-level preadder or presubtractor is required to add tap data values that have coefficients of equal value and/or opposite sign. One extra clock cycle is required to compute the result because of the additional carry bit.
The coder takes advantage of filter symmetry. This symmetry reduces the DA LUT size substantially, because the effective filter length for these filter types is halved.
Partitioned distributed arithmetic architectures implement internal
clock rates higher than the input rate. In such filter implementations,
N cycles (
N >= 2)
of the base clock for each input sample. You can specify how many
clock cycles the test bench holds the input data values in a valid
When you select Hold input data between
samples (the default), the test bench holds the input data
values in a valid state for
N clock cycles.
When you clear Hold input data between samples,
the test bench holds input data values in a valid state for only one
clock cycle. For the next
N-1 cycles, the test
bench drives the data to an unknown state (expressed as
until the next input sample is clocked in. Forcing the input data
to an unknown state verifies that the generated filter code registers
the input data only on the first cycle.
Two properties specify distributed arithmetic options to the
You can use the helper function
explore possible partitions and radix settings for your filter.
For examples, see
The Generate HDL dialog box provides several options related to DA code generation.
The Architecture pop-up menu, which lets you enable DA code generation and displays related options.
The Specify folding drop-down
menu, which lets you directly specify the folding factor, or set a
value for the
The Specify LUT drop-down menu,
which lets you directly set a value for the
You can also select an address width for the LUT.
If you specify an address width, the coder uses input LUTs as required.
The Generate HDL dialog box initially displays default DA-related
option values that correspond to the current filter design. For the
requirements for setting these options, see
To specify DA code generation using the Generate HDL dialog box, follow these steps:
Design a FIR filter (using Filter Designer, Filter Builder, or MATLAB® commands) that meets the requirements described in Requirements and Considerations for Generating Distributed Arithmetic Code.
Open the Generate HDL dialog box.
Distributed Arithmetic (DA) from
the Architecture pop-up menu.
When you select this option, the related Specify folding and Specify LUT options are displayed below the Architecture menu. The following figure shows the default DA options for a direct form FIR filter.
Select one of the following options from the Specify folding drop-down menu:
Folding factor (default):
Select a folding factor from the drop-down menu to the right of Specify
folding. The menu contains an exhaustive list of folding
factor options for the filter.
DA radix: Select the number
of bits processed simultaneously, expressed as a power of 2. The default
radix value is
2, specifying processing
of one bit at a time, or fully serial DA. If desired, set the
radix field to a nondefault value.
Select one of the following options from the Specify LUT drop-down menu:
Address width (default):
Select from the drop-down menu to the right of Specify LUT.
The menu contains an exhaustive list of LUT address widths for the
Partition: Select, or enter,
a vector specifying the number and size of LUT partitions.
Set other HDL options as required, and generate code. Invalid or illegal values for LUT Partition or DA Radix are reported at code generation time.
As you interact with the Specify folding and Specify
LUT options you can see the results of your choice in three
Total LUT size (bits).
In addition, when you click the View details hyperlink, the coder displays a report showing complete DA architectural details for the current filter, including:
Complete list of applicable folding factors and how they apply to the sets of LUTs
Tabulation of the configurations of LUTs with total LUT Size and LUT details
The following figure shows a typical report.
Distributed Arithmetic (DA) is
selected in the Architecture menu, some other
HDL options change automatically to settings that correspond to DA
Coefficient multipliers is set
Multiplier and disabled.
FIR adder style is set to
Add input register (in the Ports pane) is selected and disabled. (An input register, used as part of a shift register, is used in DA code.)
Add output register (in the Ports pane) is selected and disabled.