matlab-dsphdl-ddc-design

$npx mdskill add matlab/matlab-agentic-toolkit/matlab-dsphdl-ddc-design

Design and simulate a Digital Down Converter (DDC) using dsphdl System objects

  • Solves design challenges for FPGA/ASIC-based DDCs and receiver front-ends.
  • Deploys MATLAB's `dsphdl` System objects for NCO, mixer, decimation filter chains.
  • Determines optimal decimation strategies (integer or non-integer) based on input/output rates.
  • Generates synthesizable HDL code from the simulated design.

SKILL.md

.github/skills/matlab-dsphdl-ddc-designView on GitHub ↗
---
name: matlab-dsphdl-ddc-design
description: Use when designing a Digital Down Converter (DDC) using dsphdl System objects. Triggers on requests involving DDC design, frequency down-conversion for FPGA/ASIC, NCO + mixer + decimation filter chains, fractional/non-integer sample rate conversion, or HDL-optimized receiver front-end signal processing.
license: MathWorks BSD-3-Clause
metadata:
  author: MathWorks
  version: "1.0"
---

# dsphdl DDC: Design, Simulate, Generate HDL

## Overview

End-to-end MATLAB workflow for designing a Digital Down Converter (DDC) using `dsphdl` System objects — combining an NCO (local oscillator), complex mixer, and multi-stage decimation filter chain — then simulating the streaming HDL-optimized design and generating synthesizable HDL via HDL Coder.

**Integer decimation (all stages have integer rate change):**
```
RF Input → [Mixer] → [CIC Decimator] → [Compensation FIR Decimator] → Baseband Output
              ↑
           [NCO] (generates cos + jsin at carrier frequency)
```

**Non-integer decimation (uses Farrow for fine rate adjustment):**
```
RF Input → [Mixer] → [CIC Dec (xR)] → [Farrow (L/M)] → [FIR Dec (xD)] → Baseband Output
              ↑
           [NCO]
```

## When to Use

- Designing a DDC or receiver front-end for FPGA/ASIC
- Building an NCO + mixer + decimation chain with `dsphdl` objects
- **Non-integer decimation** — when the target output rate doesn't divide evenly into the input rate
- Converting a floating-point DDC algorithm to HDL-ready streaming architecture
- Generating Verilog/VHDL for a complete DDC subsystem

## When Not To Use

- Non-HDL workflows, e.g. embedded C code generation

## Critical Conventions

### NCO Phase Increment

**ALWAYS compute as:** `phaseInc = round((-Fc * 2^AccumulatorWL) / Fs)` where `Fc` is the carrier frequency, `Fs` is the input sample frequency, and `AccumulatorWL` is the NCO accumulator word length. This produces a negative integer. Never omit the negation or compute `round(Fc / Fs * 2^AccumulatorWL)` — the negative sign is required for correct down-conversion.

### Mixer: direct multiply with `fi()` arithmetic — NO conjugate

The mixer multiplies the input by the NCO output directly. **ALWAYS write it as a single `fi()` expression with NO `conj()`:**

```matlab
% DO — correct, concise, HDL-synthesizable:
mixed = fi(dataIn * ncoSample, 1, 16, 14);

% DON'T — conjugate the NCO (wrong convention for this toolbox):
% mixed = fi(dataIn * conj(ncoSample), 1, 16, 14);

% DON'T — manual I/Q decomposition (verbose, error-prone):
% cosVal = real(ncoOut); sinVal = imag(ncoOut);
% iMixed = fi(dataIn * cosVal, 1, 16, 14);
% qMixed = fi(dataIn * sinVal, 1, 16, 14);

% DON'T — double() arithmetic (NOT synthesizable for HDL):
% mixed = fi(double(dataIn) * double(ncoOut), 1, 16, 14);
```

### OutputDataType — ALWAYS use "Same word length as input"

**ALWAYS set `OutputDataType` to `'Same word length as input'`** on CIC and FIR stages. For Farrow, use `'Same as first input'` (equivalent property value). Never use `'Full precision'` — it causes excessive bit growth through the chain.

### FIR NumCycles for resource sharing

**ALWAYS set `NumCycles`** on FIR stages — see `references/numcycles.md` for full details.

