SuperAPI AI Directory

matlab-simulate-rf-system

General & other

View repository

Updated 10-16 00:21

About this skill

RF System Time-Domain Simulation

Run high-accuracy time-domain simulation on an RF signal chain using the rfsystem System Object. Under the hood, rfsystem auto-generates and manages a Simulink/RF Blockset model -- the user works entirely in MATLAB with the standard System Object step/reset/release interface.

When to Use

  • Running circuit envelope or idealized baseband time-domain simulation on an rfbudget chain
  • Streaming time-domain data through an RF system for EVM, power, or spectral analysis
  • Modeling MISO receivers or SIMO transmitters
  • Inspecting auto-generated RF Blockset Simulink models
  • Comparing Friis/HarmonicBalance budget results against full time-domain simulation

When NOT to Use

  • Cascade budget analysis (gain, NF, IP3) without time-domain -- use matlab-analyze-rf-budget
  • Standalone baseband signal processing without Simulink -- use matlab-process-rf-baseband
  • Frequency-domain S-parameter analysis -- use matlab-manage-sparameters
  • Building circuit topologies from R/L/C elements -- use matlab-compose-rf-circuit

Workflow

  1. Build rfbudget -- Define the RF chain (see matlab-analyze-rf-budget and matlab-create-rfbudget-elements skills)
  2. Create rfsystem -- Pass the rfbudget to rfsystem with desired library and options
  3. Stream data -- Call rfs(in) repeatedly with frame-sized input vectors
  4. Analyze output -- Measure power, EVM, spectrum, etc. on the time-domain output
  5. Clean up -- release(rfs) then close_system(rfs, 0)

Creating an rfsystem

% Build an rfbudget first
lna = amplifier('Gain', 15, 'NF', 2, 'OIP3', 35, 'Name', 'LNA');
mix = modulator('Gain', -6, 'NF', 10, 'OIP3', 20, ...
    'LO', 2.1e9, 'ConverterType', 'Down', 'Name', 'Mixer');
ifAmp = amplifier('Gain', 20, 'NF', 4, 'OIP3', 30, 'Name', 'IFAmp');
b = rfbudget([lna mix ifAmp], 2.4e9, -30, 10e6);

% Create rfsystem (default: CircuitEnvelope)
rfs = rfsystem(b);

% With options
rfs = rfsystem(b, ...
    ModelName='MyReceiver', ...
    Library='CircuitEnvelope', ...
    SampleTime=1e-8);

Constructor: rfsystem(rfbudget, Name=Value)

Properties

Property Default Description
ModelName 'untitled' Name of auto-generated Simulink model
SampleTime 1/(bw*8) Time step for simulation (seconds)
InputFrequency from budget Row vector of input carrier frequencies (Hz)
OutputFrequency from budget Row vector of output carrier frequencies (Hz)
RFInputs from budget Number of RF inputs (read-only)
RFOutputs from budget Number of RF outputs (read-only)
Library 'CircuitEnvelope' 'CircuitEnvelope' or 'IdealizedBaseband'
Rx 1 Number of input chains (MISO receiver)
Tx 1 Number of output chains (SIMO transmitter)
SLInputs 0 Number of extra Simulink input ports
SLOutputs 0 Number of extra Simulink output ports
Mismatch false Model impedance mismatch loss (IdealizedBaseband only)

Library Modes

rfsystem supports two modes. RF Blockset itself supports a third (Equivalent Baseband) that is accessible only from the Simulink model generated by exportRFBlockset(b). Both IdealizedBaseband and Equivalent Baseband process complex baseband signals and model nonlinear compression; CircuitEnvelope additionally resolves multi-carrier and mismatch effects. The legacy rfckt analysis workflow (analyze) is equivalent baseband under the hood.

CircuitEnvelope (Default)

Full RF Blockset circuit envelope simulation. Supports all rfbudget element types and provides the highest accuracy -- accounts for nonlinear compression, intermodulation, impedance mismatch, and multi-carrier effects.

rfs = rfsystem(b, Library='CircuitEnvelope');

Supported elements: amplifier, modulator, rffilter, nport, rfelement, attenuator, phaseshift, seriesRLC, shuntRLC, lcladder, mixerIMT.

IdealizedBaseband

Faster simulation using idealized complex baseband models. More restrictive on element types but significantly faster for large signal chains.

rfs = rfsystem(b, Library='IdealizedBaseband');

Supported elements: amplifier, modulator, rffilter, nport only.

