Main Content

Floating Point Support: Field-Oriented Control Algorithm

In this example you review a Field-Oriented Control (FOC) algorithm for a Permanent Magnet Synchronous Machine (PMSM) implemented using single-precision and half-precision floating-point types.

Introduction

You have seen the fixed-point version of this design in Field-Oriented Control of a Permanent Magnet Synchronous Machine that takes a deep dive into how to implement current control algorithm using fixed-point types. The model was converted to fixed-point before generating HDL code.

You can use floating-point single-precision types in your design and generate HDL code natively without converting to fixed-point types. This example shows design considerations when generating code from floating-point single-precision and half-precision variants of the fixed point model hdlcoderFocCurrentFixptHdl.

The testbench model hdlcoderFocCurrentTestBench has a reference block pointing to the DUT implemented in fixed-point or floating-point.

Salient features of Native Floating Point support

  • Vendor independent and target agnostic RTL for FPGA and/or ASIC design

  • Full range of IEEE-754 features including support for rounding modes, inf and nan data types, and optional support for denormal numbers.

  • Extensive math block (add,mul,div,recip,log,exp,sqrt,rsqrt) and trigonometric block (sin, cos, sincos, atan, atan2) support.

Why Use Floating-Point Types

Sometimes you might want to start in floating-point and stay in floating-point to target HDL, rather than convert to fixed-point, for the following reasons:

  • Your algorithms have large or unknown dynamic ranges (for example integrators in feedback loops)

  • Your algorithm uses operations that are difficult to design in fixed-point (ex: atan2)

In the fixed-point version of the example hdlcoderFocCurrentFloatHDL.slx you notice that several fixed-point rounding and saturation decisions are made to preserve the numerical behavior of the algorithm. For example the block hdlcoderFocCurrentFixptHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Saturate which is a saturation block has been placed in the integrator loop so that results do not overflow due to accumulation in the loop.

open_system('hdlcoderFocCurrentFixptHdl');
open_system('hdlcoderFocCurrentFixptHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control/Saturate');

Sometimes, the task of fixed-point conversion could take several weeks to months with multiple levels of algorithm re-validation. It may also lead to undesirable loss of precision which might not be acceptable for some mission critical applications requiring very high accuracy.

In these situations, you can choose to use native floating point synthesis features available in HDL Coder.

Single-Precision FOC Model

To open the single-precision version of the algorithm, run these commands:

load_system('hdlcoderFocCurrentFloatHdl');
open_system('hdlcoderFocCurrentFloatHdl/FOC_Current_Control')

In comparison to the fixed-point algorithm, the single-precision model does not require additional rounding and saturation blocks and settings as can be seen in the floating-point version of the model hdlcoderFocCurrentFloatHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control

open_system('hdlcoderFocCurrentFloatHdl/FOC_Current_Control/DQ_Current_Control/D_Current_Control')

To verify the behavior through simulation, run these commands:

hasSimPowerSystems = license ('test', 'Power_System_Blocks');
if hasSimPowerSystems
   open_system('hdlcoderFocCurrentTestBench')

   % set single-precision floating-point model in the testbench
   set_param('hdlcoderFocCurrentTestBench/Controller', 'ModelName', 'hdlcoderFocCurrentFloatHdl');

   set_param('hdlcoderFocCurrentTestBench','IgnoredZcDiagnostic','none');
   sim('hdlcoderFocCurrentTestBench')
   set_param('hdlcoderFocCurrentTestBench','IgnoredZcDiagnostic','warn');
end

You can generate HDL code and view the generated code for the controller.