### NCO PhaseIncrementSource

**ALWAYS set `PhaseIncrementSource` to `'Property'`** for fixed-frequency DDC designs. The default is `'Input port'`, which changes the step method signature from `nco(validIn)` to `nco(phaseInc, validIn)`.

### Valid signal piping — NEVER use if-statements on valid

**ALWAYS call every stage every clock cycle and pipe valid outputs to downstream valid inputs.** This matches the actual HDL hardware behavior where all stages run every clock cycle and valid propagates as a signal.

```matlab
% DO — pipe valid through the chain:
[ncoSample, ncoValid] = nco(validIn);
mixed = fi(dataIn * ncoSample, 1, 16, 14);
[cicSample, cicValid] = cicDec(mixed, ncoValid);
[dataOut, validOut] = firDec(cicSample, cicValid);

% DON'T — conditionally call downstream stages:
% [cicSample, cicV] = cicDec(mixed, true);
% if cicV
%     [firSample, firV] = firDec(cicSample, true);
% end
```

### Data-valid pairing — ALWAYS gate data with its corresponding valid

**Data outputs are only meaningful when the corresponding valid signal is true.** Always use `dataOut` together with `validOut` from the same stage. Never read, store, or process data samples without checking the valid that was returned alongside them.

```matlab
% DO — collect only valid output samples:
outputData = dataOut(validOut);

% DO — gate downstream processing on the valid from the same step call:
[dataOut, validOut] = firDec(cicSample, cicValid);
if validOut
    outputBuffer(idx) = dataOut;
    idx = idx + 1;
end

% DON'T — use dataOut without checking validOut:
% outputBuffer(ii) = dataOut;  % dataOut is garbage when validOut is false

% DON'T — mix valid from one stage with data from another:
% goodSamples = cicSample(validOut);  % validOut is from firDec, not cicDec
```

This applies to all stages: NCO, CIC, FIR, and Farrow. When a stage returns `[data, valid]`, those two outputs are paired — `data` is undefined when `valid` is false.

### Test signals — sinusoid modulated onto complex carrier

DDC inputs represent a baseband signal modulated onto a complex carrier. **ALWAYS construct the test signal as a real baseband waveform multiplied by a complex carrier exponential:**

```matlab
% DO — sinusoid modulated onto complex carrier:
inputSignal = cos(2*pi*Fsig*t) .* exp(1j*2*pi*Fc*t);
dataIn = fi(inputSignal, 1, 16, 14);  % fi() of complex input stays complex

% DO — complex codegen input type:
dataType = complex(fi(0, 1, 16, 14));

% DON'T — pure complex exponential at offset frequency (not a modulated signal):
% inputSignal = exp(1j*2*pi*(Fc + Fsig)*t);

% DON'T — real cos() signal (loses negative frequency content, wrong DDC behavior):
% inputSignal = cos(2*pi*(Fc + Fsig)*t);
```

After down-conversion, the expected baseband output is the original modulating waveform: `cos(2*pi*Fsig*t)`.

Do NOT pre-allocate `dataOut` or `validOut` in testbenches — let MATLAB grow them dynamically so the data type propagates from the DDC function output.

This applies to **all** generated code: design scripts, testbenches, and HDL codegen argument types.

### All System objects MUST be `persistent`

In the HDL function wrapper, declare all `dsphdl` objects as `persistent` and initialize inside `if isempty(...)`.

## Interactive Requirements Gathering (REQUIRED)

**Before generating any code, ALWAYS use AskUserQuestion to gather the user's DDC specifications. Ask exactly ONE question per AskUserQuestion call.** Do not assume defaults.

### Questions to ask (one at a time, in order):

