Main Content

Indexing Best Practices for HDL Code Generation

In MATLAB®, array indices start from 1 and follow a 1-based indexing approach. However, HDL code uses 0-based indexing, where array indices start from 0. When you generate HDL code from a MATLAB algorithm, HDL Coder™ converts 1-based MATLAB indexing to 0-based HDL indexing, which may result in excess logic that can consume more hardware area. Using these best practices can optimize your code and reduce the amount of hardware area used.

Minimize Automatic Index Conversions

Because HDL Coder converts 1-based MATLAB indexing to 0-based HDL indexing when you generate code, HDL Coder may generate excess logic in the VHDL®, Verilog®, or SystemVerilog code to assist with this conversion. This excess logic leads to increased hardware area consumption.

To minimize the number of automatic conversions HDL Coder introduces when translating your MATLAB algorithm to HDL code and meet your hardware area requirements, you can store a zero-based index in index variables. For this method to work effectively, you must cast the index variables to int32 type. When you perform an index operation, add 1 to the value of int32 cast index. HDL Coder optimizes the automatic conversion.

Unoptimized MATLAB CodeOptimized MATLAB Code
arr = [3 5 7 9];
num = length(arr);
% Index ii is 1-based
for ii = 1:num
    % 1-based index when indexing
    disp(arr(ii))
end
arr = [3 5 7 9];
num = length(arr);
% Index ii is 0-based
for ii = int32(0):num-1
    % Add 1 to the value of the int32 cast 0-based index when indexing
    disp(arr(ii+1))
end

Example of Area Consumption Optimization

This MATLAB algorithm enhances the contrast of images by transforming the values in an intensity image so that the histogram of the output image is approximately flat. Apply the indexing best practice to the algorithm. For more information on this algorithm, see Image Enhancement by Histogram Equalization. When you convert the unoptimized algorithm to HDL code, the conversion process can lead to excess logic. Compare the hardware area usage of the unoptimized algorithm to the optimized algorithm.

Unoptimized MATLAB AlgorithmOptimized MATLAB Algorithm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% mlhdlc_heq.m
% Histogram Equalization Algorithm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [x_out, y_out, pixel_out] = ...
    mlhdlc_heq(x_in, y_in, pixel_in, width, height)

% Copyright 2011-2024 The MathWorks, Inc.

persistent histogram
persistent transferFunc
persistent histInd
persistent cumSum

if isempty(histogram)
    histogram = zeros(1, 2^14);
    transferFunc = zeros(1, 2^14);
    histInd = 0;
    cumSum = 0;
end

% Figure out indexes based on where we are in the frame
if y_in < height && x_in < width % valid pixel data
    histInd = pixel_in + 1;
elseif y_in == height && x_in == 0 % first column of height+1
    histInd = 1;
elseif y_in >= height % vertical blanking period
    histInd = min(histInd + 1, 2^14);
elseif y_in < height % horizontal blanking - do nothing
    histInd = 1;
end

% Read histogram (must be outside conditional logic)
histValRead = histogram(histInd);

% Read transfer function (must be outside conditional logic)
transValRead = transferFunc(histInd);

% If valid part of frame add one to pixel bin 
% and keep transfer func val
if y_in < height && x_in < width
    histValWrite = histValRead + 1; % Add pixel to bin
    transValWrite = transValRead; % Write back same value
    cumSum = 0;
elseif y_in >= height % In blanking time index through all bins and reset to zero
    histValWrite = 0;
    transValWrite = cumSum + histValRead;
    cumSum = transValWrite;
else
    histValWrite = histValRead;
    transValWrite = transValRead;
end

% Write histogram (must be outside conditional logic)
histogram(histInd) = histValWrite;

% Write transfer function (must be outside conditional logic)
transferFunc(histInd) = transValWrite;

pixel_out = transValRead;
x_out = x_in;
y_out = y_in;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% mlhdlc_heq_bp.m
% Histogram Equalization Algorithm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [x_out, y_out, pixel_out] = ...
    mlhdlc_heq_bp(x_in, y_in, pixel_in, width, height)

