HDL Coder

Resource Sharing For Area Optimization

This example shows how to use the subsystem level sharing optimization in HDL Coder.

Introduction

Sharing is a subsystem-level optimization supported by HDL Coder for implementing area-efficient hardware.

By default, the coder implements hardware that is a 1-to-1 mapping of Simulink blocks to hardware module implementations. The resource sharing optimization enables users to share hardware resources by enabling an N-to-1 mapping of 'N' functionally-equivalent Simulink blocks to a single hardware module. The user specifies 'N' using the 'SharingFactor' implementation parameter.

Consider the following symmetric FIR filter model. It contains 4 product blocks that are functionally equivalent and which map to 4 multipliers in hardware. The Resource Utilization Report lists the hardware resources used.

bdclose all;
load_system('sfir_fixed');
open_system('sfir_fixed/symmetric_fir');
hdlset_param('sfir_fixed', 'ResourceReport', 'on');
makehdl('sfir_fixed/symmetric_fir');
### Generating HDL for 'sfir_fixed/symmetric_fir'.
### Starting HDL check.
### Begin VHDL Code Generation for 'sfir_fixed'.
### Working on sfir_fixed/symmetric_fir as hdlsrc/sfir_fixed/symmetric_fir.vhd.
### Generating HTML files for code generation report in /tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/sfir_fixed/html/sfir_fixed directory...
### Creating HDL Code Generation Check Report file:////tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/sfir_fixed/symmetric_fir_report.html
### HDL check for 'sfir_fixed' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

Sharing to Realize an N-to-1 Mapping

To reduce area resources, you can invoke the sharing optimization by setting the 'SharingFactor' parameter on the subsystem to a positive integer value. This parameter specifies 'N' in the N-to-1 hardware mapping. In this example, there are 4 product blocks, so generating HDL with 'SharingFactor' set to 4 generates HDL with 1 multiplier.

The code generation model reflects the sharing architecture. The inputs to the shared blocks are time-multiplexed over the shared resource at a faster rate (in this case 4x faster, shown in red). The outputs are then routed to the respective consumers at a slower rate (shown in green).

hdlset_param('sfir_fixed/symmetric_fir', 'SharingFactor', 4);
hdlset_param('sfir_fixed', 'GenerateValidationModel', 'on');
makehdl('sfir_fixed/symmetric_fir');
open_system('gm_sfir_fixed/symmetric_fir');
set_param('gm_sfir_fixed', 'SimulationCommand', 'update');
### Generating HDL for 'sfir_fixed/symmetric_fir'.
### Starting HDL check.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 0: 1 cycles.
### Output port 1: 1 cycles.
### Generating new validation model: <a href="matlab:open_system('gm_sfir_fixed_vnl')">gm_sfir_fixed_vnl</a>.
### Validation model generation complete.
### Begin VHDL Code Generation for 'sfir_fixed'.
### MESSAGE: The design requires 4 times faster clock with respect to the base rate = 1.
### Working on mux1_serializer as hdlsrc/sfir_fixed/mux1_serializer.vhd.
### Working on mux1_serializer1 as hdlsrc/sfir_fixed/mux1_serializer1.vhd.
### Working on m40_deserializer as hdlsrc/sfir_fixed/m40_deserializer.vhd.
### Working on symmetric_fir_tc as hdlsrc/sfir_fixed/symmetric_fir_tc.vhd.
### Working on sfir_fixed/symmetric_fir as hdlsrc/sfir_fixed/symmetric_fir.vhd.
### Generating package file hdlsrc/sfir_fixed/symmetric_fir_pkg.vhd.
### Generating HTML files for code generation report in /tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/sfir_fixed/html/sfir_fixed directory...
### Creating HDL Code Generation Check Report file:////tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/sfir_fixed/symmetric_fir_report.html
### HDL check for 'sfir_fixed' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

The sharing optimization is implemented using time-division multiplexing. Simulink requires the outputs of the shared resource to be sampled at the predefined sample rate, so HDL Coder overclocks the shared resource at a faster rate than the data rate. In the above example, the shared architecture, which includes the shared resource, multiplexer-serializer at the inputs and demultiplexer-deserializer at the outputs, operates at 4 times the rate of the input data, because 'Sharingfactor' = 4. In general an N-way shared resource results in N times overclocking.

To learn how to limit the degree of overclocking implemented by sharing, see the Sharing with Oversampling Constraints example.

Delay Balancing and Functional Equivalence

The rate transitions that implement time-multiplexing in the resource sharing architecture introduce additional latency. To maintain functional equivalence, delay balancing automatically inserts matching delays in parallel merging paths. See the Delay Balancing and Validation Model Workflow In HDL Coder™ example for more details. The generated validation model allows the user to verify functional equivalence by comparing the operation of the shared hardware architecture with the original model.