1. **Sample rate and carrier:** "What is the input sampling frequency (Fs) and the carrier/IF frequency to down-convert?"
2. **Output rate:** "How would you like to specify the output rate?" (decimation factor or output sample rate in Hz). Compute `totalDecim = Fs / Fs_out`. **Check whether `totalDecim` is an integer** (i.e., `mod(Fs, Fs_out) == 0`). Only flag as non-integer if it truly is (e.g., 8.2, 12.5). Integer values like 25, 100, etc. are integer even if they are not powers of 2.
3. **Signal bandwidth:** "What is the desired passband bandwidth at the output?"
4. **Input data type:** "What is the input word length and format?" (e.g., 16-bit signed, 14 fractional)
5. **Decimation staging:** Present factorization options based on whether `totalDecim` is integer:
   - **If integer:** Only offer integer staging options (CIC+FIR, CIC+FIR+FIR, All FIR). Compute valid integer factor pairs/triples of `totalDecim` and present them. Do NOT offer Farrow-based options. **Every stage must actually change the sample rate (decimation factor >= 2). Never offer non-decimating FIR stages (factor = 1).**
   - **If non-integer:** Offer Farrow-based options (CIC+FIR+Farrow) alongside integer approximations. Explain the Farrow handles the fractional remainder. **The Farrow must always decimate (RateChange > 1, since RateChange = fsIn/fsOut).** Choose integer stages so that CIC_R * FIR_R <= total_decimation. Never offer staging where CIC_R * FIR_R > total_decimation (that would require Farrow interpolation).
6. **CIC parameters** (if CIC used): "How many CIC sections?"
7. **HDL language:** "Verilog or VHDL?" — just present the two options; do NOT offer commentary on what each language is good for or when to choose one over the other.

### After gathering requirements — compute derived parameters:

- Phase increment = `round((-Fc * 2^AccumulatorWL) / Fs)`
- CIC/FIR decimation factors (must be integer per stage)
- FIR `NumCycles` = cumulative decimation at that FIR's input (see `references/numcycles.md`)
- For non-integer: `total_decimation = CIC_R * FIR_R * farrowRateChange`, where `farrowRateChange = total_decimation / (CIC_R * FIR_R)` (close to 1, specified as fsIn/fsOut)
- **Validate:** `signalBandwidth/2 < Fs_out/2` — if not, the desired signal exceeds the output Nyquist rate and the specs are inconsistent. Tell the user to reduce bandwidth or increase output rate.

## Complete Workflow

### Step 1: Compute DDC Parameters

```matlab
%% DDC System Parameters
Fs = 100e6;           % Input sample rate (Hz)
Fc = 25e6;            % Carrier/IF frequency (Hz)
totalDecim = 16;      % Total decimation factor
Fs_out = Fs / totalDecim;  % Output sample rate

% Decimation staging: CIC handles bulk, FIR refines
cicDecimFactor = 8;   % CIC decimation
firDecimFactor = totalDecim / cicDecimFactor;  % FIR decimation = 2

% NCO phase increment for carrier frequency
accWL = 32;           % Accumulator word length (32-bit gives ~0.023 Hz resolution at 100 MHz)
phaseInc = round((-Fc * 2^accWL) / Fs);
fprintf('Phase increment: %d\n', phaseInc);
fprintf('Actual frequency: %.6f MHz\n', abs(phaseInc) * Fs / 2^accWL / 1e6);
```

### Step 2: Design CIC Compensation FIR

**ALWAYS use `dsp.CICCompensationDecimator` to design the compensation filter.** This designs a filter that inverts the CIC's passband droop (sinc^N rolloff) while providing the stopband rejection needed for the FIR decimation. Never use `fir1()` — it produces a generic lowpass that does not compensate CIC droop.

```matlab
%% Design CIC compensation filter using dsp.CICCompensationDecimator
cicNumSections = 4;
cicDiffDelay = 1;

Fs_afterCIC = Fs / cicDecimFactor;         % Sample rate after CIC (= FIR input rate)
Fpass = signalBandwidth / 2;               % Passband edge (half of desired signal BW)
Fstop = Fs_out / 2;                        % Stopband edge (output Nyquist)

cicDroopComp = dsp.CICCompensationDecimator(firDecimFactor, ...
    'SampleRate',          Fs_afterCIC, ...
    'CICRateChangeFactor', cicDecimFactor, ...
    'CICNumSections',      cicNumSections, ...
    'PassbandFrequency',   Fpass, ...
    'StopbandFrequency',   Fstop, ...
    'PassbandRipple',      0.1, ...
    'StopbandAttenuation', 50);
compCoeffs = cicDroopComp.coeffs.Numerator;
```

### Step 3: Instantiate dsphdl System Objects

