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 withCordicDivideFcn
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.9486 sec(s) ### Elapsed Time: 4.1139 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.9873 sec(s) ### Begin Fixed Point Simulation : divide_example_tb ### Fixed Point Simulation Completed in 3.6361 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: 10.9827 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 2.0964 sec(s) ### Elapsed Time: 3.1212 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.5834 sec(s) ### Begin Fixed Point Simulation : divide_example_tb ### Fixed Point Simulation Completed in 3.6806 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.7755 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 2.5210 sec(s) ### Elapsed Time: 3.7063 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.3446 sec(s) ### Begin Fixed Point Simulation : recip_example_tb ### Fixed Point Simulation Completed in 4.2072 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: 8.1217 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.0369 sec(s) ### Elapsed Time: 3.1879 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.5974 sec(s) ### Begin Fixed Point Simulation : divbypow2_tb ### Fixed Point Simulation Completed in 3.1981 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: 8.6119 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.