AnyMath 文档
Notebook

工程IP核上的OFDM调制解调

在示例中,让我们考虑通过AnyMath IP核上的OFDM调制器和解调器传输BPSK和QPSK信号。 让我们检查数据恢复,评估EVM,并查看星座。 该模型在没有噪声的情况下工作,因此结果显示了具有固定点的计算误差。

OFDM跨正交子载波分配数据。 发射机使用IFFT生成符号并添加循环前缀;接收机去除前缀并执行FFT。 在我们的模型中,2048个子载波用于数据

其余部分保留用于保护频带和零子载波。

ofdm_model-05.10.26 21_46_16.png

C中的生成器输出q14格式的复数BPSK或QPSK样本。 转换为定点后,信号经过OFDM调制器和OFDM解调器。

FFT大小为2048,循环前缀为64个样本,窗口为32. 保护频带包含128和127个子载波,DC子载波被禁用。 输入端系数为0.5会产生幅度裕度,输出端系数为2会恢复比例。 StartupReset在前四个时钟周期重置内核。

参数和准备

采样频率为30.72mhz,仿真时间为1ms,一个带有前缀的字符需要2112个时钟周期。 首先,让我们下载模型的启动和分析功能。

In [ ]:
using Main: engee, plot, plot!, histogram, hline!, savefig, Animation, frame, gif
using JSON
if !isdefined(Main, :OFDMIPDemo)
    Base.include(Main, joinpath(@__DIR__, "ofdm_demo.jl"))
end
using Main: OFDMIPDemo
ofdm_dir = @__DIR__
ofdm_output = mktempdir(; prefix="ofdm_ip_results_")
println("结果: ", ofdm_output)
println("FFT = ", OFDMIPDemo.NFFT, ";有用子载波= ", OFDMIPDemo.ND)
Результаты: /tmp/ofdm_ip_results_ZauQcB
FFT = 2048; полезных поднесущих = 1792

模型、辅助脚本和生成器的源代码位于此脚本旁边。 路径是相对于其文件夹确定的。

BPSK验证

让我们运行BPSK模型。 让我们比较传输和恢复的字符,并检查位错误的数量。

In [ ]:
bpsk_result = OFDMIPDemo.run_case(ofdm_dir; modulation=0)
println(JSON.json(bpsk_result.metrics))
write(joinpath(ofdm_output, "bpsk_metrics.json"), JSON.json(bpsk_result.metrics))
{"Nfft":2048,"input_headroom":0.5,"output_valid":14054,"sample_rate":3.072e7,"compared_samples":12544,"bit_errors":0,"cp":64,"Nd":1792,"bits_compared":12543,"compared_symbols":7,"window":32,"evm_percent":0.4637339147816772,"output_gain":2.0,"modulation":"BPSK","input_valid":26237,"alignment_offset":0}
Out[0]:
302

获得了七个完整的OFDM符号:12544个复数样本。 EVM约为0.46%,没有误码。 初始零计数不涉及检查位。

EVM是使用具有有效信号的完整模块计算的,无需调整相位和比例:

BPSK分析

让我们绘制星座图、恢复误差和有效信号。

In [ ]:
bpsk_figure = OFDMIPDemo.result_plot(bpsk_result)
savefig(bpsk_figure, joinpath(ofdm_output, "bpsk_results.png"))
display(bpsk_figure)

恢复的点位于原始点的旁边。 误差图显示了计算误差,有效信号是内核输出数据的间隔。

检查QPSK

让我们为QPSK重复发射。 位由重构信号的实部和虚部的符号确定。

In [ ]:
qpsk_result = OFDMIPDemo.run_case(ofdm_dir; modulation=1)
println(JSON.json(qpsk_result.metrics))
qpsk_figure = OFDMIPDemo.result_plot(qpsk_result)
savefig(qpsk_figure, joinpath(ofdm_output, "qpsk_results.png"))
display(qpsk_figure)
{"Nfft":2048,"input_headroom":0.5,"output_valid":14054,"sample_rate":3.072e7,"compared_samples":12544,"bit_errors":0,"cp":64,"Nd":1792,"bits_compared":25086,"compared_symbols":7,"window":32,"evm_percent":0.4684031971951881,"output_gain":2.0,"modulation":"QPSK","input_valid":26237,"alignment_offset":0}

对于QPSK,我们得到四组点,EVM约为0.47%,而不是25086个检查位中的单个错误。

结果的可重复性和保留性

让我们再次运行BPSK并比较结果。 我们将保存三次发射的数据以供进一步分析。

In [ ]:
bpsk_repeat = OFDMIPDemo.run_case(ofdm_dir; modulation=0)
@assert bpsk_repeat.metrics["evm_percent"] == bpsk_result.metrics["evm_percent"]
@assert bpsk_repeat.metrics["bit_errors"] == 0
ofdm_report = Dict("status"=>"passed", "notebook_executed"=>true, "channel"=>"direct noiseless IP-core loopback", "runs"=>[bpsk_result.metrics, qpsk_result.metrics, bpsk_repeat.metrics])
write(joinpath(ofdm_output, "verification.json"), JSON.json(ofdm_report))
string("OFDM IP demo passed; BPSK EVM=", round(bpsk_result.metrics["evm_percent"];digits=4), "%; QPSK EVM=", round(qpsk_result.metrics["evm_percent"];digits=4), "%; bit errors=0")
Out[0]:
"OFDM IP demo passed; BPSK EVM=0.4637%; QPSK EVM=0.4684%; bit errors=0"

再次运行它会提供相同的数据和指标。 这证实了具有相同参数和核心复位的模型的再现性。

结论

该模型演示了在AnyMath IP核上使用BPSK和QPSK副载波调制进行OFDM传输。 在无噪声通道中,恢复数据时不会出现误码,EVM约为0.46-0.47%。 接受符号的轻微偏差是由于在固定点进行计算。