```matlab
%% Create the DDC components

% NCO — generates complex exponential at carrier frequency
nco = dsphdl.NCO( ...
    'DesignMethod', 'NCO parameter', ...
    'PhaseIncrementSource', 'Property', ...
    'PhaseIncrement', phaseInc, ...
    'Waveform', 'Complex exponential', ...
    'AccumulatorWL', accWL, ...
    'OutputWL', 16, ...
    'OutputFL', 14, ...
    'NumDitherBits', 4, ...
    'PhaseQuantization', true, ...
    'NumQuantizerAccumulatorBits', 12);

% CIC Decimator — bulk decimation (efficient, no multipliers)
cicDec = dsphdl.CICDecimator( ...
    'DecimationFactor', cicDecimFactor, ...
    'DifferentialDelay', cicDiffDelay, ...
    'NumSections', cicNumSections, ...
    'OutputDataType', 'Same word length as input', ...
    'GainCorrection', true);

% FIR Decimator — compensation + final decimation
% NumCycles = cicDecimFactor: FIR input arrives every 8 clocks, so reuse multipliers
firDec = dsphdl.FIRDecimator( ...
    'DecimationFactor', firDecimFactor, ...
    'Numerator', compCoeffs, ...
    'NumCycles', cicDecimFactor, ...
    'OutputDataType', 'Same word length as input', ...
    'FilterStructure', 'Direct form systolic');
```

### Step 4: Simulate the DDC

```matlab
%% Simulate DDC end-to-end
numSamples = 1000 * totalDecim;
t = (0:numSamples-1)' / Fs;
Fsig = 1e6;
inputSignal = cos(2*pi*Fsig*t) .* exp(1j*2*pi*Fc*t);
dataIn = fi(inputSignal, 1, inputWL, inputFL);

for ii = 1:numSamples
    [ncoSample, ncoValid] = nco(true);
    mixed = fi(dataIn(ii) * ncoSample, 1, inputWL, inputFL);
    [cicSample, cicValid] = cicDec(mixed, ncoValid);
    [ddcOut(ii), ddcValid(ii)] = firDec(cicSample, cicValid);
end
outputData = ddcOut(ddcValid);
fprintf('DDC produced %d output samples from %d input samples\n', numel(outputData), numSamples);
```

### Step 5: Generate HDL

#### 5a. Create the Design Function

**IMPORTANT:** `dsp.CICCompensationDecimator` is NOT supported for HDL code generation. You MUST pre-compute the FIR coefficients by running the design script (Step 2) in MATLAB first, then hardcode the resulting numeric vector in the HDL function. Never call `dsp.CICCompensationDecimator` inside an HDL function — it will fail at `codegen` time.

```matlab
function [dataOut, validOut] = myDDC(dataIn, validIn)
%myDDC HDL-optimized Digital Down Converter

    persistent nco cicDec firDec;
    if isempty(nco)
        phaseInc = round((-25e6 * 2^32) / 100e6);
        nco = dsphdl.NCO( ...
            'DesignMethod', 'NCO parameter', ...
            'PhaseIncrementSource', 'Property', ...
            'PhaseIncrement', phaseInc, ...
            'Waveform', 'Complex exponential', ...
            'AccumulatorWL', 32, ...
            'OutputWL', 16, ...
            'OutputFL', 14, ...
            'NumDitherBits', 4, ...
            'PhaseQuantization', true, ...
            'NumQuantizerAccumulatorBits', 12);

        cicDec = dsphdl.CICDecimator( ...
            'DecimationFactor', 8, ...
            'DifferentialDelay', 1, ...
            'NumSections', 4, ...
            'OutputDataType', 'Same word length as input', ...
            'GainCorrection', true);

        % Coefficients pre-computed from dsp.CICCompensationDecimator in design script
        compCoeffs = [ ... ]; % <-- paste numeric vector from Step 2
        firDec = dsphdl.FIRDecimator( ...
            'DecimationFactor', 2, ...
            'Numerator', compCoeffs, ...
            'NumCycles', 8, ...
            'OutputDataType', 'Same word length as input', ...
            'FilterStructure', 'Direct form systolic');
    end

    [ncoSample, ncoValid] = nco(validIn);
    mixed = fi(dataIn * ncoSample, 1, 16, 14);
    [cicSample, cicValid] = cicDec(mixed, ncoValid);
    [dataOut, validOut] = firDec(cicSample, cicValid);
end
```