% Copyright 2011-2024 The MathWorks, Inc.

persistent histogram
persistent transferFunc
persistent histInd
persistent cumSum

if isempty(histogram)
    histogram = zeros(1, 2^14);
    transferFunc = zeros(1, 2^14);
    histInd = 0;
    cumSum = 0;
end

% Adjust histInd index variable to be 0-based
if y_in < height && x_in < width
    histInd = pixel_in;
elseif y_in == height && x_in == 0
    histInd = 0;
elseif y_in >= height
    histInd = min(histInd + 1, 2^14-1);
elseif y_in < height
    histInd = 0;
end

% Add 1 to the value of the 0-based histInd when indexing 
histValRead = histogram(int32(histInd)+1);

% Add 1 to the value of the 0-based histInd when indexing
transValRead = transferFunc(int32(histInd)+1);

if y_in < height && x_in < width
    histValWrite = histValRead + 1;
    transValWrite = transValRead;
    cumSum = 0;
elseif y_in >= height
    histValWrite = 0;
    transValWrite = cumSum + histValRead;
    cumSum = transValWrite;
else
    histValWrite = histValRead;
    transValWrite = transValRead;
end

% Add 1 to the value of the 0-based histInd when indexing
histogram(int32(histInd)+1) = histValWrite;

% Add 1 to the value of the 0-based histInd when indexing
transferFunc(int32(histInd)+1) = transValWrite;

