Constellation Design and Mapping

Why Digital Modulation Matters

Every wireless system encodes bits into complex-valued symbols before transmission. The choice of constellation determines the data rate, error performance, and peak-to-average power ratio. In this section you will implement constellation mappers for BPSK, QPSK, 16-QAM, and 64-QAM, learning how Gray coding minimizes bit errors when neighboring symbols are confused by noise.

Definition:

Digital Constellation

An MM-ary constellation is a set of MM complex-valued symbols S={s0,s1,…,sMβˆ’1}\mathcal{S} = \{s_0, s_1, \dots, s_{M-1}\} where each symbol represents k=log⁑2Mk = \log_2 M bits. The average symbol energy is:

Es=1Mβˆ‘m=0Mβˆ’1∣sm∣2E_s = \frac{1}{M} \sum_{m=0}^{M-1} |s_m|^2

and the average bit energy is Eb=Es/kE_b = E_s / k.

import numpy as np

# QPSK constellation (M=4, k=2 bits/symbol)
M = 4
qpsk = np.exp(1j * np.pi * np.array([1, 3, 7, 5]) / 4)
Es = np.mean(np.abs(qpsk)**2)
Eb = Es / np.log2(M)

Normalizing so that Es=1E_s = 1 simplifies SNR calculations. Multiply by Es\sqrt{E_s} to set any desired energy.

Definition:

Gray Code Mapping

A Gray code assigns bit labels to constellation points such that adjacent symbols differ in exactly one bit. When noise causes a symbol error to a neighbor, only one bit is wrong, so:

Pbβ‰ˆPslog⁑2MP_b \approx \frac{P_s}{\log_2 M}

at moderate-to-high SNR, where PsP_s is the symbol error rate.

def gray_code(n_bits):
    """Generate Gray code sequence for n_bits."""
    if n_bits == 0:
        return [0]
    lower = gray_code(n_bits - 1)
    return lower + [x + (1 << (n_bits - 1)) for x in reversed(lower)]

Without Gray coding, a single symbol error can cause up to log⁑2M\log_2 M bit errors. Gray coding is universally used in practice.

Definition:

Minimum Euclidean Distance

The minimum Euclidean distance of a constellation is:

dmin⁑=min⁑iβ‰ j∣siβˆ’sj∣d_{\min} = \min_{i \neq j} |s_i - s_j|

This quantity dominates the high-SNR error probability. For MM-QAM with average energy EsE_s:

dmin⁑=6EsMβˆ’1d_{\min} = \sqrt{\frac{6 E_s}{M - 1}}

from itertools import combinations

def compute_dmin(constellation):
    """Compute minimum Euclidean distance."""
    dists = [abs(si - sj) for si, sj in combinations(constellation, 2)]
    return min(dists)

Definition:

Rectangular QAM Constellation

An MM-QAM constellation (M=4kM = 4^k for some integer kk) is the Cartesian product of two M\sqrt{M}-PAM alphabets:

sm=(2iβˆ’M+1)+j(2qβˆ’M+1),i,q∈{0,1,…,Mβˆ’1}s_{m} = (2i - \sqrt{M} + 1) + j(2q - \sqrt{M} + 1), \quad i, q \in \{0, 1, \dots, \sqrt{M}-1\}

After normalization to unit average energy:

def qam_constellation(M):
    """Generate normalized M-QAM constellation."""
    sqrt_M = int(np.sqrt(M))
    assert sqrt_M**2 == M, "M must be a perfect square"
    pam = np.arange(sqrt_M) - (sqrt_M - 1) / 2
    I, Q = np.meshgrid(pam, pam)
    constellation = (I + 1j * Q).flatten()
    # Normalize to unit average energy
    constellation /= np.sqrt(np.mean(np.abs(constellation)**2))
    return constellation

Definition:

Phase Shift Keying (PSK)

An MM-PSK constellation places symbols uniformly on the unit circle:

sm=exp⁑ ⁣(j2Ο€mM),m=0,1,…,Mβˆ’1s_m = \exp\!\left(j \frac{2\pi m}{M}\right), \quad m = 0, 1, \dots, M-1

All symbols have the same energy ∣sm∣2=1|s_m|^2 = 1, making PSK attractive for nonlinear channels (constant envelope). The minimum distance is dmin⁑=2sin⁑(Ο€/M)d_{\min} = 2\sin(\pi/M).