**Workflow for obtaining coefficients:** After running the design script (Step 2), execute `fprintf('%.15g, ', compCoeffs)` in MATLAB to get the numeric values, then paste them into the `compCoeffs` vector in the HDL function.

#### 5b. Create the Testbench

The testbench should run the DDC, print sample counts, and plot time-domain I/Q and frequency-domain output. Do NOT include correlation checks, normalization, or numeric pass/fail verification — just plot and let the user visually inspect.

**After running the testbench:** Print the sample counts and the rough decimation factor (`numInputSamples / numOutputSamples`). Do NOT add commentary or interpretation about the decimation factor — just print the numbers.

```matlab
%% DDC Testbench
clear myDDC;
totalDecim = 16; numSamples = 1000 * totalDecim;
Fs = 100e6; Fc = 25e6; Fs_out = Fs / totalDecim;
t = (0:numSamples-1)' / Fs;
Fsig = 1e6;
inputSignal = cos(2*pi*Fsig*t) .* exp(1j*2*pi*Fc*t);
dataIn = fi(inputSignal, 1, 16, 14);

for ii = 1:numSamples
    [dataOut(ii), validOut(ii)] = myDDC(dataIn(ii), true);
end
outputData = dataOut(validOut);
fprintf('DDC produced %d output samples from %d input samples\n', numel(outputData), numSamples);

%% Plot — time-domain I/Q and frequency-domain PSD
tOut = (0:numel(outputData)-1)' / Fs_out;
figure; subplot(2,1,1);
plot(tOut*1e6, real(double(outputData)), tOut*1e6, imag(double(outputData)));
xlabel('Time (\mus)'); ylabel('Amplitude'); title('DDC Output (I/Q)'); legend('I','Q'); grid on;
subplot(2,1,2); nfft = min(256, numel(outputData));
[psd, f] = pwelch(double(outputData), hanning(nfft), floor(nfft/2), nfft, Fs_out, 'centered');
plot(f/1e6, 10*log10(psd)); xlabel('Frequency (MHz)'); ylabel('PSD (dB/Hz)'); title('Output Spectrum'); grid on;
```

#### 5c. Generate HDL Code

```matlab
%% Generate HDL for DDC
hdlcfg = coder.config("hdl");
hdlcfg.TargetLanguage = 'Verilog';        % or 'VHDL'
hdlcfg.GenerateHDLTestBench = true;
hdlcfg.TestBenchName = 'myDDC_tb';

dataType = complex(fi(0, 1, 16, 14));  % scalar complex fixed-point input
codegen -config hdlcfg myDDC -args {dataType, false} -d hdl_output
```

**After HDL generation:** Do not display the resource utilization report or resource summary to the user. Just confirm that HDL generation succeeded (number of files, conformance errors) and list the key generated file paths.

## Non-Integer Decimation with Farrow Rate Converter

For non-integer decimation factors (e.g., 8.2, 12.5, 7.68), use integer CIC + FIR stages for bulk decimation and a `dsphdl.FarrowRateConverter` for the fractional fine adjustment.

**Staging strategy (DDC — Farrow must always decimate, RateChange > 1):**
1. Choose integer CIC_R and FIR_R such that CIC_R * FIR_R <= total_decimation (integer stages under-decimate; Farrow handles the remainder). **Never** choose CIC_R * FIR_R > total_decimation — that would require Farrow interpolation (RateChange < 1), which is wrong for a DDC.
2. Compute farrowRateChange = total_decimation / (CIC_R * FIR_R) (must be > 1 for DDC, since RateChange = fsIn/fsOut)
3. Verify: CIC_R * FIR_R * farrowRateChange = total_decimation

**Example: 8.2x decimation** — CIC(x4) + FIR(x2) + Farrow(RateChange=41/40) = 4 * 2 * (41/40) = 8.2