hdlset_param('hdlcoderFocCurrentFloatHdl', 'FloatingPointTargetConfiguration', hdlcoder.createFloatingPointTargetConfig('NATIVEFLOATINGPOINT'));
makehdl('hdlcoderFocCurrentFloatHdl/FOC_Current_Control');
### Begin compilation of the model 'hdlcoderFocCurrentFloatHdl'...
### Generating HDL for 'hdlcoderFocCurrentFloatHdl/FOC_Current_Control'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoderFocCurrentFloatHdl', { 'HDL Code Generation' } )">hdlcoderFocCurrentFloatHdl</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoderFocCurrentFloatHdl'.
### Working on the model 'hdlcoderFocCurrentFloatHdl'...
### Working on... <a href="matlab:configset.internal.open('hdlcoderFocCurrentFloatHdl', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoderFocCurrentFloatHdl' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### To highlight blocks that obstruct distributed pipelining, click the following MATLAB script: <a href="matlab:run('hdlsrc\hdlcoderFocCurrentFloatHdl\highlightDistributedPipeliningBarriers')">hdlsrc\hdlcoderFocCurrentFloatHdl\highlightDistributedPipeliningBarriers.m</a>
### To clear highlighting, click the following MATLAB script: <a href="matlab:run('hdlsrc\hdlcoderFocCurrentFloatHdl\clearhighlighting.m')">hdlsrc\hdlcoderFocCurrentFloatHdl\clearhighlighting.m</a>
### Generating new validation model: <a href="matlab:open_system('hdlsrc\hdlcoderFocCurrentFloatHdl\gm_hdlcoderFocCurrentFloatHdl_vnl')">gm_hdlcoderFocCurrentFloatHdl_vnl</a>.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdlcoderFocCurrentFloatHdl'.
### MESSAGE: The design requires 800 times faster clock with respect to the base rate = 2e-05.
### Begin VHDL Code Generation for 'FOC_Current_Control_tc'.
### Working on FOC_Current_Control_tc as hdlsrc\hdlcoderFocCurrentFloatHdl\FOC_Current_Control_tc.vhd.
### Code Generation for 'FOC_Current_Control_tc' completed.
### Working on... <a href="matlab:configset.internal.open('hdlcoderFocCurrentFloatHdl', 'Traceability')">Traceability</a>
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_gain_pow2_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_gain_pow2_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_mul_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_mul_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_add_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_add_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_sub_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_sub_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_relop_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_relop_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_relop_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_relop_single_block.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_relop_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_relop_single_block1.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_uminus_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_uminus_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_sincos_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_sincos_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_add2_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_add2_single.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_relop_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_relop_single_block2.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control/nfp_relop_single as hdlsrc\hdlcoderFocCurrentFloatHdl\nfp_relop_single_block3.vhd.
### Working on hdlcoderFocCurrentFloatHdl/FOC_Current_Control as hdlsrc\hdlcoderFocCurrentFloatHdl\FOC_Current_Control.vhd.
### Generating package file hdlsrc\hdlcoderFocCurrentFloatHdl\FOC_Current_Control_pkg.vhd.
### Code Generation for 'hdlcoderFocCurrentFloatHdl' completed.
### Generating HTML files for code generation report at <a href="matlab:web('C:\Users\samule\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\samule.Bdoc23b.j2314217\hdlcoder-ex95119120\hdlsrc\hdlcoderFocCurrentFloatHdl\html\hdlcoderFocCurrentFloatHdl_codegen_rpt.html')">hdlcoderFocCurrentFloatHdl_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///C:/Users/samule/OneDrive%20-%20MathWorks/Documents/MATLAB/ExampleManager/samule.Bdoc23b.j2314217/hdlcoder-ex95119120/hdlsrc/hdlcoderFocCurrentFloatHdl/FOC_Current_Control_report.html
### HDL check for 'hdlcoderFocCurrentFloatHdl' complete with 0 errors, 0 warnings, and 2 messages.
### HDL code generation complete.

Half-Precision FOC Model

For applications that require smaller dynamic range, you can use half types without having to convert your design to use fixed-point types. Using half types consumes much less memory, has lower latency, and saves FPGA resources.

Advantages of half-precision floating point types in hardware perspective:

  • Low latency

  • Low Area

  • High speed

  • 16-bit floating point behavior which will be useful for optimal storage

  • Wider dynamic range compared to integer or fixed point data types of same size

Half-precision types have same features as single- and double-precision floating-point types. Supported operators include basic arithmetic operators(EX: Add/Sub, Mul, Div/Recip) and Gain, Relational operators, Data type conversions.

load_system('hdlcoderFocCurrentFloatHalfHdl');
open_system('hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control')

To verify the behavior through simulation, run these commands:

hasSimPowerSystems = license ('test', 'Power_System_Blocks');
if hasSimPowerSystems
   open_system('hdlcoderFocCurrentTestBench')

   % set half-precision floating-point model in the testbench
   set_param('hdlcoderFocCurrentTestBench/Controller', 'ModelName', 'hdlcoderFocCurrentFloatHalfHdl');

   set_param('hdlcoderFocCurrentTestBench','IgnoredZcDiagnostic','none');
   sim('hdlcoderFocCurrentTestBench')
   set_param('hdlcoderFocCurrentTestBench','IgnoredZcDiagnostic','warn');
