Main Content

Optimize Area Usage For Frame-Based Algorithms with Tall Array Inputs

This example shows how to generate area-efficient HDL code from a frame-based algorithm that has input data with significantly more rows than columns. This type of input data is common in audio and digital signal processing algorithms. You can use the frame-to-sample conversion optimization and adjust the order in which the input data is processed for your target hardware to reduce the amount of area needed for the algorithm. For more information on the frame-to-sample conversion optimization, see HDL Code Generation from Frame-Based Algorithms.

The Input processing order configuration parameter allows you to select the order in which the frame-to-sample optimization processes an incoming matrix. By selecting the input processing order, you can align the way your algorithm is processed with the type of hardware you are using or the application you are targeting. For example, if you have an input hardware sensor or an upstream component that requires the column-major ordering, you do not need to use an extra transpose. Similarly, if you have a digital signal processing algorithm that requires column-major ordering, you do not need to transpose the matrix to make the algorithm compatible with the frame-to-sample optimization.

Inspect the Model

For this example, the input data is daily data of average temperature over the course of 10 years, stored as 365 rows for each day by 10 columns for the 10 years. The algorithm calculates a moving average within each year, which requires computing the moving average along each column.

Load the input data inputTemp from the inputData.mat file.

load('inputData.mat');

Load the model and open the MATLAB Function block that contains the moving average algorithm.

mdl = 'moving_avg_col_major';
dut = [mdl '/DUT'];

load_system(mdl);
open_system([dut '/MATLAB Function'])
function out_data = movingAvgfcn(inp_data)
out_data = hdl.npufun(@kernelAdd, [5 1], inp_data);
end

function y = kernelAdd(x)
y = single(1/5)*sum(x(:), 'native');
end

The hdl.npufun function computes the moving average algorithm and is compatible with the frame-to-sample conversion optimization. You could also use the Neighboring Processing Subsystem block to apply the same algorithm and generate HDL code with the frame-to-sample optimization. For an example, see Generate HDL Code from Frame-Based Models by Using Neighborhood Modeling Methods.

Run Model and Plot Output

Run the model to save the output data to your MATLAB workspace as outputTemp.

sim(mdl)

Plot the first year of input temperature data against the output temperature data to see the moving average filter applied to the data.

dayLength = 1:size(inputTemp,1);
yearofChoice = 1;

figure;
plot(dayLength,inputTemp(:,1));
title('Temp vs. Moving Avg Temp')
hold on;
plot(dayLength,outputTemp(:,1));
legend('Temp', 'Moving Avg Temp')

Generate HDL Code and View Area Usage

To generate HDL code using the frame-to-sample conversion optimization, first set the HDL subsystem to the DUT you want to generate code from.

hdlset_param(mdl,'HDLSubsystem', dut);

To convert the input matrix from a frame-based to a sample-based input, set the HDL block property ConvertToSamples to on on the Inport block of the DUT that connects to the frame-input signal.

hdlset_param([dut '/in_sig'], 'ConvertToSamples', 'on');

Enable the frame-to-sample conversion optimization and generate HDL code using the makehdl command.

hdlset_param(mdl, 'FrameToSampleConversion', 'on');