```matlab
function [dataOut, validOut] = myDDC_fractional(dataIn, validIn)
%myDDC_fractional DDC with non-integer 8.2x decimation

    persistent nco cicDec firDec farrow;
    if isempty(nco)
        phaseInc = round((-25e6 * 2^32) / 100e6);
        nco = dsphdl.NCO( ...
            'DesignMethod', 'NCO parameter', ...
            'PhaseIncrementSource', 'Property', ...
            'PhaseIncrement', phaseInc, ...
            'Waveform', 'Complex exponential', ...
            'AccumulatorWL', 32, ...
            'OutputWL', 16, 'OutputFL', 14, ...
            'NumDitherBits', 4, ...
            'PhaseQuantization', true, ...
            'NumQuantizerAccumulatorBits', 12);

        cicDec = dsphdl.CICDecimator( ...
            'DecimationFactor', 4, ...
            'DifferentialDelay', 1, ...
            'NumSections', 4, ...
            'OutputDataType', 'Same word length as input', ...
            'GainCorrection', true);

        % Coefficients pre-computed from dsp.CICCompensationDecimator in design script
        compCoeffs = [ ... ]; % <-- paste numeric vector from design script
        firDec = dsphdl.FIRDecimator( ...
            'DecimationFactor', 2, ...
            'Numerator', compCoeffs, ...
            'NumCycles', 4, ...
            'OutputDataType', 'Same word length as input', ...
            'FilterStructure', 'Direct form systolic');

        farrowCoeffs = [-1/6,  1/2, -1/3, 0; ...
                         1/2,  -1,   -1/2, 1; ...
                        -1/2,   1/2,  1,   0; ...
                         1/6,   0,   -1/6, 0];
        farrow = dsphdl.FarrowRateConverter( ...
            'RateChangeSource', 'Property', ...
            'RateChange', 41/40, ...
            'Coefficients', farrowCoeffs, ...
            'OutputDataType', 'Same as first input', ...
            'FilterStructure', 'Direct form systolic');
    end

    [ncoSample, ncoValid] = nco(validIn);
    mixed = fi(dataIn * ncoSample, 1, 16, 14);
    [cicSample, cicValid] = cicDec(mixed, ncoValid);
    [firSample, firValid] = firDec(cicSample, cicValid);

    % Farrow always outputs 3: [data, valid, ready]
    [dataOut, validOut, ~] = farrow(firSample, firValid);
end
```

**Key Farrow conventions:**
- `RateChange` = fsIn / fsOut. **In a DDC, Farrow must always decimate (RateChange > 1).** Never use RateChange < 1 in a DDC — that would be interpolation.
- Farrow always outputs 3 values: `[data, valid, ready]`. Capture `ready` with `~` if not using backpressure.
- Farrow must be called every clock cycle — it manages its own internal timing.
- Default 3rd-order Lagrange coefficients work well for most DDC applications.

For additional architecture variants (three-stage, Farrow vs FIR Rate Converter comparison, real I/Q mixing), see `references/architecture-variants.md`.

## Common Mistakes

These supplement the Critical Conventions above — only items not already covered there.

| Mistake | Fix |
|---|---|
| Using `mfilt` objects for filter design | **NEVER** use `mfilt` (e.g., `mfilt.cicdecim`, `mfilt.firinterp`) — it is deprecated. Use `dsp.CICCompensationDecimator`, `designMultirateFIR`, or `dsp.FIRDecimator`/`dsp.FIRInterpolator` for filter design |
| Using `fir1()` for CIC compensation filter | **ALWAYS** use `dsp.CICCompensationDecimator` — it inverts CIC droop; `fir1()` is a generic lowpass that ignores CIC response |
| Calling `dsp.CICCompensationDecimator` inside HDL function | `dsp.CICCompensationDecimator` is **NOT** supported for HDL code generation. Pre-compute coefficients in the design script, then hardcode the numeric vector in the HDL function |
| CIC decimation factor not integer | Each stage must be integer. For non-integer totals, use Farrow for the fractional part |
| Farrow misuse (wrong rate, missing output, not called every cycle) | `RateChange` = fsIn/fsOut (> 1 for DDC decimation). Always capture 3 outputs `[data, valid, ~]`. Call every cycle. Choose integer stages so CIC_R * FIR_R <= total_decimation — never > total (that requires interpolation) |
For component property tables and step method signatures, see `references/component-properties.md`.

