Map Persistent Arrays and dsp.Delay Objects to RAM
R2026bIf 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:
In the left pane, click HDL Workflow Advisor > HDL Code Generation. Click the Optimizations tab.
Select Map persistent array variables to RAMs.
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
MxNthat 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 RAM | Does 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 RAM | Does 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 RAM | Does 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 RAM | Maps 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 RAM | Does 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 Sizeis the number of elements in the array.Word Lengthis the number of bits that represent the data type of the array.Complexityis 2 for a complex data type or 1 for a real data type.
| Maps to RAM | Does 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 RAM | Does 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 RAM | Does 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 RAM | Does 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 RAM | Does 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:
DelayLengthis the value of theLengthproperty.WordLengthis the number of bits that represent the input data type.VectorLengthis the number of elements in the row vector (1 for scalar inputs).
| Maps to RAM | Does 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 Design | Supported 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.
| Characteristic | hdl.RAM
Objects | dsp.Delay
Objects | Persistent Arrays and
User-Defined System object Properties |
|---|---|---|---|
| RAM mapping criteria | Unconditionally maps to RAM | Maps 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 mapping | User specified | Automatic | Automatic |
| Access scheduling | User specified | Automatically inferred | Automatically inferred |
| Overclocking | None | None | Local 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®. | 0 | 0 | One cycle |
| RAM type | User specified | Simple dual port | Simple dual port |
See Also
coder.HdlConfig | hdl.RAM | dsp.Delay (DSP System Toolbox) | RAM mapping threshold