We send a known waveform; the channel adds noise; the receiver guesses what was sent. In Chapter 3 we built the math of cross-correlation. Here we use it.
4.1 The setup
Assume additive white Gaussian noise (AWGN): , where has flat power spectral density (two-sided) and Gaussian distribution at every instant. The receiver wants the highest possible signal-to-noise ratio at the sampling instant, because that is when it makes the decision.
4.2 The matched filter, derived
We pass through a linear filter with impulse response and sample the output at . The output is
The signal part of the output is and the noise part is a Gaussian with variance . The output SNR at sample time is
Cauchy-Schwarz inequality says with equality if and only if for some constant , i.e., the filter's impulse response is a time-reversed conjugate of the transmitted pulse. Then
where is the signal energy. The maximum achievable SNR depends only on energy and noise PSD, not on pulse shape. This is the matched filter, and its name comes from the way its impulse response is matched to the transmitted pulse.
4.3 Matched filter and correlator are the same thing
Two equivalent realisations.
The first is a filter; the second is a correlator. They produce the same output at . Hardware realises whichever is cheaper. Wi-Fi and Bluetooth use FIR filters whose taps are the matched impulse response. GPS uses correlators because the spreading code is so long that storing it as a filter would be unwieldy. The two views are mathematically identical, and Chapter 3's section on cross-correlation is exactly the same operation, dressed in receiver clothing.
4.4 The Q-function and BPSK BER, derived
For BPSK, the two possible signals are and , where is a unit-energy pulse. After matched filtering, the sample is
with . The decision threshold is zero. An error occurs when was sent but , or was sent but . By symmetry,
Since is zero-mean Gaussian with variance ,
The Q-function is the tail of the standard normal distribution. It captures the probability that a unit Gaussian exceeds standard deviations. There is no closed-form expression for in elementary functions, but numerically it is easy and many useful bounds exist (a tight one: for ).
So BPSK BER = , the most-printed formula in digital communications. Solve for various BER targets:
| BER | Required |
|---|---|
| dB | |
| 4.3 dB | |
| 6.8 dB | |
| 8.4 dB | |
| 9.6 dB | |
| 10.5 dB | |
| 12.6 dB |
Each decade of BER costs about 1 dB at high SNR.
4.5 BER for other schemes
A short cheat sheet (all assume Gray coding and AWGN, BER per bit not per symbol):
- BPSK:
- QPSK: (same as BPSK, with twice the bit rate)
- Coherent BFSK: (3 dB worse than BPSK, because the two BFSK signals are orthogonal not antipodal)
- Non-coherent BFSK: (about 0.8 dB worse than coherent BFSK)
- DPSK: (about 1 dB worse than BPSK)
- M-PSK ():
- M-QAM (square, Gray coded):
Why coherent BPSK and DPSK are close but not equal. BPSK uses the absolute phase. The decision distance between the two signals is . DPSK uses the difference of two consecutive samples; each carries phase noise, and the difference inherits twice the noise variance. The result is a slightly worse BER, by about 1 dB, in exchange for not needing carrier phase recovery.
4.6 The classical BER curve picture
Plot versus in dB for each scheme and the curves all look like cliffs that get steeper at higher SNR. The closer the curve to the y-axis, the more power-efficient the scheme. The closer to the upper-left, the more bandwidth-efficient (per Hz) it can be. There is always a tradeoff between bandwidth efficiency and SNR efficiency, and the BER curve is where you read it off. The vertical asymptote on the left is the Shannon limit for that bandwidth and SNR, the absolute lower bound below which no system can operate. We will derive that next.
# Simulate BPSK BER over AWGN and compare to theory.
import numpy as np
from scipy.special import erfc
def Q(x): return 0.5 * erfc(x / np.sqrt(2))
EbN0_dB = np.arange(0, 11)
EbN0 = 10 ** (EbN0_dB / 10)
N = 1_000_000 # bits per point
ber_sim, ber_theory = [], []
rng = np.random.default_rng(0)
for snr in EbN0:
bits = rng.integers(0, 2, N)
sym = 2*bits - 1 # 0 -> -1, 1 -> +1
noise = rng.standard_normal(N) / np.sqrt(2*snr) # variance 1/(2 Eb/N0)
rx = sym + noise
decided = (rx > 0).astype(int)
ber_sim.append((decided != bits).mean())
ber_theory.append(Q(np.sqrt(2*snr)))
# ber_sim and ber_theory will overlay neatly on a log plot.Run that and you see the simulated points hug the theoretical curve to within statistical scatter. That precise overlay is one of the satisfying confirmations that the math is right.