Where PBCH lives in the SSB
PBCH occupies symbols 1, 2, and 3 of the SSB. In symbol 2, it shares space with SSS — PBCH uses the 48 subcarriers on each side of the SSS center block. Across all three symbols, PBCH has a total of 432 data subcarriers after removing DMRS positions.
Step 1 — Extract PBCH symbols
Using timing t = 4523 from PSS, the UE computes each PBCH symbol start, removes the cyclic prefix (144 samples), and runs a 2048-point FFT to get frequency-domain subcarriers.
// Symbol timing (symbol length = 2192 samples at 61.44 Msps) Symbol 1: t = 4523 + 2192 = 6715 → skip CP (144) → FFT samples [6859..8906] Symbol 2: t = 4523 + 2×2192 = 8907 → skip CP → FFT samples [9051..11098] Symbol 3: t = 4523 + 3×2192 = 11099 → skip CP → FFT samples [11243..13290] // Extract 240 center subcarriers from each 2048-bin FFT output // → 240 complex values per symbol = PBCH + DMRS + (SSS in sym 2)
Step 2 — DMRS generation and channel estimation
PBCH DMRS is inserted every 4th subcarrier with offset v = PCI mod 4 = 2. The UE generates the expected DMRS sequence using the formula below, then uses it to estimate the channel at each DMRS position.
c_init = 2^11·(i_SSB+1)·(⌊N_ID^cell/4⌋+1) + 2^6·(i_SSB+1) + N_ID^cell mod 4
// DMRS position offset v = 442 mod 4 = 2 → DMRS at SC: 2, 6, 10, 14, 18, ... (60 per symbol) // DMRS seed c_init = 2^11×(3+1)×(⌊442/4⌋+1) + 2^6×(3+1) + (442 mod 4) = 2048×4×111 + 256 + 2 = 908546 // Channel estimation (at each of 60 DMRS subcarriers): H[k] = received[k] / DMRS_known[k] // Example at k=2: received[2] = 0.450+0.380j DMRS_known[2] = 0.707+0.707j H[2] = 0.586∠−10° (amplitude 0.586, phase shift −10°) // Interpolate H[k] linearly between DMRS positions // to estimate channel at all 180 data subcarriers H[3] ≈ (H[2]+H[6])/4×1 = 0.5873∠−10.25° H[4] ≈ (H[2]+H[6])/4×2 = 0.5885∠−10.50° H[5] ≈ (H[2]+H[6])/4×3 = 0.5898∠−10.75°
Step 3 — Equalization and QPSK demodulation
// Remove channel distortion at each data subcarrier: data_eq[k] = received[k] / H[k] // Example at k=4: received[4] = 0.412-0.089j, H[4] = 0.5885∠−10.50° data_eq[4] = 0.707+0.000j → QPSK symbol: +1+0j → bits 10 // QPSK: 2 bits per RE Total data REs: 180 (sym1) + ~53 (sym2 sides) + 180 (sym3) = 413 REs Total soft bits: 413 × 2 = 826 bits (+ rate matching padding = 864)
Step 4 — Descrambling
The 864 bits are descrambled by XOR-ing with a pseudorandom sequence seeded by PCI = 442. This reverses the scrambling applied at the gNB.
Step 5 — Rate dematching → Polar decoding
5G NR uses Polar codes for PBCH. Polar codes are theoretically proven to achieve channel capacity. The decoder uses a Successive Cancellation List (SCL) decoder with list size L=8 — it maintains 8 candidate decoding paths simultaneously, selecting the one that passes the CRC.
Step 6 — CRC check and payload extraction
// Decoded 32-bit payload structure: Bits [0..5] = SFN MSBs (6 bits) → 100011 Bit [6] = subCarrierSpacingCommon → 1 (30 kHz) Bits [7..10] = ssb-SubcarrierOffset (k_SSB) → 0010 = 2 Bit [11] = dmrs-TypeA-Position → 0 (symbol 2) Bits [12..15] = controlResourceSetZero → 0011 = 3 Bits [16..19] = searchSpaceZero → 0010 = 2 Bit [20] = cellBarred → 0 (notBarred) Bit [21] = intraFreqReselection → 0 (allowed) Bits [22..23] = spare → 00 Bits [24..31] = overhead (SFN LSBs, SSB idx) // SFN reconstruction: MSBs from MIB [0..5]: 100011 LSBs from overhead: 0101 Full SFN = 1000110101(bin) = 565