end

You can generate HDL code and view the generated code for the controller.

hdlset_param('hdlcoderFocCurrentFloatHalfHdl', 'FloatingPointTargetConfiguration', hdlcoder.createFloatingPointTargetConfig('NATIVEFLOATINGPOINT'));
makehdl('hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control');
### Generating HDL for 'hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoderFocCurrentFloatHalfHdl', { 'HDL Code Generation' } )">hdlcoderFocCurrentFloatHalfHdl</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoderFocCurrentFloatHalfHdl'.
### Begin compilation of the model 'hdlcoderFocCurrentFloatHalfHdl'...
### Begin compilation of the model 'hdlcoderFocCurrentFloatHalfHdl'...
### Working on the model 'hdlcoderFocCurrentFloatHalfHdl'...
### Working on... <a href="matlab:configset.internal.open('hdlcoderFocCurrentFloatHalfHdl', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoderFocCurrentFloatHalfHdl' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### To highlight blocks that obstruct distributed pipelining, click the following MATLAB script: <a href="matlab:run('hdlsrc\hdlcoderFocCurrentFloatHalfHdl\highlightDistributedPipeliningBarriers')">hdlsrc\hdlcoderFocCurrentFloatHalfHdl\highlightDistributedPipeliningBarriers.m</a>
### To clear highlighting, click the following MATLAB script: <a href="matlab:run('hdlsrc\hdlcoderFocCurrentFloatHalfHdl\clearhighlighting.m')">hdlsrc\hdlcoderFocCurrentFloatHalfHdl\clearhighlighting.m</a>
### Generating new validation model: <a href="matlab:open_system('hdlsrc\hdlcoderFocCurrentFloatHalfHdl\gm_hdlcoderFocCurrentFloatHalfHdl_vnl')">gm_hdlcoderFocCurrentFloatHalfHdl_vnl</a>.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdlcoderFocCurrentFloatHalfHdl'.
### MESSAGE: The design requires 800 times faster clock with respect to the base rate = 2e-05.
### Begin VHDL Code Generation for 'FOC_Current_Control_tc'.
### Working on FOC_Current_Control_tc as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\FOC_Current_Control_tc.vhd.
### Code Generation for 'FOC_Current_Control_tc' completed.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_gain_pow2_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_gain_pow2_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_add_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_add_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_mul_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_mul_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_sub_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_sub_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_relop_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_relop_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_relop_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_relop_half_block.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_uminus_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_uminus_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_relop_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_relop_half_block1.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_convert_sfix_16_En14_to_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_convert_sfix_16_En14_to_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_convert_half_to_sfix_16_En8 as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_convert_half_to_sfix_16_En8.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_add2_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_add2_half.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_relop_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_relop_half_block2.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control/nfp_relop_half as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\nfp_relop_half_block3.vhd.
### Working on hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control as hdlsrc\hdlcoderFocCurrentFloatHalfHdl\FOC_Current_Control.vhd.
### Generating package file hdlsrc\hdlcoderFocCurrentFloatHalfHdl\FOC_Current_Control_pkg.vhd.
### Code Generation for 'hdlcoderFocCurrentFloatHalfHdl' completed.
### Generating HTML files for code generation report at <a href="matlab:web('C:\Users\samule\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\samule.Bdoc23b.j2314217\hdlcoder-ex95119120\hdlsrc\hdlcoderFocCurrentFloatHalfHdl\html\hdlcoderFocCurrentFloatHalfHdl_codegen_rpt.html')">hdlcoderFocCurrentFloatHalfHdl_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///C:/Users/samule/OneDrive%20-%20MathWorks/Documents/MATLAB/ExampleManager/samule.Bdoc23b.j2314217/hdlcoder-ex95119120/hdlsrc/hdlcoderFocCurrentFloatHalfHdl/FOC_Current_Control_report.html
### HDL check for 'hdlcoderFocCurrentFloatHalfHdl' complete with 0 errors, 1 warnings, and 3 messages.
### HDL code generation complete.

You can refer to documentation for full native floating-point capabilities available in HDL Coder. See link in the Getting Started with HDL Coder Native Floating-Point Support.