QPSK调制CDMA系统仿真
在现代无线通信系统中,信道的码分多址**CDMA(Code Division Multiple Access)**的技术仍然是在公共频带中为多个用户提供同时数据传输的基本方法。 设计此类系统的一个关键方面是确保信道正交性和噪声容限,这需要在开发阶段仔细建模。
CDMA的主要原理:
/原理/描述|
|:---|:---|
/频谱扩展|每一位数据乘以高频码序列(码片序列),以频率"扩展"信号|
/码的正交性|不同信道的码被选择成使得它们的互相关接近于零(例如,沃尔什码),这使干扰最小化|
/频率共享/所有用户在同一时间工作在同一载波频率上,仅在代码上不同|
/绑定(解扩)/在接收侧,信号乘以相同的代码,这恢复了原始数据并抑制了其他用户的信号|
CDMA的优点:
-抗窄带干扰和衰落
-蜂窝网络中软切换(soft handoff)的可能性
-灵活的系统容量管理
-由于伪随机码增加传输安全性
申请表格:
-2g/3g蜂窝网络(IS-95,CDMA2000,WCDMA)
-全球定位系统(GPS,GLONASS)
-卫星通信
-军事安全通信系统
在我们的模型中,CDMA通过QPSK调制、Walsh码(以分离导频和用户信道)和PN序列(用于额外的频谱扩展)的组合来实现,这对应于直接频谱扩展系统(DSSS-CDMA)的经典架构。
该模型由两个用户子系统(Pilot_Channel 和 User1_Traffic_Channel),产生导频信道和用户业务信号。 信号经过正交相位操作(qpsk),用唯一的代码序列扩展,并在通过噪声信道传输之前进行求和。 在接收器侧,执行反向卷积和解调操作以恢复原始数据。
与Engee的集成允许灵活控制信号参数:脚本中计算的代码序列通过工作区块的信号加载到模型中,这确保了匹配数学描述和模拟的高精度。
Pkg.add("JLD2")
using JLD2, Statistics, DataFrames
下面的代码执行模拟数据的初始加载和可视化验证。
A = load("data.jld2", "A")
Size_A = length(A)
println("Size A: $(Size_A)")
plot(A[1:300])
功能 pn_gen(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
*基于线性反馈移位寄存器(LFSR)实现伪随机序列发生器(PN)。
*接受寄存器的初始状态、生成多项式的指数向量和输出序列的所需长度。
*确定寄存器N的长度并创建其副本以进行操作。
*将多项式的指数转换为抽头:如果指数为0,则将抽头添加到最后位置N,否则将抽头添加到位置N—e。
*生成给定长度的序列:在每个步骤中,它将寄存器的最后一位存储为输出,将反馈位计算为所有抽头的异或,并在开始时将寄存器与反馈位一起向右移位。
*返回整数0和1的数组(与MATLAB格式兼容)。
功能 pn_gen_walsh(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
*原因 pn_gen 得到基本二进制序列。
*执行格式转换:每个0替换为1,每个1替换为-1。
*返回+1/-1格式的序列,可用于沃尔什码的调制和乘法。
功能 walsh_hadamard(n::Int, size::Int)
*生成给定长度的正交Walsh-Hadamard码。
*从基本的4×4Hadamard矩阵开始。
*根据[H H;H-H]规则进行两次迭代扩展,形成一个16×16的矩阵。
*提取索引为n+1的字符串(从0开始编号通道)。
*重复(repeats)接收到的字符串所需的次数,以达到所需的长度大小。
*返回与Hadamard矩阵的其他行正交的+1/-1序列。
function pn_gen(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
N = length(init_state)
reg = copy(init_state)
taps = Int[]
for e in poly_exp
if e == 0
push!(taps, N)
elseif e != N
push!(taps, N - e)
end
end
outputs = Bool[]
for _ in 1:n
push!(outputs, reg[end] == 1)
fb = 0
for t in taps
fb = xor(fb, reg[t])
end
reg = [fb; reg[1:end-1]]
end
return Int.(outputs)
end
function pn_gen_walsh(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
raw = pn_gen(init_state, poly_exp, n)
return [x == 0 ? 1 : -1 for x in raw]
end
function walsh_hadamard(n::Int, size::Int)
H = [1 1 1 1; 1 -1 1 -1; 1 1 -1 -1; 1 -1 -1 1]
for i in 1:2
H = [H H; H -H]
end
code = H[n+1, :]
return repeat(code, inner=div(size, 16))
end
用于生成PN码的代码如下所示。
PN码是为信号的两个分支—共模(I)和正交(Q)单独生成的。 对于每个分支,使用一个特殊的生成器,根据移位寄存器的某些参数和反馈多项式生成随机值序列(+1或-1)。
创建沃尔什码以分离系统内的信道。 导频信道接收单单位码,第一用户信道接收交替码。 这些代码允许您分离不同用户的信号,并帮助接收器在同时传输的许多信号中识别所需的信号。
对于每个信道,通过乘以PN码和相应的Walsh码来生成最终信号。 这确保了来自不同用户的信号的分离,并有助于有效地并行传输数据。 然后检查接收信号的特性。 确认它们平衡良好(平均值接近零,标准偏差为1),这对于高质量的数据传输很重要。
pn_I = pn_gen_walsh([1; zeros(Int, 14)], [15, 13, 9, 8, 7, 5, 1], Size_A)
pn_Q = pn_gen_walsh([1; zeros(Int, 14)], [15, 12, 11, 10, 6, 5, 4, 3, 1], Size_A)
walsh_pilot = walsh_hadamard(0, Size_A) # [1,1,1,1...]
walsh_user1 = walsh_hadamard(1, Size_A) # [1,-1,1,-1...]
pilot_I = pn_I .* walsh_pilot
pilot_Q = pn_Q .* walsh_pilot
user1_I = pn_I .* walsh_user1
user1_Q = pn_Q .* walsh_user1
code_list = [A, pilot_I, pilot_Q, user1_I, user1_Q]
code_names = ["A (engee)", "Pilot I", "Pilot Q", "User1 I", "User1 Q"]
df_stats = DataFrame(
代码=code_names,
长度=[code_list中c的长度(c)],
Average=[round(mean(c),digits=4)for c in code_list],
Std = [round(std(c), digits=4) for c in code_list],
Min=[code_list中c的最小值(c)],
Max=[code_list中c的最大值(c)],
Percent_1=[code_list中c的round(count(==(1),c)/length(c)*100,digits=2)],
Percent_minis1=[code_list中c的round(count(==(-1),c)/length(c)*100,digits=2)]
)
println(df_stats)
统计表的分析显示了信号的以下特征:
*原始信号"A"是单极性的,零和一的分布相等。 标准偏差对应于对具有相等符号概率的二进制信号的期望。
*导频信道信号(导频I和导频Q)具有接近于零的平均值,这表明良好的平衡和不存在恒定分量。 标准偏差等于一,确认归一化信号功率。 单位和减单位的百分比分布接近50/50,确保了平衡的序列。
*用户通道(User1I和User1Q)也显示近零平均值和标准偏差为1。 正负单元的分布尽可能平衡,特别是对于User1Q。
一般结论证实所有信道信号具有最优的传输特性:零恒定分量、归一化功率和符号的相等概率。 与理想的小偏差与序列的精细性和统计波动有关。
下面的代码计算通道对之间的相关性,它创建一个列表 corr_data,包含成对的信道和相应的相关系数。 系数的计算方法是按元素乘以两个通道的相应元素,对结果求和,并除以序列的长度进行归一化。 然后形成表 df_corr 有两列:通道对的名称和相关的数值。 表显示在屏幕上的命令 println.
corr_data = [
("Pilot I × User1 I", round(sum(pilot_I .* user1_I)/length(pilot_I), digits=4)),
("Pilot Q × User1 Q", round(sum(pilot_Q .* user1_Q)/length(pilot_Q), digits=4))
]
df_corr = DataFrame(
Pair=[x[1]for x in corr_data],
Corr_data中x的相关性=[x[2]]
)
println(df_corr)
零相关性证实了沃尔什码的正交性、不存在相互干扰以及CDMA系统中信道信号的正确形成。 现在让我们运行我们的模型,并确保所选的值是正确的。
function run_model( name_model)
Path = (@__DIR__) * "/" * name_model * ".engee"
if name_model in [m.name for m in engee.get_all_models()]
model = engee.open( name_model )
model_output = engee.run( model, verbose=true );
else
model = engee.load( Path, force=true )
model_output = engee.run( model, verbose=true );
engee.close( name_model, force=true );
end
sleep(0.1)
return model_output
end
run_model("CDMA_MAI")
BER = collect(simout["CDMA_MAI/Error Rate Calculation.1"]).value[end]
println("误码率(BER):△(BER[1])")
println("错误数:$(BER[2])")
println("总位数:$(BER[3])")
结论
在信噪比SNR=10dB下,实现了零误码概率(BER=0)。 这演示了CDMA模型的所有组件的正确操作:伪噪声序列的生成,正交信道码的创建,具有相移的QPSK调制。 /4和随后的解调。
相关分析的结果证实了由于所使用的沃尔什码的完美正交性,信道之间完全没有串扰。 因此,仿真成功地证明了CDMA系统的正确功能及其在给定序列长度上提供可靠的无损数据传输的能力。