pixel_out = transValRead;
x_out = x_in;
y_out = y_in;
  1. Run the command mlhdlc_demo_setup('heq') in the MATLAB Command Window. This command copies the files mlhdlc_heq.m and mlhdlc_heq_tb.m into a temporary working folder.

  2. Create a new MATLAB function in the temporary working folder named mlhdlc_heq_bp.m. Copy the optimized MATLAB algorithm from the table into the function.

  3. Create a new MATLAB script in the temporary working folder named mlhdlc_heq_bp_tb.m. Copy the contents of the mlhdlc_heq_tb.m testbench into mlhdlc_heq_bp_tb.m. Change the line with the function call mlhdlc_heq to mlhdlc_heq_bp in order for the mlhdlc_heq_bp_tb.m testbench to exercise the function design of the optimized MATLAB algorithm, mlhdlc_heq_bp.

  4. Generate HDL code from the unoptimized algorithm, mlhdlc_heq. For more information on how to generate HDL code from the command line, see Generate HDL Code from MATLAB Code Using the Command Line Interface.

    fixptcfg = coder.config('fixpt');
    fixptcfg.TestBenchName = 'mlhdlc_heq_tb';
    
    hdlcfg = coder.config('hdl');
    hdlcfg.TestBenchName = 'mlhdlc_heq_tb';
    hdlcfg.MapPersistentVarsToRAM = 0;
    hdlcfg.TargetLanguage = 'VHDL';
    
    codegen -float2fixed fixptcfg -config hdlcfg mlhdlc_heq
  5. Open the generated VHDL file and observe the automatic conversion HDL Coder introduces when translating the 1-based MATLAB algorithm to 0-based VHDL indexing. For example, compare the index operations from the MATLAB algorithm to the generated VHDL code.

    Unoptimized MATLAB Algorithm Generated VHDL Code
    ...
    ...
    %Read histogram (must be outside conditional logic)
    histValRead = histogram(histInd);
    
    %Read transfer function (must be outside conditional logic)
    transValRead = transferFunc(histInd);
    ...
    ...
    ...
    ...
    --Read histogram (must be outside conditional logic)
    sub_cast := signed(resize(histInd_temp, 32));
    -- HDL Coder automatically converts between the 1- and 0-based indicies
    histValRead := mlhdlc_heq_fixpt_histogram(to_integer(sub_cast - 1)); 
    --Read transfer function (must be outside conditional logic)
    sub_cast_0 := signed(resize(histInd_temp, 32));
    -- HDL Coder automatically converts between the 1- and 0-based indicies
    transValRead := mlhdlc_heq_fixpt_transferFunc(to_integer(sub_cast_0 - 1)); 
    ...
    ...
  6. Generate HDL code from the optimized MATLAB algorithm that follows the best practice, mlhdlc_heq_bp. Set the fixptcfg and hdlcfg object parameters and run the codegen command.

    fixptcfg = coder.config('fixpt');
    fixptcfg.TestBenchName = 'mlhdlc_heq_bp_tb';
    
    hdlcfg = coder.config('hdl');
    hdlcfg.TestBenchName = 'mlhdlc_heq_bp_tb';
    hdlcfg.MapPersistentVarsToRAM = 0;
    hdlcfg.TargetLanguage = 'VHDL';
    
    codegen -float2fixed fixptcfg -config hdlcfg mlhdlc_heq_bp
  7. Open the generated VHDL file. For example, compare the index operations from the optimized MATLAB algorithm to the generated VHDL code. Observe how the generated VHDL code includes less logic.

    Optimized MATLAB AlgorithmGenerated VHDL Code
    ...
    ...
    % Add 1 to the value of the 0-based histInd when indexing 
    histValRead = histogram(histInd+1);
    
    % Add 1 to the value of the 0-based histInd when indexing
    transValRead = transferFunc(histInd+1);
    ...
    ...
    ...
    ...
    -- Add 1 to the value of the 0-based histInd when indexing
    -- HDL Coder optimizes the automatic conversion
    histValRead := mlhdlc_heq_bp_fixpt_histogram(to_integer(histInd_temp)); 
    -- Add 1 to the value of the 0-based histInd when indexing
    -- HDL Coder optimizes the automatic conversion
    transValRead := mlhdlc_heq_bp_fixpt_transferFunc(to_integer(histInd_temp)); 
    ...
    ...
  8. Set the fixptcfg and hdlcfg object parameters and run the codegen command to place and route the HDL code from the unoptimized and optimized MATLAB algorithms. For more information, see Synthesis and Analysis. For example, set the fixptcfg and hdlcfg object parameters and run the codegen command to place and route the HDL code from the optimized algorithm, mlhdlc_heq_bp.

    fixptcfg = coder.config('fixpt');
    fixptcfg.TestBenchName = 'mlhdlc_heq_bp_tb';
    
    hdlcfg = coder.config('hdl');
    hdlcfg.TestBenchName = 'mlhdlc_heq_bp_tb';
    hdlcfg.MapPersistentVarsToRAM = 1;
    hdlcfg.TargetLanguage = 'VHDL';
    
    hdlcfg.SynthesisTool = 'Xilinx Vivado';
    hdlcfg.SynthesisToolChipFamily = 'Zynq';
    hdlcfg.SynthesisToolDeviceName = 'xc7z020';
    hdlcfg.SynthesisToolPackageName = 'clg400';
    hdlcfg.SynthesisToolSpeedValue = '-1';
    hdlcfg.SynthesizeGeneratedCode = true;
    
    codegen -float2fixed fixptcfg -config hdlcfg mlhdlc_heq_bp

    VHDL code generated from the optimized MATLAB algorithm uses less hardware area, as HDL Coder introduces fewer automatic index conversions to compensate for the differences in indexing. This table compares the place and route results for the unoptimized and optimized MATLAB algorithms obtained from the synthesis tool.

    Place and Route Result for Unoptimized MATLAB AlgorithmPlace and Route Result for Optimized MATLAB Algorithm
    Parsed resource report file: mlhdlc_heq_fixpt_utilization_synth.rpt.
    
             Resource           Usage     Available     Utilization (%)
        ___________________    _______    __________    _______________
    
        {'Slice LUTs'     }    {'171'}    {'53200' }       {'0.32' }   
        {'Slice Registers'}    {'277'}    {'106400'}       {'0.26' }      
    Parsed resource report file: mlhdlc_heq_bp_fixpt_utilization_synth.rpt.
    
             Resource           Usage     Available     Utilization (%)
        ___________________    _______    __________    _______________
    
        {'Slice LUTs'     }    {'147'}    {'53200' }       {'0.28' }   
        {'Slice Registers'}    {'262'}    {'106400'}       {'0.25' }   
     

See Also

Functions

Objects

Related Topics