----

Copyright 2026 The MathWorks, Inc.

More from matlab/matlab-agentic-toolkit

SkillDescription
matlab-access-datafeed>
matlab-add-awgnRead BEFORE writing any code that adds Additive White Gaussian Noise (AWGN) to signals and converts between SNR, Eb/No, Es/No, and per-subcarrier SNR for communications simulations, using awgn(), convertSNR(), berawgn(). The default MATLAB patterns for AWGN (e.g., 'measured' option, manual SNR formulas) produce subtly incorrect results. This skill specifies the correct calling conventions, required function usage, and critical anti-patterns that must be avoided.
matlab-analyze-ams-waveformAnalyze AMS waveform data using Mixed-Signal Blockset utilities: phase noise measurement, clock jitter, anti-aliased resampling, timing measurements, lock time, INL/DNL, ADC/DAC calibration, HSpice import. Use when analyzing time-domain voltage from PLL/VCO/clock simulations, measuring phase noise from variable-step solver output, computing jitter, or resampling non-uniform data.
matlab-analyze-dataAnalyze data using MATLAB. Use when the task involves tables, timetables, time-series data, numeric arrays, sensor matrices, or gridded data — including but not limited to exploring, filtering, sorting, cleaning, transforming, aggregating, smoothing, padding, trimming, and answering questions about data. MATLAB provides extensive, easy-to-use built-in functions for these workflows with no additional products required.
matlab-analyze-dependenciesAnalyze the effective toolbox file set to produce a Dependency Manifest — classify all transitive dependencies as included, product, add-on, or external-unresolved, then present resolution options with tradeoffs. Use after matlab-define-toolbox-api when the spec is approved.
matlab-analyze-emS-parameters, insertion loss, fields, currents, mesh control, and solver selection for RF PCB performance validation. TRIGGER: user asks to compute S-parameters, analyze insertion/return loss, extract fields or currents, compare MoM vs FEM, or control mesh for any RF PCB component. Invoke BEFORE writing sparameters() or solver code — API is non-obvious. SKIP: designing or creating components (use the specific matlab-design-pcb-* skill), material/stackup setup only (use matlab-manage-pcb-material), optimization sweeps (use matlab-optimize-pcb-design), PDN/IR-drop analysis (use matlab-analyze-pcb-pdn).
matlab-analyze-installed-antennaAnalyze antennas installed on electrically large conducting platforms using MATLAB Antenna Toolbox. Loads platform geometry from STL/STEP/IGES, installs antenna elements, selects electromagnetic solvers (MoM-PO, FMM, MoM), and computes patterns, impedance, coupling, and efficiency. Use when the user wants to model an antenna on a vehicle, aircraft, ship, satellite, or other large structure.
matlab-analyze-pcb-pdnPDN DC voltage/current analysis, IR drop, design rule checking, and multi-net batch analysis on imported PCB layouts. TRIGGER: user asks about power integrity, PDN analysis, IR drop, voltage distribution, current density, power nets, or design rule checking on a PCB. Invoke BEFORE writing code — the PDN API chain is specialized and non-obvious. SKIP: importing a PCB file (use matlab-read-pcb-layout), EM field/S-parameter extraction (use matlab-analyze-em), material/stackup setup only (use matlab-manage-pcb-material), transmission line design (use matlab-design-pcb-txline).
matlab-analyze-rcsCalculate and visualize monostatic and bistatic radar cross section (RCS) using MATLAB Antenna Toolbox. Computes RCS of platforms, antennas, and arrays with PO, MoM, and FMM solvers, supporting HH/VV/HV/VH polarization, GPU acceleration, and near-field observation. Use when the user wants to compute, plot, or analyze radar cross section.
matlab-analyze-rf-propagationAnalyze RF propagation and plan wireless sites using MATLAB Antenna Toolbox. Creates transmitter/receiver sites, computes signal strength, coverage maps, SINR, line-of-sight, and ray tracing in geographic or indoor environments. Supports multiple propagation models (free-space, close-in, Longley-Rice, ray tracing, rain/gas/fog), custom terrain, building data, and directional antennas. Use when the user wants to compute coverage, signal strength, path loss, SINR, ray tracing, or plan a wireless network.