Waveform evaluation profiles (plan S15) — ofdm-lte20-v1 and ofdm-lte20-evm-v1¶
Status: proposed, pending science review and cross-validation. The
waveform, the measurement procedure, the reference-vector package and the
tests below exist in the repository; the numbers of this profile become
citable only after the cross-validation in §6 has been run by a maintainer
and the error budget in §5 has been approved. Until then the profile is
computed and stored like every other profile but is hidden in the GUI
(MetricProfile.validation = pending_cross_validation) and every result it
produces carries the limitation "profile pending cross-validation".
1. Scope¶
One waveform configuration, chosen because the lab's own captures
(DPA_200MHz, DPA_160MHz) are LTE 20 MHz carriers:
| Item | Value | Source |
|---|---|---|
| Waveform id | ofdm-lte20-v1 |
this document |
| Numerology | CP-OFDM, 15 kHz subcarrier spacing, 2048-point FFT at 30.72 MS/s, normal cyclic prefix (160, 144 × 6 samples per 0.5 ms slot), 14 symbols per 1 ms subframe | 3GPP TS 36.211 §6.12 (OFDM baseband signal generation); standard version to be fixed at cross-validation |
| Occupied subcarriers | 1200 (100 resource blocks × 12) at k = −600 … −1, +1 … +600; the DC subcarrier is empty | same |
| Modulation | 64QAM on every occupied subcarrier of every symbol, unit average power, points (±1, ±3, ±5, ±7)/√42 in I and Q, drawn uniformly from a seeded generator (numpy.random.default_rng(seed)) |
opendpd/core/waveforms/ofdm.py |
| Length | n_subframes × 30 720 samples (default 10 = one 10 ms frame); instruments play it in a loop |
spec |
| What it is | a test waveform with known symbols: no synchronisation signals, reference signals, control or shared channels, no resource mapping, no filtering or windowing | — |
| What it is not | a conformance test signal (E-TM), a 3GPP-compliant transmitter, or evidence of standard compliance; the name "LTE 20 MHz" refers to the numerology only | — |
Everything is regenerated from the specification (WaveformSpec: id,
version, seed, n_subframes); the reference-vector package (§4) is a
convenience for instruments and for cross-validation, never the source of
truth.
2. Measurement procedure of ofdm-lte20-evm-v1¶
Input: the evaluated I/Q signal (a PA model output, a simulated or measured
PA output with or without DPD) at its capture rate fs, and the dataset's
binding to the waveform (§3). Every step is deterministic and recorded in
MetricProfile.parameters.
- Rate conversion. If
fs ≠ 30.72 MS/s, the signal is converted with a polyphase resampler (scipy.signal.resample_poly, Kaiser-windowed FIR) using the exact rational ratio;fsbelow 30.72 MS/s or without a small rational ratio (denominator ≤ 10 000) givesnot_applicable. - Timing. Circular cross-correlation with the regenerated waveform
(one period) gives the integer offset and the normalised peak; a peak
below 0.3 means the signal is not (a distorted copy of) the bound waveform
→
missing_reference. - Coarse frequency offset from the cyclic-prefix correlation of every complete symbol, skipping the first 32 prefix samples (channel memory of the previous symbol).
- Equaliser. One complex gain per subcarrier, least squares over all complete symbols in the capture, from the known symbols (data aided).
- Fine frequency offset from the slope of the per-symbol residual phase (known symbols) against time; steps 4–5 iterate at most three times until the update is below 1 mHz. No per-symbol phase tracking: whatever remains counts as error.
- EVM. RMS over every occupied subcarrier of every complete symbol,
EVM_RMS = 100 · sqrt(Σ|Ŝ − S|² / Σ|S|²)in percent, also reported in dB (20·log10). Symbols are demodulated at the nominal FFT position (end of the cyclic prefix). - ACLR at the capture rate: Welch PSD (Hann,
npersegof the dataset, 50 % overlap), main channel = [−9, +9] MHz (the 18 MHz transmission bandwidth configuration), first adjacent channels centred at ±20 MHz with the same 18 MHz rectangular measurement bandwidth,ACLR = 10·log10(P_adjacent / P_main)(leakage, negative dBc, lower is better, the repository's convention). Requiresfs ≥ 58 MS/s; otherwisenot_applicablewith the reason. Definition after 3GPP TS 36.104 §6.6.2 (E-UTRA ACLR); version to be fixed at cross-validation.
Deviations from a standard EVM procedure (stated, to be quantified)¶
| Standard procedure (TS 36.104 Annex E principles) | This profile | Why |
|---|---|---|
| Channel estimate from reference signals with time/frequency averaging | least-squares gain per subcarrier from all known symbols | data-aided test waveform; no reference signals exist |
| EVM evaluated at two FFT timing positions (window edges), maximum reported | one position: end of the cyclic prefix | first version; the two-position rule is a candidate for v2 after cross-validation |
| Frequency offset estimated per standard procedure | cyclic-prefix coarse estimate + data-aided fine estimate | same numbers expected for a static offset; drift within the window is not tracked |
| Measurement over specific subframes/slots and physical channels | every complete symbol in the capture | no physical channels |
The data-aided equaliser over L symbols removes 1/L of the noise power
from the reported EVM (bias sqrt(1 − 1/L)); with L ≥ 28 this is below
2 % relative and is part of the error budget.
3. Binding a dataset to the waveform¶
opendpd datasets import … --waveform <package>/waveform.json regenerates
the waveform and cross-correlates it with the imported input column:
the offset and the normalised peak are stored as signal.waveform
(WaveformBinding) next to the package hash. The binding says which symbols
were sent; the captured data is untouched. Without a binding, or when the
input does not correlate with the waveform, the profile reports
missing_reference for the EVM metrics and never falls back to another
definition under the same name. Multi-carrier captures (the built-in
DPA_200MHz, ten carriers at 800 MS/s) are therefore reported as not
applicable to this profile, which is the correct answer.
4. Reference-vector package¶
opendpd waveforms generate --seed S --subframes N --out DIR writes
| File | Content |
|---|---|
waveform.json |
the WaveformSpec, the package hash (spec + symbols), sample count, formats |
x.npy |
float32 (n, 2) I/Q at 30.72 MS/s, unit average power, to be played in a loop |
symbols.npy |
complex64 (n_symbols, 1200) reference symbols in subcarrier order |
Expected results on the ideal signal (self-evaluation, recorded by the tests
in tests/unit/test_waveform_ofdm.py): EVM below 1e-9 % at 30.72 MS/s;
EVM floor 0.037 % after rate conversion from 122.88 MS/s or 800 MS/s
(polyphase filter ripple); a frequency offset of ±350 Hz and a linear channel
shorter than the cyclic prefix are removed exactly; white noise of SNR 30 dB
gives EVM = 100/√SNR · √(1200/2048) · √(1 − 1/L) within 0.03 percentage
points.
5. Error budget (proposed, pending approval)¶
| Contribution | Bound in this implementation | Evidence |
|---|---|---|
| Numerical floor (no rate conversion) | < 1e-9 % EVM | test_ideal_signal_demodulates_to_zero_evm_with_exact_timing |
| Rate conversion floor | 0.037 % EVM (122.88 and 800 MS/s) | test_resampling_from_a_capture_rate_has_a_small_recorded_floor |
| Equaliser noise bias | factor √(1 − 1/L), L = complete symbols in the capture | test_white_noise_of_known_power_gives_the_predicted_evm |
| Frequency offset residual | estimate within 0.01 Hz of an injected static offset; drift not tracked | test_frequency_offset_and_phase_are_estimated_and_removed |
| Timing | integer sample; sub-sample delay absorbed by the equaliser as linear phase | test_timing_offset_and_looped_playback_are_recovered, test_linear_channel_inside_the_cyclic_prefix_is_equalised_exactly |
| ACLR PSD estimate | Welch with the dataset's nperseg; bias of a tone of known power below 0.05 dB (as for general-spectral-v1) |
tests/unit/test_metrics_general.py conventions |
Comparison targets against the cross-validation backend (plan S15, fixed before any model comparison, never relaxed afterwards): adjacent-channel ratio within 0.1 dB, RMS EVM within 0.05 percentage points on the same digital reference signal. Values below the measurement floor are reported with the floor stated, not scored.
6. Cross-validation protocol (maintainer step; MATLAB not required for users)¶
- Generate a package (
--seed 1 --subframes 10) and, in MATLAB LTE Toolbox, build the same resource grid fromsymbols.npyand modulate it (lteOFDMModulatewith a 20 MHz, normal-CP configuration); the time-domain signals must agree to numerical precision after scaling. - Pass the same distorted signals through both chains: the package played
through a PA capture (or the synthetic PA of
tests/fixtures/synthetic.py), scored here and by the toolbox's EVM/ACLR functions with their default procedure; record both numbers, the differences and the toolbox version. - Record the outcome in this document (§7), set
validation = cross_validatedinopendpd/core/metrics/ofdm_evm_v1.py(protected path, science review) and fix the standard versions cited above.
Users never need MATLAB: the reference vectors and the evaluation run in Python; MATLAB is the independent backend that checks them.
7. Validation record¶
| Date | Backend and version | Signals | ACLR difference | EVM difference | Outcome |
|---|---|---|---|---|---|
| 2026-10-08 | MATLAB R2026a Update 5 on Linux; LTE Toolbox, Communications Toolbox and Signal Processing Toolbox 26.1 | ofdm-lte20-v1 waveform, synthetic memory-polynomial PA at four drive levels (1 % to 11 % EVM), a gain/delay/noise variant and a 245.76 MS/s variant (S0 to S9, plus S6b and S9b at +30 Hz) |
7 of 84 scored values against comm.ACPR are outside the 0.1 dB budget, at most 0.21 dB, all on the two lowest-distortion signals |
at most 2.1·10⁻⁹ percentage points from an independent MathWorks-blocks chain on the ten evaluable signals (budget 0.05) | not passed as registered: 102 of 115 scored items within budget, 7 outside, 6 not evaluable (the +350 Hz signals, which both tools refuse) |
The outcome above is the record of the registered cross-validation, not an approval: the ACLR differences come from how the two
tools integrate a band whose edge is not a bin centre (a pwelch PSD integrated with comm.ACPR's rule reproduces comm.ACPR
to 2.5·10⁻⁴ dB), and the EVM chain, the waveform (lteOFDMModulate, 2.9·10⁻⁸ relative RMS) and the Welch estimator agree.
validation in opendpd/core/metrics/ofdm_evm_v1.py is therefore not changed by this record. Whether to keep the band rule
and document the expected difference (up to 0.2 dB at 60 kHz resolution and coarser), to state the carrier-offset capture range
(the timing peak falls below the 0.3 rule at about 75 Hz for a 10 ms waveform) and the waveform's own ACLR floor (about
-42 dBc), is a decision for the maintainers. Rules, signals, budgets, every number and the diagnostics:
OpenDPD ↔ MATLAB parity.
8. Effect on existing results¶
Nothing changes for legacy-opendpd-v1 (frozen) or general-spectral-v1:
the new profile is an additional file under runs/<id>/results/ and reports
explicit statuses on every existing dataset (tests/unit/test_metrics_ofdm_evm.py).
Versioned follow-up (2026-10-11)¶
The v1 record above remains a failed-as-registered comparison, and
ofdm-lte20-evm-v1 remains pending_cross_validation. The separately registered
v2 profiles distinguish the two PSD configurations
and add frequency-tolerant acquisition. Both real v2 runs passed all 115 scored
items at the original tolerances and signal hashes; see the
complete evidence. This does not promote
v1 or alter the legacy/general/carrier profiles, and is not a 3GPP conformance
claim.