変調方式とビット誤り率のチートシート
BPSK、QPSK、正方QAMの1シンボルあたりのビット数、AWGNとレイリーフェージングでのBERの式、目標BERに必要なEb/N0、式を確かめるシミュレーションをまとめます。
このシートは、リンクを設計する人や、モデムを理論値と照合する人向けです。よく使う符号化なしのビット誤り率(BER)の式と、それぞれに必要なEb/N0、式を確かめる短いシミュレーションをまとめています。背景はデジタル変調のレッスンとフェージングチャネルのレッスンで解説しています。
記号
| 記号 | 意味 |
|---|---|
| M | コンステレーションの点数 |
| k = log2 M | 1シンボルあたりのビット数 |
| Es/N0 | シンボルエネルギーと雑音電力密度の比。雑音帯域幅がシンボルレートに等しいときSNRに一致する |
| Eb/N0 | ビットエネルギーと雑音電力密度の比。Es/N0 = k Eb/N0、dBではEs/N0 = Eb/N0 + 10 log10 k |
| Q(x) | ガウス分布の裾確率。Q(x) = 0.5 erfc(x / √2) |
変調方式
| 方式 | 1シンボルあたりのビット数 | 使われる場面 |
|---|---|---|
| BPSK | 1 | ビットあたりのマージンを最も多く必要とする低レートのリンク |
| π/2-BPSK | 1 | トランスフォームプリコーディングを有効にしたNR PUSCH(TS 38.211) |
| QPSK | 2 | TS 38.214のNR CQIテーブルで最も低レートのエントリ、多くの衛星リンク |
| 16-QAM | 4 | LTE・NR・Wi-Fiの中程度のレート |
| 64-QAM | 6 | 良好なチャネル |
| 256-QAM | 8 | 短く良好なリンク。TS 38.214のNR CQI Table 2に含まれる |
| 1024-QAM | 10 | Release 17以降のNR FR1下りリンク(TS 38.214の変更履歴による) |
3GPP TS 38.211(NRの物理チャネルと変調)は、π/2-BPSK、BPSK、QPSK、16・64・256・1024 QAMのビットからシンボルへのマッピングを定義しています。いずれも平均エネルギーが1になるよう正規化されています。この仕様の位置づけは3GPP仕様マップを参照してください。
AWGNでのBER
全体を通してグレイ符号化を仮定します。したがって、隣接点へのシンボル誤りは1ビットの誤りになります。
| 方式 | Eb/N0で表したBER | 精度 |
|---|---|---|
| BPSK | Q(√(2 Eb/N0)) | 厳密 |
| QPSK | Q(√(2 Eb/N0)) | 厳密。IとQは独立した2つのBPSKチャネル |
| 正方M-QAM | (4/k)(1 − 1/√M) Q(√(3k Eb/N0 / (M − 1))) | 最近傍近似。M = 4では厳密、BER 10⁻²以下ではよく一致 |
| 16-QAM | (3/4) Q(√(4 Eb/N0 / 5)) | 上の式から |
| 64-QAM | (7/12) Q(√(2 Eb/N0 / 7)) | 上の式から |
BPSKとQPSKの式は、TseとViswanathの「Fundamentals of Wireless Communication」第3章に示されています。M-QAMの式は、各軸をグレイラベル付きの√M値PAMとして扱うと導けます。後述のシミュレーションは、モンテカルロ法のばらつきの範囲内でこの式と一致します。
AWGNで必要なEb/N0
上の式から、このページ末尾のコードで求めた値です。
| 方式 | BER 10⁻³ | BER 10⁻⁵ | BER 10⁻⁶ |
|---|---|---|---|
| BPSK・QPSK | 6.8 dB | 9.6 dB | 10.5 dB |
| 16-QAM | 10.5 dB | 13.4 dB | 14.4 dB |
| 64-QAM | 14.8 dB | 17.8 dB | 18.8 dB |
| 256-QAM | 19.4 dB | 22.5 dB | 23.5 dB |
16点から64点、64点から256点へと一段上げるごとに、Eb/N0で約4〜5 dB多く必要になり、1シンボルあたり2ビット増えます。Es/N0に換算すると(10 log10 kを加える)、256-QAMでBER 10⁻⁶を得るには約32.5 dBが必要です。位相雑音とPAのひずみがあるため、実際の送信機でこの値に届くものはわずかです。
レイリーフェージングでのBER
同期検波で完全なチャネル情報があり、SNRを1シンボルあたりの平均受信SNRとすると、TseとViswanath(式3.19・3.21)はBPSKについて次の式を示しています。
BPSK, Rayleigh: p_e = 0.5 (1 - sqrt(SNR / (1 + SNR))) ~ 1 / (4 SNR) at high SNR
同書の表3.1には、ほかの方式の高SNRでのBERが載っています。
| 方式 | 高SNRでのBER(レイリー) | 1シンボルあたりのビット数 |
|---|---|---|
| 同期検波BPSK | 1/(4 SNR) | 1 |
| 同期検波QPSK | 1/(2 SNR) | 2 |
| 同期検波16-QAM | 5/(2 SNR) | 4 |
| 差動BPSK | 1/(2 SNR) | 1 |
| 差動QPSK | 1/SNR | 2 |
この場合、誤り率は10 dBあたり1桁しか下がりません。TseとViswanathは、BER 10⁻³において、AWGNでのBPSKとレイリーフェージングでのBPSKの間に17 dBの差があると述べています。この差を埋めるのは送信電力の追加ではなく、ダイバーシチと符号化です。独立なブランチがL本あれば、誤り率はSNRの−L乗で下がります。
コード: シミュレーションで式を確かめる
次のコードは、AWGNでのグレイ符号化正方QAMと、レイリーフェージングでのBPSKをシミュレーションします。ベースバンドサンプルはcomplex128で、1シンボルあたり1サンプルです。続いて、各方式に必要なEb/N0を求めます。実行時間は1秒を大きく下回ります。
import numpy as np
from scipy.special import erfc
from scipy.optimize import brentq
def qfunc(x):
return 0.5 * erfc(x / np.sqrt(2))
def ber_mqam_theory(ebn0_db: float, m: int) -> float:
"""Gray-coded square M-QAM, nearest-neighbour approximation (exact for M = 4)."""
k = np.log2(m)
ebn0 = 10 ** (ebn0_db / 10)
return (4 / k) * (1 - 1 / np.sqrt(m)) * qfunc(np.sqrt(3 * k * ebn0 / (m - 1)))
def gray_pam_levels(bits_per_axis: int) -> tuple[np.ndarray, np.ndarray]:
"""Return PAM amplitudes and the Gray label of each amplitude index."""
n = 2 ** bits_per_axis
levels = np.arange(-(n - 1), n, 2, dtype=float)
gray = np.arange(n) ^ (np.arange(n) >> 1)
return levels, gray
def simulate_mqam(ebn0_db: float, m: int, n_sym: int, rng) -> float:
k = int(np.log2(m))
kb = k // 2
levels, gray = gray_pam_levels(kb)
idx_i = rng.integers(0, 2 ** kb, n_sym)
idx_q = rng.integers(0, 2 ** kb, n_sym)
s = levels[idx_i] + 1j * levels[idx_q]
es = np.mean(np.abs(levels[:, None] + 1j * levels[None, :]) ** 2)
n0 = es / (k * 10 ** (ebn0_db / 10))
r = s + np.sqrt(n0 / 2) * (rng.standard_normal(n_sym) + 1j * rng.standard_normal(n_sym))
def slice_axis(x):
return np.clip(np.round((x + (2 ** kb - 1)) / 2), 0, 2 ** kb - 1).astype(int)
det_i, det_q = slice_axis(r.real), slice_axis(r.imag)
errs = 0
for tx, rx in [(idx_i, det_i), (idx_q, det_q)]:
diff = gray[tx] ^ gray[rx]
errs += sum(np.count_nonzero(diff & (1 << b)) for b in range(kb))
return errs / (n_sym * k)
rng = np.random.default_rng(1)
n_sym = 400_000
print("Eb/N0 M theory simulated")
for m, ebn0_db in [(4, 6), (16, 10), (64, 14)]:
print(f"{ebn0_db:4d} dB {m:3d} {ber_mqam_theory(ebn0_db, m):.3e} {simulate_mqam(ebn0_db, m, n_sym, rng):.3e}")
# BPSK over Rayleigh fading with coherent detection (Tse and Viswanath eq. 3.19)
snr = 10 ** (20 / 10)
h = (rng.standard_normal(n_sym) + 1j * rng.standard_normal(n_sym)) / np.sqrt(2)
b = rng.integers(0, 2, n_sym)
x = 2.0 * b - 1
y = h * x + np.sqrt(1 / (2 * snr)) * (rng.standard_normal(n_sym) + 1j * rng.standard_normal(n_sym))
ber_sim = np.mean(((np.conj(h) * y).real > 0) != (b == 1))
ber_th = 0.5 * (1 - np.sqrt(snr / (1 + snr)))
print(f"Rayleigh BPSK at 20 dB: theory {ber_th:.3e}, simulated {ber_sim:.3e}, 1/(4 SNR) = {1/(4*snr):.3e}")
# Eb/N0 needed for a target BER over AWGN
print("Required Eb/N0 (dB) for BER 1e-3, 1e-5, 1e-6")
for m in [4, 16, 64, 256]:
req = [brentq(lambda e: np.log10(ber_mqam_theory(e, m)) - np.log10(t), -5, 30) for t in (1e-3, 1e-5, 1e-6)]
print(f"M = {m:3d}: " + ", ".join(f"{v:.1f}" for v in req))
期待される出力:
Eb/N0 M theory simulated
6 dB 4 2.388e-03 2.376e-03
10 dB 16 1.754e-03 1.752e-03
14 dB 64 2.154e-03 2.165e-03
Rayleigh BPSK at 20 dB: theory 2.481e-03, simulated 2.480e-03, 1/(4 SNR) = 2.500e-03
Required Eb/N0 (dB) for BER 1e-3, 1e-5, 1e-6
M = 4: 6.8, 9.6, 10.5
M = 16: 10.5, 13.4, 14.4
M = 64: 14.8, 17.8, 18.8
M = 256: 19.4, 22.5, 23.5
グラフの値は次のコードで出力したものです。
import numpy as np
from scipy.special import erfc
def qfunc(x):
return 0.5 * erfc(x / np.sqrt(2))
ebn0_db = np.arange(0, 22, 2)
g = 10 ** (ebn0_db / 10)
curves = {
"BPSK and QPSK, AWGN": qfunc(np.sqrt(2 * g)),
"16-QAM, AWGN": 0.75 * qfunc(np.sqrt(4 * g / 5)),
"64-QAM, AWGN": (7 / 12) * qfunc(np.sqrt(18 * g / 63)),
"BPSK, Rayleigh": 0.5 * (1 - np.sqrt(g / (1 + g))),
}
for name, ber in curves.items():
pts = [[int(e), float(f"{b:.3g}")] for e, b in zip(ebn0_db, ber) if b > 1e-9]
print(name, pts)
落とし穴
- Es/N0、Eb/N0、SNRを混同する。各軸がどれを使っているかを明記してください。Es/N0に対してプロットした64-QAMの曲線は、Eb/N0に対してプロットした同じ曲線より7.8 dB右に位置します。
- 信号より広い帯域幅でSNRを測る。広いチャネルフィルタを通して測った雑音は、整合フィルタの後で判定器(スライサ)が受ける雑音とは異なります。
- グレイ符号ではなく自然(2進)ラベルを使う。この場合、隣接点への誤りが1ビットを超える誤りになります。
- 符号化なしの曲線を、符号化ありのシステムの仕様と比べる。LDPC符号やポーラ符号はウォーターフォール領域を数 dB動かします。
- シミュレーションのビット数が少なすぎる。BER 10⁻⁵を信頼するには少なくとも100個の誤りを数えてください。そのためには少なくとも10⁷ビットが必要です。
出典
- D. Tse and P. Viswanath, 「Fundamentals of Wireless Communication」, Cambridge University Press, 2005, doi:10.1017/CBO9780511807213。第3章は著者のサイトで無料公開されています。
- 3GPP TS 38.211、NRの物理チャネルと変調。変調マッパーの定義。
- 3GPP TS 38.214、NRのデータ向け物理レイヤ手順。CQIテーブルとMCSテーブル。
- 用語集: ビット誤り率、Eb/N0、コンステレーション図、レイリーフェージング。