Main Content

Automated Fixed-Point Conversion Best Practices

When you convert floating-point MATLAB® code to fixed-point code using the MATLAB Coder™ app, follow these best practices.

Create a Test File

A best practice for structuring your code is to separate your core algorithm from other code that you use to test and verify the results. Create a test file to call your original MATLAB algorithm and fixed-point versions of the algorithm. For example, as shown in the following table, you might set up some input data to feed into your algorithm, and then, after you process that data, create some plots to verify the results. Since you need to convert only the algorithmic portion to fixed point, it is more efficient to structure your code so that you have a test file, in which you create your inputs, call your algorithm, and plot the results, and one (or more) algorithmic files, in which you do the core processing.

Original codeBest PracticeModified code
% TEST INPUT
x = randn(100,1);

% ALGORITHM
y = zeros(size(x));
y(1) = x(1);
for n=2:length(x)
  y(n)=y(n-1) + x(n);
end

% VERIFY RESULTS
yExpected=cumsum(x);
plot(y-yExpected)
title('Error')

Issue

Generation of test input and verification of results are intermingled with the algorithm code.

Fix

Create a test file that is separate from your algorithm. Put the algorithm in its own function.

Test file

% TEST INPUT
x = randn(100,1);

% ALGORITHM
y = cumulative_sum(x);

% VERIFY RESULTS
yExpected = cumsum(x);
plot(y-yExpected)
title('Error')

Algorithm in its own function

function y = cumulative_sum(x)
  y = zeros(size(x));
  y(1) = x(1);
  for n=2:length(x)
    y(n) = y(n-1) + x(n);
  end
end

You can use the test file to:

  • Verify that your floating-point algorithm behaves as you expect before you convert it to fixed point. The floating-point algorithm behavior is the baseline against which you compare the behavior of the fixed-point versions of your algorithm.

  • Propose fixed-point data types.

  • Compare the behavior of the fixed-point versions of your algorithm to the floating-point baseline.

  • Help you determine initial values for static ranges.

Your test files should exercise the algorithm over its full operating range so that the simulation ranges are accurate. For example, for a filter, realistic inputs are impulses, sums of sinusoids, and chirp signals. With these inputs, using linear theory, you can verify that the outputs are correct. Signals that produce maximum output are useful for verifying that your system does not overflow. The quality of the proposed fixed-point data types depends on how well the test files cover the operating range of the algorithm with the accuracy that you want.

By default, the MATLAB Coder app shows code coverage results. Reviewing code coverage results helps you verify that your test file is exercising the algorithm adequately. Review code flagged with a red code coverage bar because this code is not executed. If the code coverage is inadequate, modify the test file or add more test files to increase coverage. See Code Coverage.

Prepare Your Algorithm for Code Generation

The automated conversion process instruments your code and provides data type proposals to help you convert your algorithm to fixed point.

MATLAB algorithms that you want to convert to fixed point automatically must comply with code generation requirements and rules. To view the subset of the MATLAB language that is supported for code generation, see Functions and Objects Supported for C/C++ Code Generation.

To help you identify unsupported functions or constructs in your MATLAB code, add the %#codegen pragma to the top of your MATLAB file. The MATLAB Code Analyzer flags functions and constructs that are not available in the subset of the MATLAB language supported for code generation. This advice appears in real time as you edit your code in the MATLAB editor. For more information, see Check Code with the Code Analyzer. The software provides a link to a report that identifies calls to functions and the use of data types that are not supported for code generation. For more information, see Check Code by Using the Code Generation Readiness Tool.

Check for Fixed-Point Support for Functions Used in Your Algorithm

The app flags unsupported function calls found in your algorithm on the Function Replacements tab. For example, if you use the fft function, which is not supported for fixed point, the tool adds an entry to the table on this tab and indicates that you need to specify a replacement function to use for fixed-point operations.

You can specify additional replacement functions. For example, functions like sin, cos,and sqrt might support fixed point, but for better efficiency, you might want to consider an alternative implementation like a lookup table or CORDIC-based algorithm. The app provides an option to generate lookup table approximations for continuous and stateless single-input, single-output functions in your original MATLAB code. See Replacing Functions Using Lookup Table Approximations.

Manage Data Types and Control Bit Growth

The automated fixed-point conversion process automatically manages data types and controls bit growth. It controls bit growth by using subscripted assignments, that is, assignments that use the colon (:) operator, in the generated code. When you use subscripted assignments, MATLAB overwrites the value of the left side argument but retains the existing data type and array size. In addition to preventing bit growth, subscripted assignment reduces the number of casts in the generated fixed-point code and makes the code more readable.

Convert to Fixed Point

What Are Your Goals for Converting to Fixed Point?

Before you start the conversion, consider your goals for converting to fixed point. Are you implementing your algorithm in C or HDL? What are your target constraints? The answers to these questions determine many fixed-point properties such as the available word length, fraction length, and math modes, as well as available math libraries.