makehdl(dut)
### Generating HDL for 'moving_avg_col_major/DUT'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('moving_avg_col_major', { 'HDL Code Generation' } )">moving_avg_col_major</a> for HDL code generation parameters.
### Running HDL checks on the model 'moving_avg_col_major'.
### Begin compilation of the model 'moving_avg_col_major'...
### Working on the model 'moving_avg_col_major'...
### <a href="matlab:configset.internal.open('moving_avg_col_major','AdaptivePipelining')">'AdaptivePipelining'</a> is set to 'Off' for the model. 'AdaptivePipelining' can improve the achievable clock frequency and reduce the area usage on FPGA boards. To enable adaptive pipelining, please set the option to 'On'. When adaptive pipelining is enabled, it inserts pipeline registers to create patterns that efficiently map blocks to DSP units on the target FPGA device.
### <a href="matlab:configset.internal.open('moving_avg_col_major','LUTMapToRAM')">'LUTMapToRAM'</a> is set to 'On' for the model. This option is used to map lookup tables to a block RAM in hardware.  To disable pipeline insertion for mapping lookup tables to RAM, please set the option to 'Off'.
### The code generation and optimization options you have chosen have introduced additional pipeline delays.
### The delay balancing feature has automatically inserted matching delays for compensation.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 1: 59 cycles.
### Output port 1: The first valid output of this port will be after an initial latency of 20 valid inputs.
### Output port 2: 59 cycles.
### Output port 2: The first valid output of this port will be after an initial latency of 20 valid inputs.
### Working on... <a href="matlab:configset.internal.open('moving_avg_col_major', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_moving_avg_col_major' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Begin VHDL Code Generation for 'moving_avg_col_major'.
### MESSAGE: The design requires 3650 times faster clock with respect to the base rate = 0.2.
### Working on counterNetwork as hdl_prj/hdlsrc/moving_avg_col_major/counterNetwork.vhd.
### Working on NeighborhoodCreator_5x1/row4_linebuffer/SimpleDualPortRAM_generic as hdl_prj/hdlsrc/moving_avg_col_major/SimpleDualPortRAM_generic.vhd.
### Working on NeighborhoodCreator_5x1/row4_linebuffer as hdl_prj/hdlsrc/moving_avg_col_major/row4_linebuffer.vhd.
### Working on NeighborhoodCreator_5x1 as hdl_prj/hdlsrc/moving_avg_col_major/NeighborhoodCreator_5x1.vhd.
### Working on boundaryCounters_5_1 as hdl_prj/hdlsrc/moving_avg_col_major/boundaryCounters_5_1.vhd.
### Working on BoundaryCheck_5x1 as hdl_prj/hdlsrc/moving_avg_col_major/BoundaryCheck_5x1.vhd.
### Working on ValidDelay_20 as hdl_prj/hdlsrc/moving_avg_col_major/ValidDelay_20.vhd.
### Working on inp_data_NeighborhoodCreator as hdl_prj/hdlsrc/moving_avg_col_major/inp_data_NeighborhoodCreator.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function/kernelAdd/nfp_add_single as hdl_prj/hdlsrc/moving_avg_col_major/nfp_add_single.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function/kernelAdd/nfp_mul_single as hdl_prj/hdlsrc/moving_avg_col_major/nfp_mul_single.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function/kernelAdd as hdl_prj/hdlsrc/moving_avg_col_major/kernelAdd.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function as hdl_prj/hdlsrc/moving_avg_col_major/MATLAB_Function.vhd.
### Working on moving_avg_col_major/DUT/Input_FIFOs/in_sig_FIFO as hdl_prj/hdlsrc/moving_avg_col_major/in_sig_FIFO.vhd.
### Working on moving_avg_col_major/DUT/Input_FIFOs as hdl_prj/hdlsrc/moving_avg_col_major/Input_FIFOs.vhd.
### Working on moving_avg_col_major/DUT/Output_FIFOs/out_data_FIFO as hdl_prj/hdlsrc/moving_avg_col_major/out_data_FIFO.vhd.
### Working on moving_avg_col_major/DUT/Output_FIFOs as hdl_prj/hdlsrc/moving_avg_col_major/Output_FIFOs.vhd.
### Working on moving_avg_col_major/DUT as hdl_prj/hdlsrc/moving_avg_col_major/DUT.vhd.
### Generating package file hdl_prj/hdlsrc/moving_avg_col_major/DUT_pkg.vhd.
### Code Generation for 'moving_avg_col_major' completed.
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23a_2213998_3299997/tp98edd189/hdlcoder-ex69077812/hdl_prj/hdlsrc/moving_avg_col_major/DUT_report.html
### HDL check for 'moving_avg_col_major' complete with 0 errors, 2 warnings, and 3 messages.
### HDL code generation complete.

Run Synthesis

By default, the Input Processing Order parameter is set to RowMajor. Run synthesis to determine the initial area usage from the model without applying column-major ordering for optimization. To run synthesis on the model, you need to have a synthesis tool installed and on the MATLAB™ path. For more information, see Tool Setup.

To run synthesis on the model:

1. In Simulink, in the HDL Code tab, click Workflow Advisor.

2. In the left pane, click 1. Set Target > 1.1 Set Target Device and Synthesis Tool. Set:

  • Target workflow to Generic ASIC/FPGA

  • Synthesis tool to Xilinx Vivado

  • Family to Virtex7

  • Device to xc7vx485t

  • Package to ffg1761

  • Speed to -2

3. Click 1.2 Set Target Frequency, and set Target Frequency (MHz) to 300.

4. In the left pane, click 4. FPGA Synthesis and Analysis > 4.2 Perform Synthesis and P/R > 4.2.2. Run Implementation. Clear Skip This Task.

5. Right-click 4.2.2 Run Implementation and click Run to Selected Task.

The HDL Workflow Advisor runs through synthesis and implementation for the model. The synthesis results display the Resource summary and Timing summary.

For more information on the code generation and synthesis steps, see HDL Code Generation and FPGA Synthesis from Simulink Model.

Optimize Area Usage

Typically, for incoming frame data that has a significantly larger number of rows than columns, also called a tall matrix, you can use column-major ordering to optimize the area used on hardware. For incoming frame data that has a significantly larger number of columns than rows, also called a long matrix, you can use row-major ordering to optimize the area used on hardware. The output of either ordering method is the same, but the ordering can generate less or more efficient mapping onto the target FPGA hardware.

For this example, to optimize the area, you either change the input processing order to column-major ordering or manually transpose the data. It is less time consuming and requires no extra manual effort to use the Input Processing Order parameter instead of manually transposing the data. Set the input processing order to column major by using the command-line.

hdlset_param(mdl, 'InputProcessingOrder', 'ColumnMajor');

Generate HDL code using the makehdl command and run through synthesis with the same settings as you did before.

