Main Content

Map Persistent Arrays and dsp.Delay Objects to RAM

R2026b

If your MATLAB code or Simulink MATLAB Function block contains long persistent arrays or dsp.Delay System object™ objects, you can reduce the FPGA resources that your design uses by mapping them to block RAM. When you enable RAM mapping, the code generator evaluates each persistent array or dsp.Delay object and maps the ones that meet certain criteria to RAM. The resulting design uses fewer resources but has higher latency.

Use RAM mapping when your persistent arrays or delays are large enough that a register-based implementation wastes FPGA area. For small arrays, such as arrays that have fewer than 16 elements, or for timing-critical paths where the additional cycle of latency is unacceptable, use a register-based implementation. For more information on RAM mapping, see Apply RAM Mapping to Optimize Area.

How RAM Mapping Changes the Generated Hardware

Without RAM mapping, a persistent array generates a bank of registers and a dsp.Delay System object generates a chain of registers. With RAM mapping, both elements map to a Simple Dual Port RAM instance with automatically generated address counters and pipeline registers.

This diagram shows the generated hardware for a function persist_array_ram that reads and writes a persistent array:

function y = persist_array_ram(u, addr)
persistent myArray;
if isempty(myArray)
    myArray = fi(zeros(32,1), 1, 16, 8);
end
y = myArray(addr);
myArray(addr) = u;

The code generator maps myArray to a Simple Dual Port RAM instance and generates address logic that computes addr - 1, which converts 1-based MATLAB indexing to 0-based hardware addressing. The write enable is always asserted because every call writes to the array.

This diagram shows the generated hardware for a function that uses a dsp.Delay System object with the Length property equal to 16:

function y = dsp_delay_ram_design(u)
%#codegen
persistent delayObj;
if isempty(delayObj)
    delayObj = dsp.Delay('Length', 16, 'InitialConditions', 0);
end
y = delayObj(u);

When RAM mapping is off, the dsp.Delay generates a chain of 16 registers. When RAM mapping is on, the delay maps to a Simple Dual Port RAM instance, with automatically generated address counters and pipeline registers.

Enable RAM Mapping

The setting that enables RAM mapping controls both persistent arrays and dsp.Delay System object objects. When you turn it on, the code generator evaluates every candidate against its element-specific requirements. See RAM Mapping Requirements for Persistent Arrays and User-Defined System object Properties.

When this setting is off, persistent arrays and dsp.Delay objects map to registers in the generated HDL code.

In MATLAB Code

To enable persistent array RAM mapping from the command line, set properties on the coder.HdlConfig object:

hdlcfg = coder.HdlConfig;
hdlcfg.MapPersistentVarsToRAM = true;
hdlcfg.RAMThreshold = "256";

The RAMThreshold property accepts a string value. You can specify either a single integer threshold or a two-dimensional threshold with the format "MxN", where M is the minimum array size and N is the minimum word length. For example:

hdlcfg.RAMThreshold = "8x16";

In a MATLAB Function Block

To enable persistent array RAM mapping inside a MATLAB Function block in a Simulink model, set the MapPersistentVarsToRAM HDL block property on the block, and set the model-level RAMMappingThreshold model configuration parameter:

hdlset_param(mlfbBlock, "MapPersistentVarsToRAM", "on");
hdlset_param(model, "RAMMappingThreshold", 256);

The MapPersistentVarsToRAM property is set on the MATLAB Function block, not on the parent subsystem or model. The RAMMappingThreshold parameter accepts either an integer or a string in the format "MxN". For more information, see RAM mapping threshold.

Using the HDL Workflow Advisor

To enable persistent array RAM mapping in the MATLAB-to-HDL workflow with the HDL Workflow Advisor:

  1. In the left pane, click HDL Workflow Advisor > HDL Code Generation. Click the Optimizations tab.

  2. Select Map persistent array variables to RAMs.

  3. Set the RAM mapping threshold to either:

    • An integer that specifies the RAM size of the smallest persistent array or user-defined System object private property that you want to map to RAM.

    • A string in the format MxN that defines the shape of the data to map to RAM, where M is the array size and N is the word length or bit width of the data type. Setting both thresholds prevents small or narrow persistent arrays from mapping to block RAM.

RAM Mapping Requirements

Whether a persistent array or a dsp.Delay System object maps to RAM depends on the element type and a set of conditions. All conditions must be true for mapping to occur.

This image summarizes the RAM mapping decision logic. If any condition on the path is not met, the element maps to registers instead. To learn more about each RAM mapping condition, click the boxes in the image.