def psk_constellation(M):
    """Generate M-PSK constellation."""
    return np.exp(1j * 2 * np.pi * np.arange(M) / M)

BPSK (M=2M=2) and QPSK (M=4M=4) are the most common PSK schemes. QPSK has the same BER as BPSK but double the spectral efficiency.

Definition:

Bit-to-Symbol Mapper with Gray Coding

A mapper takes a binary bit stream and groups k=log⁑2Mk = \log_2 M consecutive bits into an integer index, which selects a constellation point. With Gray coding, the mapping is:

bits→Gray index→sm\text{bits} \to \text{Gray index} \to s_m

def bits_to_symbols(bits, constellation, gray_map):
    """Map bits to constellation symbols using Gray mapping."""
    k = int(np.log2(len(constellation)))
    n_symbols = len(bits) // k
    bit_groups = bits[:n_symbols * k].reshape(n_symbols, k)
    indices = np.array([int(''.join(map(str, b)), 2) for b in bit_groups])
    symbols = constellation[gray_map[indices]]
    return symbols

Theorem: Optimality of Antipodal Signaling

Among all binary constellations with average bit energy EbE_b, BPSK (s0=+Ebs_0 = +\sqrt{E_b}, s1=βˆ’Ebs_1 = -\sqrt{E_b}) maximizes the minimum Euclidean distance dmin⁑=2Ebd_{\min} = 2\sqrt{E_b} and achieves:

Pb=Q ⁣(2EbN0)P_b = Q\!\left(\sqrt{\frac{2E_b}{N_0}}\right)

This is the best achievable BER for uncoded binary signaling over AWGN.

Placing two points as far apart as possible on the real line maximizes the distance for a given energy budget. The factor of 2 in the exponent arises because the distance is 2Eb2\sqrt{E_b}, not Eb\sqrt{E_b}.

Theorem: Nearest-Neighbor Union Bound

For an MM-ary constellation in AWGN, the symbol error rate is upper-bounded by:

Psβ‰€βˆ‘m=0Mβˆ’11Mβˆ‘kβ‰ mQ ⁣(∣smβˆ’sk∣2Οƒn)P_s \le \sum_{m=0}^{M-1} \frac{1}{M} \sum_{k \neq m} Q\!\left(\frac{|s_m - s_k|}{2\sigma_n}\right)

At high SNR, only the nearest-neighbor pairs dominate:

Psβ‰ˆNΛ‰min⁑ Q ⁣(dmin⁑2Οƒn)P_s \approx \bar{N}_{\min} \, Q\!\left(\frac{d_{\min}}{2\sigma_n}\right)

where NΛ‰min⁑\bar{N}_{\min} is the average number of nearest neighbors.

Each pairwise error acts like a BPSK decision between two symbols. The union bound sums these pairwise errors, and at high SNR only the closest pairs matter.

Theorem: QPSK BER Equivalence to BPSK

With Gray coding, QPSK achieves the same BER as BPSK:

PbQPSK=Q ⁣(2EbN0)P_b^{\text{QPSK}} = Q\!\left(\sqrt{\frac{2E_b}{N_0}}\right)

despite transmitting 2 bits per symbol (double the spectral efficiency).

QPSK decomposes into two orthogonal BPSK channels on the I and Q axes. Each axis carries one bit at energy EbE_b, and the noise on the two axes is independent.

Example: Building QAM Constellations in NumPy

Implement a function that generates BPSK, QPSK, 16-QAM, and 64-QAM constellations with Gray coding and unit average energy.

Example: Implementing Gray Code Bit Mapping

Implement Gray-coded bit mapping for 16-QAM and verify that adjacent constellation points differ by exactly one bit.

Example: Comparing BER Across Constellation Sizes

Simulate the BER of BPSK, QPSK, 16-QAM, and 64-QAM over AWGN and compare with theoretical curves.

Interactive Constellation Viewer

Explore BPSK, QPSK, 16-QAM, and 64-QAM constellations. Adjust SNR to see noisy received symbols scatter around the ideal points.

Parameters

BER Comparison Across Modulation Schemes

Compare theoretical and simulated BER curves for different modulation orders.

Parameters

Gray Code vs Natural Binary: BER Impact