makehdl(dut)
### Generating HDL for 'moving_avg_col_major/DUT'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('moving_avg_col_major', { 'HDL Code Generation' } )">moving_avg_col_major</a> for HDL code generation parameters.
### Running HDL checks on the model 'moving_avg_col_major'.
### Begin compilation of the model 'moving_avg_col_major'...
### Working on the model 'moving_avg_col_major'...
### <a href="matlab:configset.internal.open('moving_avg_col_major','AdaptivePipelining')">'AdaptivePipelining'</a> is set to 'Off' for the model. 'AdaptivePipelining' can improve the achievable clock frequency and reduce the area usage on FPGA boards. To enable adaptive pipelining, please set the option to 'On'. When adaptive pipelining is enabled, it inserts pipeline registers to create patterns that efficiently map blocks to DSP units on the target FPGA device.
### <a href="matlab:configset.internal.open('moving_avg_col_major','LUTMapToRAM')">'LUTMapToRAM'</a> is set to 'On' for the model. This option is used to map lookup tables to a block RAM in hardware.  To disable pipeline insertion for mapping lookup tables to RAM, please set the option to 'Off'.
### The code generation and optimization options you have chosen have introduced additional pipeline delays.
### The delay balancing feature has automatically inserted matching delays for compensation.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 1: 59 cycles.
### Output port 1: The first valid output of this port will be after an initial latency of 2 valid inputs.
### Output port 2: 59 cycles.
### Output port 2: The first valid output of this port will be after an initial latency of 2 valid inputs.
### Working on... <a href="matlab:configset.internal.open('moving_avg_col_major', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_moving_avg_col_major' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Begin VHDL Code Generation for 'moving_avg_col_major'.
### MESSAGE: The design requires 3650 times faster clock with respect to the base rate = 0.2.
### Working on counterNetwork as hdl_prj/hdlsrc/moving_avg_col_major/counterNetwork.vhd.
### Working on NeighborhoodCreator_5x1/row1_col4 as hdl_prj/hdlsrc/moving_avg_col_major/row1_col4.vhd.
### Working on NeighborhoodCreator_5x1 as hdl_prj/hdlsrc/moving_avg_col_major/NeighborhoodCreator_5x1.vhd.
### Working on boundaryCounters_5_1 as hdl_prj/hdlsrc/moving_avg_col_major/boundaryCounters_5_1.vhd.
### Working on BoundaryCheck_5x1 as hdl_prj/hdlsrc/moving_avg_col_major/BoundaryCheck_5x1.vhd.
### Working on ValidDelay_2 as hdl_prj/hdlsrc/moving_avg_col_major/ValidDelay_2.vhd.
### Working on inp_data_NeighborhoodCreator as hdl_prj/hdlsrc/moving_avg_col_major/inp_data_NeighborhoodCreator.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function/kernelAdd/nfp_add_single as hdl_prj/hdlsrc/moving_avg_col_major/nfp_add_single.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function/kernelAdd/nfp_mul_single as hdl_prj/hdlsrc/moving_avg_col_major/nfp_mul_single.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function/kernelAdd as hdl_prj/hdlsrc/moving_avg_col_major/kernelAdd.vhd.
### Working on moving_avg_col_major/DUT/MATLAB Function as hdl_prj/hdlsrc/moving_avg_col_major/MATLAB_Function.vhd.
### Working on moving_avg_col_major/DUT/Input_FIFOs/in_sig_FIFO/FIFO/FIFO_classic/SimpleDualPortRAM_generic as hdl_prj/hdlsrc/moving_avg_col_major/SimpleDualPortRAM_generic.vhd.
### Working on moving_avg_col_major/DUT/Input_FIFOs/in_sig_FIFO as hdl_prj/hdlsrc/moving_avg_col_major/in_sig_FIFO.vhd.
### Working on moving_avg_col_major/DUT/Input_FIFOs as hdl_prj/hdlsrc/moving_avg_col_major/Input_FIFOs.vhd.
### Working on moving_avg_col_major/DUT/Output_FIFOs/out_data_FIFO as hdl_prj/hdlsrc/moving_avg_col_major/out_data_FIFO.vhd.
### Working on moving_avg_col_major/DUT/Output_FIFOs as hdl_prj/hdlsrc/moving_avg_col_major/Output_FIFOs.vhd.
### Working on moving_avg_col_major/DUT as hdl_prj/hdlsrc/moving_avg_col_major/DUT.vhd.
### Generating package file hdl_prj/hdlsrc/moving_avg_col_major/DUT_pkg.vhd.
### Code Generation for 'moving_avg_col_major' completed.
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23a_2213998_3299997/tp98edd189/hdlcoder-ex69077812/hdl_prj/hdlsrc/moving_avg_col_major/DUT_report.html
### HDL check for 'moving_avg_col_major' complete with 0 errors, 2 warnings, and 3 messages.
### HDL code generation complete.

The Resource summary in the synthesis results shows a reduction in LUTs and register hardware used to map the algorithm as a result of altering the order in which input data is processed.

Related Examples

More About