sim('gm_sfir_fixed_vnl');
open_system('gm_sfir_fixed_vnl/Compare/Assert_y_out/compare: y_out')
open_system('gm_sfir_fixed_vnl/Compare/Assert_delayed_xout/compare: delayed_xout')

Block Support, Atomic Subsystems and Extensions

HDL Coder supports resource sharing of 4 block types: Product, Gain, Atomic Subsystem, and MATLAB Function.

Sharing functionally equivalent Product and Gain blocks means that the multipliers in the HDL implementation will be shared. Two Product blocks are functionally equivalent if: a) the data types of their inputs and outputs are identical, b) their block parameter settings are identical, and c) their HDL block properties are identical. For a Gain block, functional equivalence additionally requires that the constant value and data types are also identical. However, if the gain constant data types are identical for two Gain blocks with different gain constant values, HDL Coder can share them. Similarly, if a Gain block can be implemented as a Product block with constant input, and it has the same data types as another Product block in the design, the coder can share them.

The third block type, Atomic Subsystem, is useful for sharing functionally equivalent islands of logic encapsulated inside atomic subsystems. Two atomic subsystems are functionally equivalent and can be shared if: a) their Simulink checksums are identical (see Simulink.SubSystem.getChecksumSimulink.SubSystem.getChecksum for more details), and b) their HDL block properties are identical.

The fourth block type, MATLAB Function block, can be shared if it is stateless. A MATLAB Function block is stateless if it does not contain persistent variables, or if its persistent variables are not updated in one call to the function and read on a subsequent call. If you only want to share multipliers within a single MATLAB Function block, you can set its SharingFactor block property.

Sharing Atomic Subsystems

% The following example demonstrates an audio filtering model that applies
% the same filter on the left and right channels. By default, HDL Coder
% generates two filter modules in hardware.
bdclose all;
load_system('hdlcoder_audiofiltering');
open_system('hdlcoder_audiofiltering/Audio filter');

% The filters on the two audio channels can be shared by specifying a
% 'SharingFactor' value of 2 on the encompassing subsystem. This generates
% an architecture that uses only one filter, as shown below.
hdlset_param('hdlcoder_audiofiltering/Audio filter', 'SharingFactor', 2);
makehdl('hdlcoder_audiofiltering/Audio filter');
open_system('gm_hdlcoder_audiofiltering/Audio filter');
set_param('gm_hdlcoder_audiofiltering', 'SimulationCommand', 'update');
### Generating HDL for 'hdlcoder_audiofiltering/Audio filter'.
### Starting HDL check.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 0: 1 cycles.
### Output port 1: 1 cycles.
### Begin VHDL Code Generation for 'hdlcoder_audiofiltering'.
### MESSAGE: The design requires 2 times faster clock with respect to the base rate = 0.00012207.
### Working on hdlcoder_audiofiltering/Audio filter/Filter_left as hdlsrc/hdlcoder_audiofiltering/Filter_left.vhd.
### Working on mux1_serializer as hdlsrc/hdlcoder_audiofiltering/mux1_serializer.vhd.
### Working on Filter_left0_deserializer as hdlsrc/hdlcoder_audiofiltering/Filter_left0_deserializer.vhd.
### Working on Audio filter_tc as hdlsrc/hdlcoder_audiofiltering/Audio_filter_tc.vhd.
### Working on hdlcoder_audiofiltering/Audio filter as hdlsrc/hdlcoder_audiofiltering/Audio_filter.vhd.
### Generating package file hdlsrc/hdlcoder_audiofiltering/Audio_filter_pkg.vhd.
### Creating HDL Code Generation Check Report file:////tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/hdlcoder_audiofiltering/Audio_filter_report.html
### HDL check for 'hdlcoder_audiofiltering' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

Opportunities Across Hierarchies

Since 'SharingFactor' is a subsystem-level parameter, different subsystems at different levels of the hierarchy can specify different sharing values. In the audio filter example, the filters on each channel use 3 gain blocks respectively.

open_system('hdlcoder_audiofiltering/Audio filter/Filter_left');

Sharing at Higher Level of Hierarchy

We can specify a 'SharingFactor' value of 2 at the top-level of the DUT to share the filters on the two channels. Additionally, we can specify a 'SharingFactor' value of 3 on each of the filter subsystems to enable sharing of the 3 gain blocks in each channel. When HDL code is now generated, notice first that the left and right filters have been shared and we have only one filter at the top-level of the hierarchy.