Gotcha: IdealizedBaseband rejects rfelement, attenuator, phaseshift, seriesRLC, shuntRLC, lcladder, mixerIMT, and rfantenna with "Expected elements in rfobj to be one of these types: amplifier, modulator, rffilter, nport." Replace unsupported elements or use CircuitEnvelope.

Mismatch Loss

rfs = rfsystem(b, Library='IdealizedBaseband', Mismatch=true);

Gotcha: Mismatch=true only works with IdealizedBaseband. Using it with CircuitEnvelope errors.

Running Simulation (step)

The rfsystem object follows the standard System Object streaming pattern: call rfs(in) repeatedly with frame-sized input vectors.

rfs = rfsystem(b);
Ts = rfs.SampleTime;

% Input: complex baseband envelope at InputFrequency
% Power scaling: Vin = sqrt(2 * Z0 * Pin_W) for a 50-ohm system
Pin_dBm = -30;
Pin_W = 10^((Pin_dBm - 30) / 10);
Vin = sqrt(2 * 50 * Pin_W);

% Single frame
nSamples = 100;
inSig = Vin * ones(nSamples, 1);       % CW tone
out = rfs(inSig);

% Measure output power
Pout_dBm = 10*log10(mean(abs(out).^2 / (2*50))) + 30;
fprintf('Output: %.2f dBm\n', Pout_dBm);

Multi-Frame Streaming

Call step repeatedly -- the system accumulates state across frames:

nFrames = 10;
frameLen = 256;
allOut = zeros(frameLen * nFrames, 1);

for k = 1:nFrames
    inFrame = Vin * randn(frameLen, 1) + 1j * Vin * randn(frameLen, 1);
    outFrame = rfs(inFrame);
    allOut((k-1)*frameLen + (1:frameLen)) = outFrame;
end

Modulated Signal Example

% QPSK signal through receiver chain
rng(42);
nSym = 1000;
symbols = (2*randi([0 1], nSym, 1) - 1) + 1j*(2*randi([0 1], nSym, 1) - 1);
inMod = Vin * symbols / sqrt(2);

outMod = rfs(inMod);
Pout = 10*log10(mean(abs(outMod).^2 / (2*50))) + 30;
fprintf('Modulated output: %.2f dBm\n', Pout);

Zero-IF (Direct Conversion)

When the rfbudget output frequency is 0 Hz (fRF = fLO), the output splits into separate I and Q components. The RFOutputs property becomes 2.

% Direct-conversion receiver: fRF = fLO
lna = amplifier('Gain', 15, 'NF', 2, 'OIP3', 35, 'Name', 'LNA');
mix = modulator('Gain', -6, 'NF', 10, 'OIP3', 20, ...
    'LO', 2.4e9, 'ConverterType', 'Down', 'Name', 'Mixer');
ifAmp = amplifier('Gain', 20, 'NF', 4, 'OIP3', 30, 'Name', 'IFAmp');
b = rfbudget([lna mix ifAmp], 2.4e9, -30, 10e6);

rfs = rfsystem(b);
fprintf('RFOutputs: %d\n', rfs.RFOutputs);   % 2 (I and Q)

% Step returns separate I and Q
[outI, outQ] = rfs(inSig);
outComplex = outI + 1j * outQ;               % Reconstruct complex baseband

Gotcha: When OutputFrequency is 0, RFOutputs becomes 2 and the step method returns two output arguments (I and Q). Using a single output out = rfs(in) gives only the I component.

MISO Receiver and SIMO Transmitter

MISO Receiver (Multiple Inputs, Single Output)

rfs = rfsystem(b, Rx=2);
fprintf('RFInputs: %d\n', rfs.RFInputs);     % 2

% Two RF inputs combined into one output
out = rfs(in1, in2);

SIMO Transmitter (Single Input, Multiple Outputs)

% Up-conversion transmitter chain
upMix = modulator('Gain', -6, 'NF', 10, 'OIP3', 20, ...
    'LO', 2.1e9, 'ConverterType', 'Up', 'Name', 'UpMixer');
pa = amplifier('Gain', 25, 'NF', 5, 'OIP3', 40, 'Name', 'PA');
bTx = rfbudget([upMix pa], 0.3e9, -10, 10e6);

rfsTx = rfsystem(bTx, Tx=2);
fprintf('RFOutputs: %d\n', rfsTx.RFOutputs);  % 2

[out1, out2] = rfsTx(inSig);

Simulink I/O Ports (SLInputs / SLOutputs)

Add extra Simulink ports for control signals or monitoring:

rfs = rfsystem(b, SLInputs=1, SLOutputs=1);

% Step with RF input and Simulink control input
[outRF, outSL] = rfs(inRF, inSL);