Compare BER with Gray coding versus natural binary labeling.

Parameters

Noise Effect on Constellation Points

Watch how increasing noise variance spreads received symbols away from ideal constellation points, causing detection errors.

Parameters

Quick Check

How many bits does each symbol carry in 64-QAM?

4

6

8

64

Quick Check

What is the primary benefit of Gray coding in a digital constellation?

Reduces symbol error rate

Ensures adjacent symbols differ by one bit

Increases minimum Euclidean distance

Reduces peak-to-average power ratio

Common Mistake: Forgetting Constellation Normalization

Mistake:

Creating a QAM constellation without normalizing to unit energy, then using Eb/N0E_b/N_0 formulas that assume Es=1E_s = 1.

Correction:

Always normalize: const /= np.sqrt(np.mean(np.abs(const)**2)). Alternatively, scale the noise variance to match the actual EsE_s.

Common Mistake: Wrong Noise Variance for Complex AWGN

Mistake:

Adding complex noise with total variance N0N_0 instead of N0/2N_0/2 per real/imaginary component.

Correction:

For complex AWGN: n = sqrt(N0/2) * (randn(...) + 1j*randn(...)). The total noise power is E[∣n∣2]=N0E[|n|^2] = N_0, split equally between I and Q.

Key Takeaway

Higher-order constellations (16-QAM, 64-QAM) increase spectral efficiency (log⁑2M\log_2 M bits/symbol) but require higher SNR to maintain the same BER. Gray coding is essential to minimize the BER-to-SER gap.

Key Takeaway

QPSK achieves the same BER as BPSK while doubling spectral efficiency. This is because QPSK decomposes into two independent BPSK channels on the I and Q axes.

Why This Matters: Modulation in 5G NR

5G NR supports QPSK, 16-QAM, 64-QAM, and 256-QAM. The base station selects the modulation order based on channel quality feedback (CQI): strong channels use 256-QAM for maximum throughput, while weak channels fall back to QPSK for robustness. The adaptive modulation and coding (AMC) scheme is the single most important factor in wireless throughput.

See full treatment in Chapter 22

Historical Note: The Evolution of QAM

1960s-present

Quadrature amplitude modulation was first used in telephone modems in the 1960s. The V.29 modem (1976) used 16-QAM at 9600 bps. Today, Wi-Fi 6 uses 1024-QAM, and cable modems use 4096-QAM, pushing the limits of analog hardware precision.

Historical Note: Frank Gray and the Reflected Binary Code

1953

Frank Gray of Bell Labs patented the reflected binary code in 1953 (US Patent 2,632,058). He developed it to prevent errors in analog-to-digital conversion, but it became fundamental to digital communications. The recursive construction (reflect and prefix) is both elegant and practical.

Constellation

A set of complex-valued symbols used in digital modulation. Each symbol represents log⁑2M\log_2 M bits for an MM-ary constellation.

Related: Quadrature Amplitude Modulation (QAM), Phase Shift Keying (PSK)

Quadrature Amplitude Modulation (QAM)

A modulation scheme where symbols occupy a rectangular grid in the complex plane, varying both amplitude and phase.

Related: Constellation

Phase Shift Keying (PSK)

A modulation scheme where all symbols have equal energy (lie on a circle) and information is encoded only in the phase.

Related: Constellation

Gray Code

A binary labeling scheme where adjacent symbols differ by exactly one bit, minimizing the bit error rate for nearest-neighbor symbol errors.

Minimum Euclidean Distance

The smallest distance between any two constellation points; dominates the error probability at high SNR.

Spectral Efficiency

The number of bits transmitted per second per Hertz; equals log⁑2M\log_2 M for MM-ary modulation with Nyquist pulse shaping.

Modulation Scheme Comparison

PropertyBPSKQPSK16-QAM64-QAM
Bits/symbol1246
dmin⁑/Esd_{\min}/\sqrt{E_s}2.001.410.630.31
BER at 10 dB Eb/N0E_b/N_03.9Γ—10βˆ’63.9 \times 10^{-6}3.9Γ—10βˆ’63.9 \times 10^{-6}2.2Γ—10βˆ’42.2 \times 10^{-4}2.8Γ—10βˆ’32.8 \times 10^{-3}
Constant envelope?YesYesNoNo
5G NR supportNoYesYesYes