信道是信号传输的媒介,它对信号的影响决定了通信系统设计的核心挑战。理解信道模型是设计信道编码、调制和均衡器的基础。
| 分类维度 | 类型 | 特点 | 典型场景 |
|---|---|---|---|
| 按噪声 | AWGN | 加性高斯白噪声 | 深空通信 |
| 按衰落 | 平坦衰落 | 带宽<相干带宽 | NLOS室内 |
| 按衰落 | 频率选择性 | 带宽>相干带宽 | 高速移动 |
| 按时变 | 慢衰落 | 符号时间<相干时间 | 静止/低速 |
| 按时变 | 快衰落 | 符号时间>相干时间 | 高速移动 |
最基本也最重要的信道模型——加性高斯白噪声信道:
AWGN信道的容量即Shannon极限:C = B·log₂(1 + S/N)。虽然简单,AWGN是评估调制方式性能的基准。
无线信道中,信号经多条路径到达接收端,各路径随机叠加。当没有直射路径(NLOS)时,接收信号包络服从瑞利分布:
当存在直射路径(LOS)时,接收信号包络服从莱斯分布。K因子定义了直射路径功率与散射路径功率之比:
K→∞时退化为AWGN信道,K=0时退化为瑞利衰落。卫星通信和微波视距链路是典型的莱斯信道。
// channel_model.v - 信道模型仿真器
// 第07课:信道模型
module awgn_channel #(
parameter DATA_W = 12,
parameter NOISE_W = 12,
parameter SEED = 32'hDEADBEEF
)(
input wire clk,
input wire rst_n,
input wire signed [DATA_W-1:0] signal_in,
input wire valid_in,
output wire signed [DATA_W-1:0] signal_out,
output wire valid_out,
input wire [7:0] snr_control
);
// LFSR伪随机数生成器
reg [31:0] lfsr;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) lfsr <= SEED;
else lfsr <= {lfsr[30:0], lfsr[31] ^ lfsr[21] ^ lfsr[1] ^ lfsr[0]};
end
// 8个LFSR输出叠加近似高斯分布(中心极限定理)
reg signed [NOISE_W-1:0] noise_sample;
reg [2:0] accum_cnt;
reg signed [NOISE_W+2:0] noise_acc;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
noise_sample <= 0; accum_cnt <= 0; noise_acc <= 0;
end else begin
if (accum_cnt == 0)
noise_acc <= {{3{lfsr[7]}},lfsr[7:0]} + {{3{lfsr[15]}},lfsr[15:8]} +
{{3{lfsr[23]}},lfsr[23:16]} + {{3{lfsr[31]}},lfsr[31:24]};
else
noise_acc <= noise_acc + {{3{lfsr[7]}},lfsr[7:0]} +
{{3{lfsr[15]}},lfsr[15:8]} + {{3{lfsr[23]}},lfsr[23:16]} +
{{3{lfsr[31]}},lfsr[31:24]};
accum_cnt <= accum_cnt + 1'b1;
if (accum_cnt == 3'd7)
noise_sample <= (noise_acc >>> 3) * $signed({1'b0, snr_control});
end
end
assign signal_out = signal_in + noise_sample[NOISE_W-1:0];
assign valid_out = valid_in;
endmodule
// 瑞利衰落信道模型
module rayleigh_channel #(
parameter DATA_W = 12,
parameter TAP_NUM = 4,
parameter SEED = 32'hCAFEBABE
)(
input wire clk,
input wire rst_n,
input wire signed [DATA_W-1:0] signal_in,
input wire valid_in,
output wire signed [DATA_W-1:0] signal_out,
output wire valid_out
);
reg signed [DATA_W-1:0] delay_line [0:TAP_NUM-1];
reg signed [15:0] fade_coeff [0:TAP_NUM-1];
reg [31:0] lfsr_fade;
integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
lfsr_fade <= SEED;
for (i = 0; i < TAP_NUM; i = i + 1) begin
fade_coeff[i] <= 16'sd16384;
delay_line[i] <= 0;
end
end else if (valid_in) begin
lfsr_fade <= {lfsr_fade[30:0], lfsr_fade[31] ^ lfsr_fade[21]};
delay_line[0] <= signal_in;
for (i = 1; i < TAP_NUM; i = i + 1)
delay_line[i] <= delay_line[i-1];
for (i = 0; i < TAP_NUM; i = i + 1)
fade_coeff[i] <= fade_coeff[i] +
{{8{lfsr_fade[7]}}, lfsr_fade[7:0]} >>> 4;
end
end
reg signed [DATA_W+4:0] sum_out;
always @(*) begin
sum_out = 0;
for (i = 0; i < TAP_NUM; i = i + 1)
sum_out = sum_out + (delay_line[i] * fade_coeff[i]) >>> 15;
end
assign signal_out = sum_out[DATA_W-1:0];
assign valid_out = valid_in;
endmodule
// 莱斯衰落信道 (K因子可配)
module rician_channel #(
parameter DATA_W = 12,
parameter K_FACTOR_DB = 6 // K因子(dB)
)(
input wire clk,
input wire rst_n,
input wire signed [DATA_W-1:0] signal_in,
input wire valid_in,
output wire signed [DATA_W-1:0] signal_out,
output wire valid_out
);
// LOS分量 (固定增益)
localparam signed [15:0] los_gain =
$rtoi(2**15 * $sqrt(10**(K_FACTOR_DB/10.0) / (10**(K_FACTOR_DB/10.0) + 1)));
// NLOS分量 (瑞利衰落)
wire signed [DATA_W-1:0] nlos_out;
rayleigh_channel #(
.DATA_W(DATA_W),
.TAP_NUM(1),
.SEED(32'h12345678)
) u_rayleigh (
.clk(clk), .rst_n(rst_n),
.signal_in(signal_in), .valid_in(valid_in),
.signal_out(nlos_out), .valid_out()
);
// LOS + NLOS
localparam signed [15:0] nlos_gain = 2**15 - los_gain;
assign signal_out = (signal_in * los_gain + nlos_out * nlos_gain) >>> 15;
assign valid_out = valid_in;
endmodule
#!/usr/bin/env python3
"""channel_sim.py - 信道模型仿真 - 第07课"""
import numpy as np
import matplotlib.pyplot as plt
def awgn(signal, snr_db):
"""AWGN信道"""
snr_lin = 10**(snr_db/10)
return signal + np.sqrt(np.mean(signal**2)/(2*snr_lin))*np.random.randn(len(signal))
def rayleigh_fade_jakes(num_samples, fd, fs):
"""Jakes模型生成瑞利衰落"""
t = np.arange(num_samples)/fs
h = np.zeros(num_samples, dtype=complex)
N = 20
for n in range(N):
theta = 2*np.pi*n/N
phi = np.random.uniform(0, 2*np.pi)
h += np.exp(1j*(2*np.pi*fd*np.cos(theta)*t + phi))
return h / np.sqrt(N)
def simulate_channel_ber():
"""对比AWGN和瑞利衰落信道的BER"""
np.random.seed(42)
num_bits = 100000
bits = np.random.randint(0, 2, num_bits)
symbols = 1 - 2*bits
snr_range = np.arange(0, 30)
ber_awgn, ber_rayleigh = [], []
for snr_db in snr_range:
# AWGN
rx = awgn(symbols, snr_db)
ber_awgn.append(max(np.sum(bits != (rx < 0).astype(int))/num_bits, 1e-7))
# 瑞利 + AWGN
errs = 0
for _ in range(5):
h = np.abs(np.random.randn()+1j*np.random.randn())/np.sqrt(2)
rx_r = h*symbols + np.sqrt(1/(2*10**(snr_db/10)))*np.random.randn(num_bits)
errs += np.sum(bits != (rx_r < 0).astype(int))
ber_rayleigh.append(max(errs/(5*num_bits), 1e-7))
plt.figure(figsize=(10, 7))
plt.semilogy(snr_range, ber_awgn, 'c-o', markersize=4, label='AWGN')
plt.semilogy(snr_range, ber_rayleigh, '#f59e0b-^', markersize=4, label='Rayleigh')
plt.xlabel('Eb/N0 (dB)'); plt.ylabel('BER')
plt.title('BPSK在AWGN和瑞利衰落下的BER对比')
plt.legend(); plt.grid(True, alpha=0.3, which='both'); plt.ylim(1e-6, 1)
plt.savefig('/var/www/ttl/digital-comm/channel_ber.png', dpi=100,
facecolor='#0f172a', edgecolor='none')
print("信道BER对比图已保存")
def simulate_multipath_pdp():
"""多径功率时延谱分析"""
fs = 100e6
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
for idx, (tau_ns, label) in enumerate([(50, '室内(50ns)'),
(500, '室外(500ns)'),
(5000, '广域(5us)')]):
num_taps = max(int(tau_ns*1e-9*fs)+1, 1)
tap_powers = np.exp(-np.arange(num_taps)/max(num_taps/5, 1))
h = np.sqrt(tap_powers/2)*(np.random.randn(num_taps)+1j*np.random.randn(num_taps))
H = np.fft.fft(h, 1024)
freq = np.fft.fftfreq(1024, 1/fs)/1e6
axes[idx].plot(freq[:512], 20*np.log10(np.abs(H[:512])+1e-10), 'c-')
coherence_bw = 1/(5*tau_ns*1e-9)/1e6
axes[idx].axhline(-3, color='r', linestyle='--', alpha=0.5)
axes[idx].set_title(f'{label}, Bc={coherence_bw:.1f}MHz')
axes[idx].set_xlabel('频率(MHz)'); axes[idx].set_ylabel('|H(f)| (dB)')
axes[idx].grid(True, alpha=0.3); axes[idx].set_ylim(-30, 10)
plt.tight_layout()
plt.savefig('/var/www/ttl/digital-comm/multipath.png', dpi=100,
facecolor='#0f172a', edgecolor='none')
print("多径信道图已保存")
def simulate_rician_k_factor():
"""莱斯K因子对BER的影响"""
np.random.seed(42)
num_bits = 50000
bits = np.random.randint(0, 2, num_bits)
symbols = 1 - 2*bits
snr_db = 15
k_factors = np.arange(-5, 21, 1)
bers = []
for k_db in k_factors:
k_lin = 10**(k_db/10)
los_power = k_lin / (k_lin + 1)
nlos_power = 1 / (k_lin + 1)
errs = 0
for _ in range(10):
h_los = np.sqrt(los_power)
h_nlos = np.sqrt(nlos_power/2)*(np.random.randn()+1j*np.random.randn())
h = h_los + h_nlos
rx = h*symbols + np.sqrt(1/(2*10**(snr_db/10)))*np.random.randn(num_bits)
errs += np.sum(bits != (rx < 0).astype(int))
bers.append(max(errs/(10*num_bits), 1e-7))
plt.figure(figsize=(10, 6))
plt.semilogy(k_factors, bers, 'c-o', markersize=5)
plt.xlabel('K因子 (dB)'); plt.ylabel('BER')
plt.title(f'莱斯信道K因子对BER的影响 (SNR={snr_db}dB)')
plt.grid(True, alpha=0.3, which='both')
plt.savefig('/var/www/ttl/digital-comm/rician_k.png', dpi=100,
facecolor='#0f172a', edgecolor='none')
print("莱斯K因子图已保存")
if __name__ == '__main__':
simulate_channel_ber()
simulate_multipath_pdp()
simulate_rician_k_factor()
print("✅ 信道模型仿真全部完成!")
练习1:实现莱斯衰落信道(K因子可配),分析K对BER的影响。
练习2:用Python仿真频率选择性衰落信道,观察ISI现象。
练习3:改进AWGN仿真器,使用Box-Muller变换生成更精确的高斯噪声。
练习4:仿真多普勒频移对载波同步的影响,计算不同移动速度下的相干时间。
练习5:实现2×2 MIMO瑞利衰落信道模型,分析空间分集增益。
你理解了通信信道的物理本质!从AWGN到瑞利衰落,从多径时延到多普勒扩展,你已经能建模和仿真真实的无线信道了。
下一课预告:第08课将学习最简单的纠错码——汉明码。