System Object Lifecycle

reset -- Clear Internal State

Restarts simulation clock to t=0 (clears operating point). Can call step again immediately without unlocking properties:

reset(rfs);
out = rfs(newInput);        % Fresh simulation from t=0

release -- Allow Property Changes

Unlocks properties for modification. After release, SampleTime, InputFrequency, etc. can be changed:

release(rfs);
rfs.SampleTime = 5e-9;     % Change sample time
out = rfs(newInput);        % Re-runs setup on next step

Summary: reset = restart clock, release = unlock properties.

Gotcha: Properties are locked while the system is in use (between first step and release). Attempting to set a property without calling release first errors.

Model Management

The auto-generated Simulink model can be inspected, modified, and saved:

rfs = rfsystem(b, ModelName='MyReceiver');

load_system(rfs);           % Load model into memory (no GUI)
open_system(rfs);           % Open model in Simulink editor
hide_system(rfs);           % Hide model window
save_system(rfs);           % Save model to disk
save_system(rfs, 'NewName');% Save with new name
close_system(rfs, 0);       % Close without saving (0 = discard changes)
close_system(rfs, 1);       % Close and save

Gotcha: close_system(rfs) with no second argument errors if the model has unsaved changes: "Unable to close the model because it has been changed." Always use close_system(rfs, 0) to discard or close_system(rfs, 1) to save.

Inspecting the Model

load_system(rfs);
blocks = find_system(rfs.ModelName, 'Type', 'Block');
for k = 1:numel(blocks)
    fprintf('%s\n', blocks{k});
end

The model contains RF Blockset blocks corresponding to each rfbudget element, plus Inport/Outport blocks for the RF and Simulink I/O.

rfBudgetAnalyzer

Open the RF Budget Analyzer app pre-loaded with the rfsystem's budget:

rfBudgetAnalyzer(rfs);

SampleTime Selection

Default: 1 / (rfbudget.SignalBandwidth * 8) -- 8 samples per signal bandwidth period. Decrease for higher time resolution; increase for faster simulation.

rfs = rfsystem(b, SampleTime=1e-9);   % 1 ns time step

Element Compatibility Summary

Element CircuitEnvelope IdealizedBaseband
amplifier Yes Yes
modulator Yes Yes
rffilter Yes Yes
nport Yes Yes
rfelement Yes No
attenuator Yes No
phaseshift Yes No
seriesRLC Yes No
shuntRLC Yes No
lcladder Yes No
mixerIMT Yes No
rfantenna No No

Gotchas

  1. Requires rfbudget -- rfsystem takes an rfbudget object, not raw elements or a circuit. Build the budget first.
  2. close_system needs save flag -- close_system(rfs) errors on unsaved models. Use close_system(rfs, 0) to discard changes.
  3. IdealizedBaseband element restrictions -- Only amplifier, modulator, rffilter, nport. Other types error at construction.
  4. Mismatch only with IdealizedBaseband -- Mismatch=true errors with CircuitEnvelope.
  5. Zero-IF splits I/Q -- When OutputFrequency=0, RFOutputs becomes 2 and step returns [I, Q] not a single complex output.
  6. rfantenna not supported -- Neither library mode supports rfantenna in the chain.
  7. Properties locked during use -- Cannot change SampleTime, InputFrequency, etc. between step calls. Call release(rfs) first.
  8. SampleTime default is bandwidth-derived -- 1/(SignalBandwidth*8). For wideband signals, this can produce very small time steps and slow simulation.
  9. Simulink license required -- rfsystem requires a Simulink license even though the user never sees Simulink directly.
  10. ModelName must be valid -- Must be a valid Simulink model name (valid MATLAB identifier, no spaces).
  11. Element Name must be a valid variable name -- 'IF Filter' errors with "not valid variable names." Use 'IFFilter' or 'IF_Filter' (no spaces, no special characters). This applies to all rfbudget element Name properties.
  12. Clone elements before reusing in a second rfbudget -- An element object can only belong to one rfbudget at a time. Reusing it errors with "Element is already in another rfbudget." Use clone(element) to create an independent copy for each budget.

Conventions

  • Use tiledlayout/nexttile for multi-panel time-domain and spectral plots
  • Always label axes with units (dBm, ns, MHz) and include figure titles
  • Call close_system(rfs, 0) in cleanup to avoid orphaned Simulink models
  • Compare rfsystem output against rfbudget Friis results to quantify nonlinear effects -- deltas of 0.5-2 dB are normal at backed-off power levels due to compression; larger deltas indicate operation near saturation

Copyright 2026 The MathWorks, Inc.