Main Content

Replace Arithmetic Operation to Generate Efficient HDL and High-Level Synthesis Code

Best practices when using division operation in your MATLAB® code for HDL and High-Level Synthesis (HLS) code generation.

Division Operation

One of the fundamental arithmetic operation, division is found in many applications including vector normalization and matrix decomposition. The example starts with floating-point division operation and use fixed-point conversion to map division into efficient implementations before generating code.

Division Using Cordic Algorithm

Cordic algorithm is one of the hardware efficient algorithms for division operations that require only shift-add operations. You can use fixed.cordicDivide method supported for fixed-point data type in MATLAB to generate efficient code.

To facilitate automatic replacement of division operation with fixed.cordicDivide function:

  • Write the division operation into a separate function called divide_op.

function y = divide_example(u, v)
  y = divide_op(u, v);
end

function y = divide_op(u, v)
 y = u / v;
end
  • Replace the divide_op function with CordicDivideFcn when converting from floating-point type to fixed-point data type.

function y = CordicDivideFcn(a, b)
 y = fixed.cordicDivide(a, b, numerictype(0,14,14));
end

Perform fixed-point conversion and generate HLS code by using these commands.

% Create HDL configuration object
hdlcfg = coder.config('hdl');
hdlcfg.Workflow = 'High Level Synthesis';
hdlcfg.TargetLanguage = 'SystemC'; 
hdlcfg.DesignFunctionName = 'divide_example';
hdlcfg.TestBenchName = 'divide_example_tb';

% Create float to fixed configuration object
cfg = coder.config('fixpt');
cfg.TestBenchName = { 'divide_example_tb.m' };
cfg.LogIOForComparisonPlotting = true;
cfg.TestNumerics = true;
cfg.PlotWithSimulationDataInspector = true;

% Replace divide_op with cordic divide function
cfg.addFunctionReplacement('divide_op', 'CordicDivideFcn');

% Invoke fixed-point conversion and generate SystemC code
codegen -float2fixed cfg divide_example -config hdlcfg -args {0,0}
===================================================
Design Name: divide_example
Test Bench Name: divide_example_tb
===================================================


============= Step1: Analyze floating-point code ==============

Code generation successful.



============= Step1a: Verify Floating Point ==============

### Analyzing the design 'divide_example'
### Analyzing the test bench(es) 'divide_example_tb'
### Begin Floating Point Simulation (Instrumented)
### Floating Point Simulation Completed in   2.5242 sec(s)
### Elapsed Time:             3.9292 sec(s)

============= Step2: Propose Types based on Range Information ==============


============= Step3: Generate Fixed Point Code ==============

### Generating Fixed Point MATLAB Code divide_example_fixpt using Proposed Types
### Generating Fixed Point MATLAB Design Wrapper divide_example_wrapper_fixpt
### Generating Mex file for ' divide_example_wrapper_fixpt '
Code generation successful: View report
### Generating Type Proposal Report for 'divide_example' divide_example_report.html

============= Step4: Verify Fixed Point Code ==============

### Analyzing the design 'divide_example'
### Analyzing the test bench(es) 'divide_example_tb'
### Begin Floating Point Simulation
### Floating Point Simulation Completed in   1.0194 sec(s)
### Begin Fixed Point Simulation : divide_example_tb
### Fixed Point Simulation Completed in   2.3450 sec(s)

Generating comparison plot(s) for 'divide_example' using Simulation Data Inspector.

--------------  Input variable : u  --------------
Generating comparison plot...

--------------  Input variable : v  --------------
Generating comparison plot...

--------------  Output variable : y  --------------
Generating comparison plot...

### Generating Fixed-point Types Report for 'divide_example_fixpt' divide_example_fixpt_report.html
### Elapsed Time:             7.2580 sec(s)

===================================================
Code generation successful.

### Begin HLS Code Generation
### Working on divide_example_fixptClass.hpp as divide_example_fixptClass.hpp.
### Working on divide_example_fixptModule.hpp as divide_example_fixptModule.hpp.
### Generating Resource Utilization Report resource_report.html.
### Generating HDL Conformance Report divide_example_fixpt_hdl_conformance_report.html.
### HDL Conformance check complete with 0 errors, 0 warnings, and 0 messages.
Code generation successful.

