Cheat sheet

OFDM and 5G NR numerology cheat sheet

NR numerologies, slot and cyclic prefix durations from TS 38.211, resource block counts per channel bandwidth from TS 38.101, LTE for comparison, and OFDM sizing code.

Last verified 15 Nov 2026· 3GPP TS 38.211 V19.5.0, TS 38.101-1 V19.7.0, TS 38.101-2 V19.5.0 (Release 19); NumPy 2.5

This sheet is for engineers who configure, simulate or decode NR and LTE carriers and need the time and frequency grid at a glance. Every NR number here was checked against the Release 19 versions of 3GPP TS 38.211 (NR physical channels and modulation), TS 38.101-1 and TS 38.101-2 (NR UE radio transmission and reception, FR1 and FR2) and TS 38.104 (NR base station radio transmission and reception). For how OFDM works, start with the OFDM from scratch lesson.

OFDM relations

Quantity Formula Example
Subcarrier spacing Δf = fs / N_FFT 30.72 Msample/s / 1024 = 30 kHz
Useful symbol length T_u = 1 / Δf 33.33 µs at 30 kHz
Cyclic prefix Must exceed the channel’s delay spread 2.34 µs normal CP at 30 kHz
CP overhead T_cp / (T_u + T_cp) About 6.6 % for NR normal CP
Occupied bandwidth N_RB × 12 × Δf 273 × 12 × 30 kHz = 98.28 MHz
Sample rate N_FFT × Δf 4096 × 30 kHz = 122.88 Msample/s

A resource block is 12 consecutive subcarriers in frequency (TS 38.211). The cyclic prefix turns the channel’s linear convolution into a circular one, so each subcarrier sees one complex gain. That is why one-tap equalisation works.

NR numerologies

TS 38.211 defines the basic time unit Tc = 1 / (480 kHz × 4096) and κ = 64. A frame is 10 ms and a subframe is 1 ms. The numerology index μ sets Δf = 15 × 2^μ kHz.

μ Δf CP types Slots per subframe Slots per frame Slot length Useful symbol Normal CP Longer CP (twice per 1 ms)
0 15 kHz Normal 1 10 1 ms 66.67 µs 4.688 µs 5.208 µs
1 30 kHz Normal 2 20 0.5 ms 33.33 µs 2.344 µs 2.865 µs
2 60 kHz Normal, extended 4 40 0.25 ms 16.67 µs 1.172 µs 1.693 µs
3 120 kHz Normal 8 80 125 µs 8.33 µs 0.586 µs 1.107 µs
4 240 kHz Normal 16 160 62.5 µs 4.17 µs 0.293 µs 0.814 µs
5 480 kHz Normal 32 320 31.25 µs 2.08 µs 0.146 µs 0.667 µs
6 960 kHz Normal 64 640 15.625 µs 1.04 µs 0.073 µs 0.594 µs

A slot holds 14 OFDM symbols with normal CP and 12 with extended CP (60 kHz only, extended CP 4.167 µs). The normal CP is 144κ·2^−μ Tc. The first symbol of each 0.5 ms half-subframe gets 16κ Tc extra, so the slots line up with the 1 ms subframe at every μ. The columns from slot length onwards are computed by the code below from the TS 38.211 formulas.

Which numerology where

Use Subcarrier spacing
FR1, data (TS 38.101-1) 15, 30, 60 kHz
FR2, data (TS 38.101-2) 60 and 120 kHz, plus 480 and 960 kHz marked optional
SS/PBCH block (TS 38.213 cases A to G) 15 kHz (A), 30 kHz (B, C), 120 kHz (D), 240 kHz (E), 480 kHz (F), 960 kHz (G)

TS 38.104 defines FR1 as 410 MHz to 7125 MHz, FR2-1 as 24250 MHz to 52600 MHz and FR2-2 as 52600 MHz to 71000 MHz. An SS/PBCH block is 4 OFDM symbols by 240 subcarriers (20 resource blocks).

Resource blocks per channel bandwidth

Maximum transmission bandwidth configuration N_RB from TS 38.101-1 Table 5.3.2-1 (FR1). N/A means the combination is not defined.

Channel bandwidth 15 kHz 30 kHz 60 kHz
5 MHz 25 11 N/A
10 MHz 52 24 11
15 MHz 79 38 18
20 MHz 106 51 24
25 MHz 133 65 31
30 MHz 160 78 38
40 MHz 216 106 51
50 MHz 270 133 65
60 MHz N/A 162 79
80 MHz N/A 217 107
100 MHz N/A 273 135

The table also has rows for 3, 7, 35, 45, 70 and 90 MHz. FR2 from TS 38.101-2 Table 5.3.2-1:

Channel bandwidth 60 kHz 120 kHz
50 MHz 66 32
100 MHz 132 66
200 MHz 264 132
400 MHz N/A 264

A bandwidth part is a subset of these resource blocks with its own numerology. A UE may use a narrower one than the carrier.

LTE for comparison

TS 36.211 (E-UTRA physical channels and modulation) uses Ts = 1 / (15000 × 2048) s, a 10 ms frame of 307200 Ts and a 1 ms subframe of two 0.5 ms slots. LTE’s normal CP is 160 Ts for the first symbol of a slot and 144 Ts for the other six. The extended CP is 512 Ts. At 15 kHz these are the same durations as NR μ = 0, because 144 Ts equals 144κ Tc. LTE also defines 7.5 kHz, 3.75 kHz and 1.25 kHz spacings for special cases.

Code: durations from the TS 38.211 formulas

import numpy as np

