AWGN Channel and BER Simulation
The AWGN Channel: The Fundamental Benchmark
The additive white Gaussian noise (AWGN) channel is the simplest and most important channel model. Every new modulation or coding scheme is first validated against AWGN BER curves before testing on fading channels. This section teaches you to simulate BER with proper statistical rigor.
Definition: Additive White Gaussian Noise Channel
Additive White Gaussian Noise Channel
The AWGN channel models the received signal as:
where is the transmitted symbol and is circularly symmetric complex Gaussian noise. The signal-to-noise ratio is:
def awgn_channel(symbols, snr_dB, bits_per_symbol=1):
snr = 10**(snr_dB / 10)
Es = np.mean(np.abs(symbols)**2)
N0 = Es / snr
noise = np.sqrt(N0/2) * (np.random.randn(len(symbols))
+ 1j * np.random.randn(len(symbols)))
return symbols + noise
Always be clear about whether SNR is per-symbol () or per-bit (). The difference is dB.
Definition: Maximum Likelihood (ML) Symbol Detection
Maximum Likelihood (ML) Symbol Detection
The ML detector selects the symbol that maximizes the likelihood:
This is equivalent to finding the nearest constellation point in Euclidean distance.
def ml_detect(received, constellation):
"""ML detection: nearest constellation point."""
# Vectorized: broadcast over all constellation points
distances = np.abs(received[:, None] - constellation[None, :])
return np.argmin(distances, axis=1)
For BPSK and QPSK, ML detection simplifies to sign decisions on the I and Q components, avoiding the distance computation.
Theorem: Exact BER for M-QAM with Gray Coding
For rectangular -QAM with Gray coding over AWGN, the approximate BER (tight at moderate-to-high SNR) is:
For BPSK/QPSK: .
The factor accounts for edge and corner symbols having fewer nearest neighbors. The argument of reflects the decreasing as grows.
Theorem: Clopper-Pearson Confidence Interval for BER
Given errors in trials, the exact (Clopper-Pearson) confidence interval for BER is:
where is the inverse beta CDF. The relative half-width scales as .
You need at least 100 errors per SNR point for a tight confidence interval (about relative width at 95% confidence).
Theorem: SNR Penalty for Higher-Order Modulation
To achieve the same BER, -QAM requires approximately:
more than -QAM (for ). Going from QPSK to 16-QAM costs about 3.8 dB; from 16-QAM to 64-QAM costs about 4.2 dB.
Each doubling of roughly halves for the same energy, requiring about 4 dB more SNR to compensate.
Example: Complete Vectorized BER Simulation
Implement a complete BER simulation for -QAM over AWGN with confidence intervals, and validate against theory.
Simulation function
import numpy as np
from scipy.special import erfc
from scipy.stats import beta as beta_dist
def simulate_ber_qam(M, EbN0_dB_range, min_errors=100, max_bits=10_000_000):
k = int(np.log2(M))
const = qam_constellation(M)
results = []
for EbN0_dB in EbN0_dB_range:
EbN0 = 10**(EbN0_dB / 10)
N0 = 1 / (k * EbN0)
sigma = np.sqrt(N0 / 2)
total_errors, total_bits = 0, 0
while total_errors < min_errors and total_bits < max_bits:
bits = np.random.randint(0, 2, k * 10000)
idx = bits.reshape(-1, k).dot(1 << np.arange(k)[::-1])
tx = const[idx % M]
rx = tx + sigma * (np.random.randn(len(tx)) + 1j*np.random.randn(len(tx)))
det = np.argmin(np.abs(rx[:,None] - const[None,:]), axis=1)
det_bits = np.unpackbits(det.astype(np.uint8)).reshape(-1, 8)[:, -k:]
total_errors += np.sum(bits[:len(det_bits.flat)] != det_bits.flat[:len(bits)])
total_bits += len(bits)
ber = total_errors / total_bits
results.append({'EbN0_dB': EbN0_dB, 'ber': ber, 'errors': total_errors})
return results
Run and plot
EbN0_range = np.arange(0, 25, 2)
for M in [4, 16, 64]:
results = simulate_ber_qam(M, EbN0_range)
# Plot simulated vs theoretical
Example: Converting Between Eb/N0 and Es/N0
Explain and implement the conversion between and for different modulation orders.
Conversion
def EbN0_to_EsN0(EbN0_dB, M):
"""Convert Eb/N0 (dB) to Es/N0 (dB)."""
return EbN0_dB + 10 * np.log10(np.log2(M))
def EsN0_to_EbN0(EsN0_dB, M):
"""Convert Es/N0 (dB) to Eb/N0 (dB)."""
return EsN0_dB - 10 * np.log10(np.log2(M))
# Example: 16-QAM at Eb/N0 = 10 dB
# Es/N0 = 10 + 10*log10(4) = 16.02 dB
print(f"Es/N0 = {EbN0_to_EsN0(10, 16):.2f} dB")
BER Waterfall Curves
Explore BER versus for different modulation schemes. Toggle between theoretical and simulated curves.
Parameters
ML Decision Regions for 16-QAM
Quick Check
For 64-QAM, what is the difference between and in dB?
3.01 dB
6.02 dB
7.78 dB
10.0 dB
Correct: dB since 64-QAM carries 6 bits/symbol.
Common Mistake: Reporting BER with Too Few Errors
Mistake:
Stopping a BER simulation after a fixed number of bits regardless of how many errors were counted (e.g., 0 or 3 errors).
Correction:
Run until at least 100 errors are counted per SNR point. Report Clopper-Pearson confidence intervals. At , you need at least bits for 100 errors.
AWGN
Additive White Gaussian Noise: the simplest channel model where noise has flat spectral density and Gaussian amplitude distribution.
Related: Bit Error Rate (BER)
Bit Error Rate (BER)
The probability that a received bit differs from the transmitted bit; the primary performance metric for digital communication systems.
Related: Symbol Error Rate (SER)
Symbol Error Rate (SER)
The probability of detecting the wrong constellation symbol. Related to BER by with Gray coding.