In the HDL workflow advisor, function replacements are done in the fixed-point converter step using the Function Replacements tab.

Division Using Shift-Add

Non-restoring division algorithm uses only shifts and addition operations and is advantageous to use in hardware. You can use a custom implementation of this division algorithm for fixed-point data types in function shift_add_divider. Write division operation in a separate function which can be replaced after fixed-point conversion with our custom implementation function shift_add_divider.

function y = divide_example(u, v)
  y = divide_op(u, v);
end

function y = divide_op(u, v)
 y = u / v;
end

Perform fixed-point conversion and generate HLS code by using these commands.

% Create configuration object of class 'coder.HdlConfig'.
hdlcfg = coder.config('hdl');
hdlcfg.Workflow = 'High Level Synthesis';
hdlcfg.TargetLanguage = 'SystemC'; % Use target language as 'HDL' for HDL code generation
hdlcfg.DesignFunctionName = 'divide_example';
hdlcfg.TestBenchName = 'divide_example_tb';

% Create configuration object of class 'coder.FixPtConfig'.
cfg = coder.config('fixpt');
cfg.TestBenchName = { 'divide_example_tb.m' };
cfg.LogIOForComparisonPlotting = true;
cfg.TestNumerics = true;
cfg.PlotWithSimulationDataInspector = true;

% Replace divide_op with shift-add divide function
cfg.addTypeSpecification('divide_example', 'u', numerictype(0,14,10));
cfg.addTypeSpecification('divide_op', 'u', numerictype(0,14,10));
cfg.addFunctionReplacement('divide_op', 'shift_add_divider');

% Invoke fixed-point conversion and generate SystemC
codegen -float2fixed cfg -config hdlcfg divide_example -args {0,0}
===================================================
Design Name: divide_example
Test Bench Name: divide_example_tb
===================================================


============= Step1: Analyze floating-point code ==============


============= Step1a: Verify Floating Point ==============

### Analyzing the design 'divide_example'
### Analyzing the test bench(es) 'divide_example_tb'
### Begin Floating Point Simulation (Instrumented)
### Floating Point Simulation Completed in   1.9169 sec(s)
### Elapsed Time:             2.5655 sec(s)

============= Step2: Propose Types based on Range Information ==============


============= Step3: Generate Fixed Point Code ==============

### Generating Fixed Point MATLAB Code divide_example_fixpt using Proposed Types
### Generating Fixed Point MATLAB Design Wrapper divide_example_wrapper_fixpt
### Generating Mex file for ' divide_example_wrapper_fixpt '
Code generation successful: View report
### Generating Type Proposal Report for 'divide_example' divide_example_report.html

============= Step4: Verify Fixed Point Code ==============

### Analyzing the design 'divide_example'
### Analyzing the test bench(es) 'divide_example_tb'
### Begin Floating Point Simulation
### Floating Point Simulation Completed in   1.4577 sec(s)
### Begin Fixed Point Simulation : divide_example_tb
### Fixed Point Simulation Completed in   3.3688 sec(s)

Generating comparison plot(s) for 'divide_example' using Simulation Data Inspector.

--------------  Input variable : u  --------------
Generating comparison plot...

--------------  Input variable : v  --------------
Generating comparison plot...

--------------  Output variable : y  --------------
Generating comparison plot...

### Generating Fixed-point Types Report for 'divide_example_fixpt' divide_example_fixpt_report.html
### Elapsed Time:             6.7749 sec(s)

===================================================
Code generation successful.

### Begin HLS Code Generation
### Working on divide_example_fixptClass.hpp as divide_example_fixptClass.hpp.
### Working on divide_example_fixptModule.hpp as divide_example_fixptModule.hpp.
### Generating Resource Utilization Report resource_report.html.
### Generating HDL Conformance Report divide_example_fixpt_hdl_conformance_report.html.
### HDL Conformance check complete with 0 errors, 0 warnings, and 0 messages.
Code generation successful.

Division Using Lookup Table

When the output of division does not have high dynamic range, use lookup table approach to compute reciprocal and then multiply the reciprocal with numerator to perform division operation.