# TS 38.211 clause 4.1: Tc = 1/(480e3 * 4096) s, kappa = 64
TC = 1 / (480e3 * 4096)
KAPPA = 64

print(" mu  SCS_kHz slots/sf  slot_us  Nu_us  CP_us  CPlong_us  CP_ext_us")
for mu in range(7):
    scs_khz = 15 * 2 ** mu
    nu = 2048 * KAPPA * 2.0 ** -mu * TC          # useful symbol length
    cp = 144 * KAPPA * 2.0 ** -mu * TC           # normal CP, l != 0 and l != 7*2^mu
    cp_long = cp + 16 * KAPPA * TC               # normal CP, l = 0 or l = 7*2^mu
    cp_ext = 512 * KAPPA * 2.0 ** -mu * TC if mu == 2 else float("nan")
    slots = 2 ** mu
    slot_us = 1e3 / slots
    print(f"{mu:3d} {scs_khz:7d} {slots:8d} {slot_us:8.2f} {nu*1e6:6.2f} {cp*1e6:6.3f} {cp_long*1e6:9.3f} {cp_ext*1e6:9.3f}")

# Check: 14 symbols (with two long CPs per half-subframe) fill exactly 0.5 ms per 7*2^mu symbols
for mu in range(7):
    n_half = 7 * 2 ** mu
    total = sum((2048 * KAPPA * 2.0 ** -mu + 144 * KAPPA * 2.0 ** -mu + (16 * KAPPA if l == 0 else 0)) * TC
                for l in range(n_half))
    assert abs(total - 0.5e-3) < 1e-12, (mu, total)
print("each 0.5 ms half-subframe is filled exactly for mu = 0..6")

# Sample rate for a chosen FFT size: fs = N_fft * SCS
for scs_khz, n_fft in [(15, 2048), (30, 4096), (30, 1024), (120, 4096)]:
    print(f"SCS {scs_khz} kHz, FFT {n_fft}: fs = {n_fft * scs_khz / 1e3:.2f} Msample/s")

Expected output:

 mu  SCS_kHz slots/sf  slot_us  Nu_us  CP_us  CPlong_us  CP_ext_us
  0      15        1  1000.00  66.67  4.688     5.208       nan
  1      30        2   500.00  33.33  2.344     2.865       nan
  2      60        4   250.00  16.67  1.172     1.693     4.167
  3     120        8   125.00   8.33  0.586     1.107       nan
  4     240       16    62.50   4.17  0.293     0.814       nan
  5     480       32    31.25   2.08  0.146     0.667       nan
  6     960       64    15.62   1.04  0.073     0.594       nan
each 0.5 ms half-subframe is filled exactly for mu = 0..6
SCS 15 kHz, FFT 2048: fs = 30.72 Msample/s
SCS 30 kHz, FFT 4096: fs = 122.88 Msample/s
SCS 30 kHz, FFT 1024: fs = 30.72 Msample/s
SCS 120 kHz, FFT 4096: fs = 491.52 Msample/s

Code: one OFDM symbol through a multipath channel

A 30 kHz, 1024-point symbol at 30.72 Msample/s carries 612 QPSK subcarriers (51 resource blocks, the 20 MHz entry at 30 kHz). Samples are complex128. A 9-tap channel shorter than the cyclic prefix is undone exactly by one complex division per subcarrier.

import numpy as np

rng = np.random.default_rng(7)
n_fft, n_cp, n_used = 1024, 72, 612          # 30 kHz SCS -> fs = 30.72 Msample/s, 51 RB x 12 = 612 subcarriers
fs = n_fft * 30e3
qpsk = (rng.choice([-1, 1], n_used) + 1j * rng.choice([-1, 1], n_used)) / np.sqrt(2)

grid = np.zeros(n_fft, dtype=np.complex128)
k = np.r_[1:n_used // 2 + 1, n_fft - n_used // 2:n_fft]   # skip DC, fill both edges
grid[k] = qpsk
x = np.fft.ifft(grid) * np.sqrt(n_fft)
tx = np.concatenate([x[-n_cp:], x])                  # prepend cyclic prefix

h = np.array([1.0, 0, 0, 0.5j, 0, 0, 0, 0, 0.25])  # 9-tap channel, shorter than the CP
rx = np.convolve(tx, h)[: tx.size]
y = np.fft.fft(rx[n_cp:]) / np.sqrt(n_fft)
H = np.fft.fft(h, n_fft)
eq = y[k] / H[k]                                    # one-tap equaliser per subcarrier

print(f"fs = {fs/1e6:.2f} Msample/s, CP = {n_cp/fs*1e6:.2f} us, channel span = {(h.size-1)/fs*1e6:.2f} us")
print(f"max error after one-tap equalisation: {np.max(np.abs(eq - qpsk)):.2e}")
print(f"CP overhead: {n_cp / (n_fft + n_cp) * 100:.1f} %")

Expected output:

fs = 30.72 Msample/s, CP = 2.34 us, channel span = 0.26 us
max error after one-tap equalisation: 1.02e-15
CP overhead: 6.6 %

The 72-sample prefix at 30.72 Msample/s is the NR normal CP for 30 kHz. Lengthen h past 73 taps and the error jumps, because intersymbol interference leaks in.

Pitfalls

  • Assuming every slot is 1 ms. Only μ = 0 has one slot per subframe.
  • Forgetting the longer CP on the first symbol of each half-subframe. Symbol start times drift if you use one CP length throughout.
  • Reading N_RB for the wrong frequency range. FR1 and FR2 tables differ.
  • Confusing the SS/PBCH block spacing with the data spacing. They can differ on the same carrier.
  • Taking a release’s feature list as what a network runs. Operators enable features selectively.

Sources