Main Content

Reduce Area by Sharing Multipliers in a Symmetric FIR Filter

R2026b

This example shows how to use the resource sharing optimization in HDL Coder™ to reduce hardware area by sharing multipliers in a MATLAB® design that implements a symmetric FIR filter.

Resource sharing maps N functionally equivalent multipliers to a single multiplier that operates at N times the base clock rate. You control the number of shared multipliers by setting the ResourceSharing property on the HDL configuration object. This optimization trades increased clock rate for decreased area.

Without resource sharing, each of the four multipliers in the symmetric FIR filter design occupies dedicated hardware resources. With resource sharing enabled, HDL Coder time-multiplexes a single multiplier at a faster clock rate.

Examine the MATLAB Design and Test Bench

Set up the MATLAB function and test bench for this example. In the MATLAB Command Window, enter:

mlhdlc_demo_setup("mlhdlc_sharing");
This command opens a temporary working folder with the files required to run this example. The folder includes the:

  • MATLAB function

  • Test bench

  • mlhdlc_sharing_runme.m script, which includes the commands to generate HDL code with resource sharing

The MATLAB function, mlhdlc_sharing, models a symmetric FIR filter with eight persistent delay states, four symmetric additions, and four multiplications. On each call, the function shifts input samples through the delay line, computes symmetric sums of paired delay elements, and multiplies each sum by a filter coefficient. To view the function, enter:

open mlhdlc_sharing.m;

The test bench, mlhdlc_sharing_tb, generates a noise-modulated cosine input signal and passes 2001 samples through the filter. To view the test bench, enter:

open mlhdlc_sharing_tb.m;

Simulate the Design

To check for run-time errors, simulate the design by running the test bench. In the MATLAB Command Window, enter:

mlhdlc_sharing_tb;

Generate HDL Code

Specify the design name and test bench and create fixed-point and HDL configuration objects.

designName = "mlhdlc_sharing";
designTB = "mlhdlc_sharing_tb";

fixptCfg = coder.config("fixpt");
fixptCfg.TestBenchName = designTB;

cfg = coder.config("hdl");
cfg.TestBenchName = designTB;

Run the floating-point to fixed-point conversion and generate HDL code:

codegen("-float2fixed", "fixptCfg", "-config", "cfg", designName, ...
    "-launchreport");

After code generation completes, the report opens. Examine the Resource Report. The Resource Report shows 4 multipliers.

Generate HDL Code with Resource Sharing

To share multipliers, the multipliers must be functionally equivalent and require uniform numeric types. Use the fixed-point configuration object to add data type specifications to ensure all internal variables have the same numeric type.

signed = 1;
wordLength = 14;
fractionLength = 12;
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u1", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u2", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u3", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u4", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u5", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u6", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u7", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "u8", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "a1", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "a2", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "a3", ...
    numerictype(signed, wordLength, fractionLength));
fixptCfg.addTypeSpecification("mlhdlc_sharing", "a4", ...
    numerictype(signed, wordLength, fractionLength));

Next, to reduce the number of multipliers, enable resource sharing by setting the ResourceSharing HDL configuration object property to 4 and generate HDL code. This maps the four equivalent multipliers to a single multiplier that operates at four times the base clock rate.

cfg.ResourceSharing = 4;
codegen("-float2fixed", "fixptCfg", "-config", "cfg", designName, ...
    "-launchreport");

After code generation completes, the report opens. Examine the Resource Report. The Resource Report shows 1 multiplier instead of 4.

HDL Resource Utilization Report showing 4 multipliers before resource sharing and 1 multiplier after resource sharing

Compare Design Architectures

Without resource sharing, each multiplier occupies dedicated hardware resources. This image shows four separate multipliers.

Block diagram of the symmetric FIR filter without resource sharing. Four separate multipliers (h1 through h4) each receive one pair of symmetric delay-line sums and produce independent products that feed into an adder tree to compute the filter output.

With resource sharing enabled, HDL Coder implements a time-multiplexed architecture. The inputs to the shared multiplier are multiplexed at four times the base clock rate, shown in red. The outputs are routed to the respective consumers at the base rate, shown in green.

Block diagram of the symmetric FIR filter with resource sharing enabled. A single shared multiplier receives time-multiplexed inputs at 4x clock rate (shown in red) and routes outputs to the four original consumers at the base rate (shown in green).

See Also

| |

Topics