For using a 1-D lookup table, split the division operation into a reciprocal operation and a multiplication. Implement the reciprocal using the lookup table.

function y = recip_example(u, v)
   recip = reciprocal_op(v);
   y = u * recip;
end

The function reciprocal_op need to be in a separate file so that the fixed-point converter can use the results of this function to create lookup table data.

function y = reciprocal_op(v)
  y = 1 / v;
end

Perform fixed-point conversion and generate HLS code by using these commands.

% HDL Configuration
hdlcfg = coder.config('hdl');
hdlcfg.Workflow = 'High Level Synthesis';
hdlcfg.TargetLanguage = 'SystemC';
hdlcfg.DesignFunctionName = 'recip_example';
hdlcfg.TestBenchName = 'recip_example_tb';

% Fixpt conversion configuration
cfg = coder.config('fixpt');
cfg.TestBenchName = { 'recip_example_tb.m' };
cfg.LogIOForComparisonPlotting = true;
cfg.TestNumerics = true;
cfg.PlotWithSimulationDataInspector = true;

cfg.addTypeSpecification('recip_example', 'v', numerictype(0,6,0));

% Lookup table specification
approxConfig = coder.approximation('reciprocal_op');
approxConfig.CandidateFunction = 'reciprocal_op';
approxConfig.InterpolationDegree = 1;
approxConfig.NumberOfPoints = 1000;
cfg.addApproximation(approxConfig);

% Invoke code generation
codegen -float2fixed cfg recip_example -config hdlcfg -args {0,0}
===================================================
Design Name: recip_example
Test Bench Name: recip_example_tb
===================================================


============= Step1: Analyze floating-point code ==============

Code generation successful.



============= Step1a: Verify Floating Point ==============

### Analyzing the design 'recip_example'
### Analyzing the test bench(es) 'recip_example_tb'
### Begin Floating Point Simulation (Instrumented)
### Floating Point Simulation Completed in   1.8351 sec(s)
### Elapsed Time:             2.6151 sec(s)

============= Step2: Propose Types based on Range Information ==============


============= Step3: Generate Fixed Point Code ==============

### Generating Fixed Point MATLAB Code recip_example_fixpt using Proposed Types
### Generating Fixed Point MATLAB Design Wrapper recip_example_wrapper_fixpt
### Generating Mex file for ' recip_example_wrapper_fixpt '
Code generation successful: View report
### Generating Type Proposal Report for 'recip_example' recip_example_report.html

============= Step4: Verify Fixed Point Code ==============

### Analyzing the design 'recip_example'
### Analyzing the test bench(es) 'recip_example_tb'
### Begin Floating Point Simulation
### Floating Point Simulation Completed in   1.5098 sec(s)
### Begin Fixed Point Simulation : recip_example_tb
### Fixed Point Simulation Completed in   2.5469 sec(s)

Generating comparison plot(s) for 'recip_example' using Simulation Data Inspector.

--------------  Input variable : u  --------------
Generating comparison plot...

--------------  Input variable : v  --------------
Generating comparison plot...

--------------  Output variable : y  --------------
Generating comparison plot...

### Generating Fixed-point Types Report for 'recip_example_fixpt' recip_example_fixpt_report.html
### Elapsed Time:             6.2453 sec(s)

===================================================
Code generation successful.

### Begin HLS Code Generation
### Working on recip_example_fixptClass.hpp as recip_example_fixptClass.hpp.
### Working on recip_example_fixptModule.hpp as recip_example_fixptModule.hpp.
### Generating Resource Utilization Report resource_report.html.
### Generating HDL Conformance Report recip_example_fixpt_hdl_conformance_report.html.
### HDL Conformance check complete with 0 errors, 0 warnings, and 0 messages.
Code generation successful.

In the HDL workflow advisor, lookup table replacements are done in the fixed-point converter step using the Function Replacements tab. Lookup table parameters like table size and interpolation method can be customized in the workflow advisor.

Division Using Power of 2

Dividing a number by a power of two can be more efficiently done using a shift operation. For example, a / 2^exponent is replaced with bitsra(a, exponent), which performs a right bitwise shift. Write division operation in a separate function localDiv which can be replaced after fixed-point conversion with our custom implementation function bitsra.