hdlset_param('hdlcoder_audiofiltering/Audio filter', 'SharingFactor', 2);
hdlset_param('hdlcoder_audiofiltering/Audio filter/Filter_left', 'SharingFactor', 3);
hdlset_param('hdlcoder_audiofiltering/Audio filter/Filter_right', 'SharingFactor', 3);
makehdl('hdlcoder_audiofiltering/Audio filter');
open_system('gm_hdlcoder_audiofiltering/Audio filter');
set_param('gm_hdlcoder_audiofiltering', 'SimulationCommand', 'update');
### Generating HDL for 'hdlcoder_audiofiltering/Audio filter'.
### Starting HDL check.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 0: 2 cycles.
### Output port 1: 2 cycles.
### Begin VHDL Code Generation for 'hdlcoder_audiofiltering'.
### MESSAGE: The design requires 6 times faster clock with respect to the base rate = 0.00012207.
### Working on mux1_serializer as hdlsrc/hdlcoder_audiofiltering/mux1_serializer.vhd.
### Working on mux1_serializer1 as hdlsrc/hdlcoder_audiofiltering/mux1_serializer1.vhd.
### Working on b_1_0_deserializer as hdlsrc/hdlcoder_audiofiltering/b_1_0_deserializer.vhd.
### Working on hdlcoder_audiofiltering/Audio filter/Filter_left as hdlsrc/hdlcoder_audiofiltering/Filter_left.vhd.
### Working on mux1_serializer_block as hdlsrc/hdlcoder_audiofiltering/mux1_serializer_block.vhd.
### Working on Filter_left0_deserializer as hdlsrc/hdlcoder_audiofiltering/Filter_left0_deserializer.vhd.
### Working on Audio filter_tc as hdlsrc/hdlcoder_audiofiltering/Audio_filter_tc.vhd.
### Working on hdlcoder_audiofiltering/Audio filter as hdlsrc/hdlcoder_audiofiltering/Audio_filter.vhd.
### Generating package file hdlsrc/hdlcoder_audiofiltering/Audio_filter_pkg.vhd.
### Creating HDL Code Generation Check Report file:////tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/hdlcoder_audiofiltering/Audio_filter_report.html
### HDL check for 'hdlcoder_audiofiltering' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

Sharing at Lower Level of Hierarchy

Additionally, the 3 gain blocks in the lower of the hierarchy (within the filter subsystem) have also been shared. The net result is that we have reduced the resource usage from 6 multipliers to just one.

open_system('gm_hdlcoder_audiofiltering/Audio filter/Filter_left');
set_param('gm_hdlcoder_audiofiltering', 'SimulationCommand', 'update');

Combining Optimizations and Sharing

Resource sharing can also be combined with other optimizations like streaming.

Consider the model below: it contains a 24-element vector datapath and 3 vector gain blocks, which will map to 72 multipliers, by default. Streaming can scalarize the vector datapath while sharing can share the 3 gain blocks.

bdclose all;
load_system('hdl_areaopt1');
open_system('hdl_areaopt1/Controller');
set_param('hdl_areaopt1', 'SimulationCommand', 'update');

Streaming and Sharing Reduce the Design to Use One Multiplier

To invoke both optimizations, we set 'StreamingFactor' to 24 and 'SharingFactor' to 3. The former will reduce the number of multipliers from 72 to 3, and the latter reduces the 3 scalar multipliers to 1.

hdlset_param('hdl_areaopt1/Controller', 'StreamingFactor', 24);
hdlset_param('hdl_areaopt1/Controller', 'SharingFactor', 3);
makehdl('hdl_areaopt1/Controller');
open_system('gm_hdl_areaopt1/Controller');
set_param('gm_hdl_areaopt1', 'SimulationCommand', 'update');




% LocalWords:  xout getchecksum
### Generating HDL for 'hdl_areaopt1/Controller'.
### Starting HDL check.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 0: 2 cycles.
### Begin VHDL Code Generation for 'hdl_areaopt1'.
### MESSAGE: The design requires 72 times faster clock with respect to the base rate = 2.
### Working on err_d_serializercomp as hdlsrc/hdl_areaopt1/err_d_serializercomp.vhd.
### Working on Saturation_out1_serialcomp as hdlsrc/hdl_areaopt1/Saturation_out1_serialcomp.vhd.
### Working on kconst_serializercomp as hdlsrc/hdl_areaopt1/kconst_serializercomp.vhd.
### Working on mux1_serializer as hdlsrc/hdl_areaopt1/mux1_serializer.vhd.
### Working on P0_deserializer as hdlsrc/hdl_areaopt1/P0_deserializer.vhd.
### Working on Controller_tc as hdlsrc/hdl_areaopt1/Controller_tc.vhd.
### Working on hdl_areaopt1/Controller as hdlsrc/hdl_areaopt1/Controller.vhd.
### Generating package file hdlsrc/hdl_areaopt1/Controller_pkg.vhd.
### Generating HTML files for code generation report in /tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/hdl_areaopt1/html/hdl_areaopt1 directory...
### Creating HDL Code Generation Check Report file:////tmp/BR2014bd_145981_71764/tpdfa8be6b_8422_4ece_a70d_403b684ee32c/hdlsrc/hdl_areaopt1/Controller_report.html
### HDL check for 'hdl_areaopt1' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.