These sections describe each of these conditions in detail.

RAM Mapping Requirements for Persistent Arrays and User-Defined System object Properties

With RAM mapping enabled, a persistent array or user-defined System object private property maps to a block RAM when all of these conditions are true:

Each read or write access is for a single element only. For example, range-based indexing, such as myArray(1:4), and array copies are not supported. Multiple individual scalar reads at different indices are supported. HDL Coder generates a faster clock for the RAM to schedule the accesses sequentially within one base-clock cycle (local multirate).

Maps to RAMDoes Not Map to RAM
% Multiple scalar reads (2x overclocking)
y = myArray(addr) + myArray(addr+1);
% Range-based indexing
y(:) = myArray(1:4);

Address computation logic is not read-dependent. For example, the code generator does not support computation of a read or write address by using the data read from the array.

Maps to RAMDoes Not Map to RAM
% Address from external input
y = myArray(addr);
% Address depends on array data
idx = myArray(addr);
y = myArray(idx);

Persistent variables or user-defined System object private properties are initialized to zero using the zeros function. Non-zero initialization prevents RAM mapping because block RAM is zero-initialized by the FPGA bitstream.

Maps to RAMDoes Not Map to RAM
% Initialized to zero
persistent myArray;
myArray = fi(zeros(32,1), 1, 16, 8);
% Nonzero initialization
persistent myArray;
myArray = fi(ones(32,1), 1, 16, 8);

If an access is within a conditional statement, the condition expression must produce a scalar logical result. Any HDL-compatible expression is supported in the condition, including function calls such as mod, bitand, or user-defined functions. The condition becomes a write-enable signal in the generated HDL.

Maps to RAMMaps to RAM (with overclocking)
% Function call in condition
if (mod(addr, 2) > 0)
    y = myArray(addr);
end
% Condition depends on array data
if myArray(addr) > fi(0,1,16,8)
    y = myArray(addr+1);
end

The persistent array or user-defined System object private property value depends on external inputs.

Maps to RAMDoes Not Map to RAM
% Write depends on external input u
bigarray(idx+1) = u;
% Write depends only on internal state
bigarray(idx+1) = idx;

The RAM size is greater than or equal to the RAMThreshold value. The RAM size is the product of Array Size * Word Length * Complexity, where:

  • Array Size is the number of elements in the array.

  • Word Length is the number of bits that represent the data type of the array.

  • Complexity is 2 for a complex data type or 1 for a real data type.

Maps to RAMDoes Not Map to RAM
% 32 x 16 = 512 bits (threshold = 256)
persistent myArray;
myArray = fi(zeros(32,1), 1, 16, 8);
% 8 x 16 = 128 bits (threshold = 256)
persistent myArray;
myArray = fi(zeros(8,1), 1, 16, 8);

Access to the persistent variable that you are mapping to RAM is not in a loop, such as a for loop, unless the loop is unrolled. To unroll a loop, use the coder.unroll pragma or set LoopOptimization to 'UnrollLoops'. When an unrolled loop contains multiple accesses to the same persistent array, HDL Coder generates a faster clock for the RAM to schedule the accesses sequentially (local multirate).

Maps to RAMDoes Not Map to RAM
% Loop unrolled (4x overclocking)
for i = coder.unroll(1:4)
    y(:) = y + myArray(i);
end
% Loop access without unrolling
for i = 1:4
    y(:) = y + myArray(i);
end

If any of the above conditions is false, the persistent array or user-defined System object private property maps to a register in the HDL code.

RAM Mapping Requirements for dsp.Delay System Objects

A dsp.Delay System object maps to a block RAM when all of these conditions are true:

The Length property is greater than or equal to 4.

Maps to RAMDoes Not Map to RAM
% Length = 4 (threshold = '10')
delayObj = dsp.Delay('Length', 4, ...
    'InitialConditions', 0);
y = delayObj(u);
% Length = 3
delayObj = dsp.Delay('Length', 3, ...
    'InitialConditions', 0);
y = delayObj(u);

The InitialConditions property is 0. Block RAM is zero-initialized by the FPGA bitstream, so non-zero initial conditions prevent RAM mapping.

Maps to RAMDoes Not Map to RAM
% InitialConditions = 0
delayObj = dsp.Delay('Length', 16, ...
    'InitialConditions', 0);
y = delayObj(u);
% InitialConditions = 5
delayObj = dsp.Delay('Length', 16, ...
    'InitialConditions', 5);
y = delayObj(u);