function y = divbypow2(u, exponent)
    y = localDiv(u, exponent);
end

function y = localDiv(u, exponent)
    y = u / 2^exponent;
end

Perform fixed-point conversion and generate HLS code by using these commands.

hdlCfg = coder.config('hdl');
hdlcfg.Workflow = 'High Level Synthesis';
hdlcfg.TargetLanguage = 'SystemC';
hdlCfg.DesignFunctionName = 'divbypow2';
hdlCfg.TestBenchName = 'divbypow2_tb';

% %% Define argument types for entry-point 'divbypow2_fixpt'.
% ARGS = cell(1,1);
% ARGS{1} = cell(2,1);
% ARGS{1}{1} = coder.typeof(fi(0,numerictype(0,14,14));
% ARGS{1}{2} = coder.typeof(fi(0,numerictype(0,3,0));
% codegen -config cfg  -args ARGS{1}
%% Create configuration object of class 'coder.FixPtConfig'.
fixptCfg = coder.config('fixpt');
fixptCfg.TestBenchName = { 'divbypow2_tb.m' };
fixptCfg.LogIOForComparisonPlotting = true;
fixptCfg.TestNumerics = true;
fixptCfg.addFunctionReplacement('localDiv', 'bitsra');

%% Invoke fixed-point conversion.
codegen -float2fixed fixptCfg divbypow2 -config hdlCfg -args {0, 0}
===================================================
Design Name: divbypow2
Test Bench Name: divbypow2_tb
===================================================


============= Step1: Analyze floating-point code ==============

Code generation successful.



============= Step1a: Verify Floating Point ==============

### Analyzing the design 'divbypow2'
### Analyzing the test bench(es) 'divbypow2_tb'
### Begin Floating Point Simulation (Instrumented)
### Floating Point Simulation Completed in   2.0689 sec(s)
### Elapsed Time:             3.3990 sec(s)

============= Step2: Propose Types based on Range Information ==============


============= Step3: Generate Fixed Point Code ==============

### Generating Fixed Point MATLAB Code divbypow2_fixpt using Proposed Types
### Generating Fixed Point MATLAB Design Wrapper divbypow2_wrapper_fixpt
### Generating Mex file for ' divbypow2_wrapper_fixpt '
Code generation successful: View report
### Generating Type Proposal Report for 'divbypow2' divbypow2_report.html

============= Step4: Verify Fixed Point Code ==============

### Analyzing the design 'divbypow2'
### Analyzing the test bench(es) 'divbypow2_tb'
### Begin Floating Point Simulation
### Floating Point Simulation Completed in   1.6779 sec(s)
### Begin Fixed Point Simulation : divbypow2_tb
### Fixed Point Simulation Completed in   2.0546 sec(s)

Generating comparison plot(s) for 'divbypow2' using PlotFunction : 'coder.internal.plotting.inBuiltPlotFunctionCLI'...

--------------  Input variable : u  --------------
Generating comparison plot...

Max Positive Error : 5.5836e-05
Max Negative Error : 0
Max Absolute Value : 0.96489
Max Percentage Error : 0.0057868
--------------  Input variable : exponent  --------------
Generating comparison plot...

Max Positive Error : 0
Max Negative Error : 0
Max Absolute Value : 4
Max Percentage Error : 0
--------------  Output variable : y  --------------
Generating comparison plot...

Max Positive Error : 5.3795e-05
Max Negative Error : 0
Max Absolute Value : 0.060306
Max Percentage Error : 0.089204
### Generating Fixed-point Types Report for 'divbypow2_fixpt' divbypow2_fixpt_report.html
### Elapsed Time:             7.0535 sec(s)

===================================================
Code generation successful.

### Begin VHDL Code Generation
### Working on divbypow2_fixpt as divbypow2_fixpt.vhd.
### Generating Resource Utilization Report resource_report.html.
### Generating HDL Conformance Report divbypow2_fixpt_hdl_conformance_report.html.
### HDL Conformance check complete with 0 errors, 0 warnings, and 0 messages.
Code generation successful.

Summary

The above examples showed different ways of implementing division operation that are suitable for hardware. These techniques can be effectively used for HDL and HLS code generation from MATLAB.