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.4317 sec(s)
### Elapsed Time:             3.3158 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.5238 sec(s)
### Begin Fixed Point Simulation : divide_example_tb
### Fixed Point Simulation Completed in   2.6923 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.4584 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.9688 sec(s)
### Elapsed Time:             2.7792 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.1632 sec(s)
### Begin Fixed Point Simulation : divide_example_tb
### Fixed Point Simulation Completed in   2.9738 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.0803 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.7133 sec(s)
### Elapsed Time:             2.6362 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.1867 sec(s)
### Begin Fixed Point Simulation : recip_example_tb
### Fixed Point Simulation Completed in   2.5834 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:             5.6428 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.0558 sec(s)
### Elapsed Time:             2.9000 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.0497 sec(s)
### Begin Fixed Point Simulation : divbypow2_tb
### Fixed Point Simulation Completed in   2.2593 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:             5.6920 sec(s)

Figure divbypow2>input>exponent: 14-bit WL (19:48:19) contains 3 axes objects. Axes object 1 with title divbypow2 > float : exponent contains an object of type line. Axes object 2 with title divbypow2 > fixed : exponent contains an object of type line. Axes object 3 with title error contains an object of type line.

Figure divbypow2>output>y: 14-bit WL (19:48:19) contains 3 axes objects. Axes object 1 with title divbypow2 > float : y contains an object of type line. Axes object 2 with title divbypow2 > fixed : y contains an object of type line. Axes object 3 with title error contains an object of type line.

Figure divbypow2>input>u: 14-bit WL (19:48:19) contains 3 axes objects. Axes object 1 with title divbypow2 > float : u contains an object of type line. Axes object 2 with title divbypow2 > fixed : u contains an object of type line. Axes object 3 with title error contains an object of type line.

===================================================
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.