To set up these properties, use the Advanced settings.

For more information, see Specify Type Proposal Options.

Run with Fixed-Point Types and Compare Results

Create a test file to validate that the floating-point algorithm works as expected before converting it to fixed point. You can use the same test file to propose fixed-point data types and to compare fixed-point results to the floating-point baseline after the conversion. For more information, see Running a Simulation.

Use the Histogram to Fine-Tune Data Type Settings

To fine-tune fixed-point type settings, use the histogram. For more information, see Log Data for Histogram.

To log data for histograms, in the app, click the Analyze arrow and select Log data for histogram.

After simulation and static analysis:

  • To view the histogram for a variable, on the Variables tab, click the Proposed Type field for that variable.

    You can view the effect of changing the proposed data types by dragging the edges of the bounding box in the histogram window to change the proposed data type and selecting or clearing the Signed option.

  • If the values overflow and the range cannot fit the proposed type, the table shows proposed types in red.

When the tool applies data types, it generates an html report that provides overflow information and highlights overflows in red. Review the proposed data types.

Optimize Your Algorithm

Use fimath to Get Optimal Types for C or HDL

fimath properties define the rules for performing arithmetic operations on fi objects, including math, rounding, and overflow properties. You can use the fimath ProductMode and SumMode properties to retain optimal data types for C or HDL. HDL can have arbitrary word length types in the generated HDL code, whereas C requires container types (uint8, uint16, uint32). Use the Advanced settings, see Specify Type Proposal Options.

C.  The KeepLSB setting for ProductMode and SumMode models the behavior of integer operations in the C language, while KeepMSB models the behavior of many DSP devices. Different rounding methods require different amounts of overhead code. Setting the RoundingMethod property to Floor, which is equivalent to two's complement truncation, provides the most efficient rounding implementation. Similarly, the standard method for handling overflows is to wrap using modulo arithmetic. Other overflow handling methods create costly logic. Whenever possible, set OverflowAction to Wrap.

MATLAB CodeBest PracticeGenerated C Code

Code being compiled

function y = adder(a,b)
  y = a + b;
end

Note

In the app, set Default word length to 16.

Issue

With the default word length set to 16 and the default fimath settings, additional code is generated to implement saturation overflow, nearest rounding, and full-precision arithmetic.

int adder(short a, short b)
{
  int y;
  int i;
  int i1;
  int i2;
  int i3;
  i = a;
  i1 = b;
  if ((i & 65536) != 0) {
    i2 = i | -65536;
  } else {
    i2 = i & 65535;
  }

  if ((i1 & 65536) != 0) {
    i3 = i1 | -65536;
  } else {
    i3 = i1 & 65535;
  }

  i = i2 + i3;
  if ((i & 65536) != 0) {
    y = i | -65536;
  } else {
    y = i & 65535;
  }

  return y;
}

Fix

To make the generated C code more efficient, choose fixed-point math settings that match your processor types.

To customize fixed-point type proposals, use the app Settings. Select fimath and then set:

int adder(short a, short b)
{
  return a + b;
}
Rounding methodFloor
Overflow actionWrap
Product mode KeepLSB
Sum modeKeepLSB
Product word length32
Sum word length32

HDL.  For HDL code generation, set:

  • ProductMode and SumMode to FullPrecision

  • Overflow action to Wrap

  • Rounding method to Floor

Replace Built-in Functions with More Efficient Fixed-Point Implementations

Some MATLAB built-in functions can be made more efficient for fixed-point implementation. For example, you can replace a built-in function with a lookup table implementation or a CORDIC implementation, which requires only iterative shift-add operations. For more information, see Function Replacements.

Reimplement Division Operations Where Possible

Often, division is not fully supported by hardware and can result in slow processing. When your algorithm requires a division, consider replacing it with one of the following options:

  • Use bit shifting when the denominator is a power of two. For example, bitsra(x,3) instead of x/8.

  • Multiply by the inverse when the denominator is constant. For example, x*0.2 instead of x/5.

  • If the divisor is not constant, use a temporary variable for the division. Doing so results in a more efficient data type proposal and, if overflows occur, makes it easier to see which expression is overflowing.

Eliminate Floating-Point Variables

For more efficient code, the automated fixed-point conversion process eliminates floating-point variables. The one exception to this is loop indices because they usually become integer types. It is good practice to inspect the fixed-point code after conversion to verify that there are no floating-point variables in the generated fixed-point code.

Avoid Explicit Double and Single Casts

For the automated workflow, do not use explicit double or single casts in your MATLAB algorithm to insulate functions that do not support fixed-point data types. The automated conversion tool does not support these casts.

Instead of using casts, supply a replacement function. For more information, see Function Replacements.

See Also

| | | |