The delay input data type is one of these types:

  • Real scalar with a non-floating-point data type

  • Real row vector (1-by-N) where each element has a non-floating-point data type

Maps to RAMDoes Not Map to RAM
% Real scalar fixed-point
u = fi(0, 1, 16, 8);
y = delayObj(u);
% Complex fixed-point
u = fi(complex(0,0), 1, 16, 8);
y = delayObj(u);
% Real row vector (1x4)
u = fi(zeros(1,4), 1, 16, 8);
y = delayObj(u);
% Column vector (4x1) - frame data
u = fi(zeros(4,1), 1, 16, 8);
y = delayObj(u);

Note

Complex data types and column vectors (N-by-1) do not support RAM mapping for dsp.Delay. Column vectors are interpreted as frame data in the MATLAB-to-HDL workflow and fail HDL code generation. To map a complex delay to RAM, split the input into real and imaginary parts by using separate dsp.Delay objects for each part:

yReal = delayReal(real(u));
yImag = delayImag(imag(u));
y = complex(yReal, yImag);

The RAM size is greater than or equal to the RAMThreshold value. The RAM size is the product of DelayLength * WordLength * VectorLength, where:

  • DelayLength is the value of the Length property.

  • WordLength is the number of bits that represent the input data type.

  • VectorLength is the number of elements in the row vector (1 for scalar inputs).

Maps to RAMDoes Not Map to RAM
% 16 * 16 * 1 = 256 bits (threshold = 256)
delayObj = dsp.Delay('Length', 16, ...
    'InitialConditions', 0);
u = fi(0, 1, 16, 8);
y = delayObj(u);
% 4 * 16 * 1 = 64 bits (threshold = 256)
delayObj = dsp.Delay('Length', 4, ...
    'InitialConditions', 0);
u = fi(0, 1, 16, 8);
y = delayObj(u);
% Row vector: 4 * 16 * 4 = 256 (threshold = 256)
delayObj = dsp.Delay('Length', 4, ...
    'InitialConditions', 0);
u = fi(zeros(1,4), 1, 16, 8);
y = delayObj(u);
 

If any of the conditions are false, the dsp.Delay System object maps to registers in the HDL code.

Additional dsp.Delay Considerations

The dsp.Delay System object supports only feed-forward delay modeling. You cannot use dsp.Delay to model feedback paths. A feedback path is one where the output depends on a previous value of the state. This pattern requires persistent variables instead of dsp.Delay System objects.

Supported dsp.Delay Feed-Forward DesignSupported Feedback Design with Persistent Variables
%#codegen
function y = feed_fwd(u)
delay = dsp.Delay('Length', 16);
y = u - delay(u);
%#codegen
function y = accumulate(u)
persistent p;
if isempty(p)
   p = 0;
end
y = p;
p = p + u;

Setting the Length property of a dsp.Delay System object to a value greater than 1 maps the delay to a shift register in the generated HDL code. Both hdl.Delay and dsp.Delay model pipeline registers. However, only dsp.Delay supports automatic mapping to RAM. hdl.Delay always maps to registers. To generate a local reset for a delay, use the dsp.Delay System object with the ResetInputPort property.

RAM Mapping Comparison

Three MATLAB code elements map to RAM, each suited to different use cases:

  • hdl.RAM — Full manual control over addresses, ports, and scheduling. Use for custom memory architectures.

  • dsp.Delay — Automatic delay-to-RAM conversion with no code changes. Use for long feed-forward delay lines.

  • Persistent arrays — Automatic RAM inference from indexed array patterns. Use for general-purpose memory access with read and write operations.

This table compares the implementation characteristics of each element type.

Characteristichdl.RAM Objectsdsp.Delay Objects Persistent Arrays and
User-Defined System object Properties
RAM mapping criteriaUnconditionally maps to RAMMaps to RAM in HDL code under specific conditions. See RAM Mapping Requirements for dsp.Delay System Objects.Maps to RAM in HDL code under specific conditions. See RAM Mapping Requirements for Persistent Arrays and User-Defined System object Properties.
Address generation and port mappingUser specifiedAutomaticAutomatic
Access schedulingUser specifiedAutomatically inferredAutomatically inferred
OverclockingNoneNoneLocal multirate (faster RAM clock), if the access schedule requires it. Compatible with clock-rate pipelining when the Oversampling factor is greater than 1.
Latency with respect to simulation in MATLAB®.00One cycle
RAM typeUser specifiedSimple dual portSimple dual port

See Also

| | (DSP System Toolbox) |

Topics