目录
- 1. 前言
- 2. 调制
- 2.1 QAM调制
- 2.2 64-QAM 调制
- 2.3 16-QAM 调制
- 3.模块实现
- 4.Matlab仿真
- 5.ModelSim仿真
- 6.verilog代码
原文连接(相关文章合集): OFDM 802.11a的xilinx FPGA实现
1. 前言
在上一篇博客当中,已经完成了数据域的交织,数据域的数据经过交织之后,下一步就是需要对交织之后的bit进行星座图的映射了。
2. 调制
在 OFDM 通信系统中根据不同的速率要求,其子载波需要用二进制相移键控(BPSK)、正交相移键控(QPSK)、或正交幅度调制(QAM)方式进行调制。数据经过卷积编码和交织后,串行比特流每 1、2、4 或 6 个比特被分为一组,用一定的规律将比特流映射成为复数,形成 BPSK,QPSK,16-QAM,64-QAM 调制。
在传输过程中调制方式可能发生变化,如 signal 域的数据采用的是 bpsk 调制,而 data 域采用的是另一种调制方式,为了使所有的映射有一样的平均功率,需要对映射进行归一化。映射后的复数值乘上一个归一化的量 Kmod,即可得到输出数据。Kmod 的值根据不同的调制模式而不同。
2.1 QAM调制
QAM 与其他调制技术相比,能得到更高的频谱效率,且具有抗噪声能力强等优点,因此得到了广泛的应用。QAM调制中,数据信号由相互正交的两个载波的幅度变化表示。QAM 是一种矢量调制,将输入比特先映射(一般采用格雷码)到一个复平面(星座图)上,形成复数调制符号,然后将该符号的 i、q 分量(即该复数的实部和虚部)分别对应调制在相互正交(时域正交)的两个载波cos 和 sin 上。
正交振幅调制可以表示为:
s ( t ) = A m c o s ( w t ) + B m c o s ( w t ) ( 0 ≤ t ≤ T s ) s(t)=A_{m}cos(wt)+B_{m}cos(wt) (0 \leq t\leq Ts) s(t)=Amcos(wt)+Bmcos(wt)(0≤t≤Ts)
上述式子当中 A m , B m A{m}, B{m} Am,Bm就是调制之后得到的实部和虚部的数据。
2.2 64-QAM 调制
64-QAM在星座图上具有64个星座点,每个星座点代表一种状态,每6个bit表示一个星座点,其映射关系如下:
串行输入的bit,每6个bit构成一个星座点,第一个进来的是b0,进入的顺序依次排列为b0b1b2b3b4b5,根据映射表,可以得到虚部和实部的映射结果:
b0b1b2对应I路,b3b4b5对应Q路数据,再乘以归一化因子,得到调制之后的IQ路的值。
2.3 16-QAM 调制
16-QAM在星座图上具有16个星座点,每个星座点代表一种状态,每4个bit表示一个星座点,其映射关系如下:
串行输入的bit,每4个bit构成一个星座点,第一个进来的是b0,进入的顺序依次排列为b0b1b2b3,根据映射表,可以得到虚部和实部的映射结果:
b0b1 | Re/I | b2b3 | Im/Q |
---|---|---|---|
00 | -3 | 00 | -3 |
01 | -1 | 01 | -1 |
11 | 1 | 11 | 1 |
10 | 3 | 10 | 3 |
3.模块实现
设计上,通过调制方式不同,将串行数据流以1、2、4或6比特分成一组,缓存在一个6比特寄存器中,等到比特数据达到一组时,通过该组数据映射方式进行映射并归一化得到调制的I和Q两路数据。复数以8位定点数形式进行输出,格式为:1位符号位,一位整数位,6位小数位,负数以补码形式表示。与上下游端口数据交互依然采用valid-ready握手机制,不必又去跨时钟域。
输出实部和虚部各8位,一位符号位,一位整数位,六位小数位;高8位为实部,低8位为虚部。Index_Out为输出标号。端口示意图如下:
4.Matlab仿真
以2个OFDM符号,16-QAM调制,编码效率为3/4,进行仿真,生成测试数据共计288个,如下:
test_data =列 1 至 270 1 1 0 1 1 0 1 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 1列 28 至 541 1 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 1列 55 至 811 1 1 0 0 1 0 0 1 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1 0 1 0列 82 至 1081 0 1 0 1 1 0 1 0 0 1 1 1 0 1 1 1 1 1 0 0 1 0 0 1 1 1列 109 至 1350 1 0 1 1 1 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0列 136 至 1621 0 0 0 0 1 0 0 1 0 0 1 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0列 163 至 1891 0 0 1 0 1 1 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 1 0 1 1 1列 190 至 2160 0 0 1 0 1 0 0 1 0 0 1 0 0 1 1 1 1 0 0 1 0 1 1 0 0 1列 217 至 2431 0 1 1 0 0 1 1 0 0 1 1 1 0 0 0 1 1 0 0 1 0 1 0 0 0 0列 244 至 2701 0 1 0 0 1 1 1 0 0 1 0 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1列 271 至 2880 1 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1
测试数据经过前面章节的扰码、编码、删余、交织,然后进行如下的调制映射:
%% 调制映射
mod_out = qammod(int_lea_2_out', 2^M, 'InputType', 'bit', 'UnitAveragePower', true, 'PlotConstellation', true)';%复数以8位定点数形式进行输出,格式为:1位符号位,一位整数位,6位小数位,负数以补码形式表示。
q = quantizer('fixed','round','saturate',[8,6]);
mod_out_q = num2bin(q,mod_out);%量化
mod_out = bin2num(q,mod_out_q);%反量化
调制映射结果如下:
mod_out =列 1 至 8-0.9531 - 0.3125i 0.3125 + 0.9531i -0.9531 + 0.9531i -0.9531 + 0.3125i 0.9531 + 0.3125i 0.3125 - 0.9531i -0.3125 - 0.9531i 0.3125 - 0.3125i列 9 至 160.3125 + 0.9531i -0.9531 - 0.9531i 0.3125 - 0.9531i 0.9531 - 0.3125i -0.9531 + 0.9531i 0.3125 + 0.3125i 0.3125 - 0.9531i 0.9531 + 0.9531i列 17 至 24-0.9531 - 0.9531i -0.9531 + 0.9531i -0.3125 - 0.9531i 0.9531 + 0.9531i -0.3125 + 0.3125i -0.9531 - 0.3125i -0.3125 - 0.3125i 0.9531 + 0.3125i列 25 至 32-0.3125 + 0.3125i -0.9531 - 0.3125i -0.3125 + 0.3125i 0.9531 + 0.3125i 0.3125 + 0.3125i 0.9531 + 0.3125i 0.9531 - 0.9531i 0.3125 - 0.3125i列 33 至 40-0.3125 + 0.3125i -0.9531 + 0.9531i -0.3125 - 0.9531i -0.9531 + 0.9531i 0.3125 + 0.3125i 0.9531 - 0.3125i 0.3125 + 0.3125i 0.9531 - 0.9531i列 41 至 480.3125 + 0.3125i 0.3125 - 0.3125i -0.9531 + 0.3125i -0.9531 + 0.3125i -0.9531 + 0.3125i 0.9531 - 0.3125i -0.9531 + 0.9531i -0.9531 - 0.3125i列 49 至 560.9531 + 0.9531i -0.9531 + 0.3125i -0.3125 + 0.9531i 0.9531 - 0.3125i 0.3125 + 0.3125i 0.9531 + 0.3125i -0.9531 - 0.3125i -0.3125 - 0.3125i列 57 至 64-0.3125 - 0.3125i 0.3125 + 0.3125i -0.9531 + 0.9531i -0.3125 - 0.9531i -0.3125 - 0.3125i 0.3125 - 0.9531i 0.9531 - 0.3125i 0.9531 + 0.9531i列 65 至 720.9531 + 0.9531i -0.3125 + 0.9531i -0.9531 + 0.9531i -0.3125 - 0.3125i 0.9531 - 0.3125i 0.3125 + 0.3125i 0.3125 + 0.9531i -0.3125 + 0.9531i列 73 至 800.3125 - 0.9531i -0.9531 - 0.3125i -0.3125 - 0.3125i 0.3125 + 0.3125i 0.9531 - 0.3125i 0.3125 - 0.9531i 0.3125 - 0.9531i 0.9531 + 0.3125i列 81 至 880.3125 - 0.9531i -0.3125 + 0.3125i 0.3125 + 0.3125i 0.9531 - 0.3125i -0.9531 + 0.3125i 0.9531 - 0.9531i 0.3125 - 0.3125i 0.9531 + 0.3125i列 89 至 960.3125 - 0.9531i 0.9531 - 0.9531i 0.3125 + 0.3125i 0.9531 + 0.3125i 0.3125 - 0.3125i 0.9531 - 0.3125i 0.3125 - 0.9531i -0.3125 - 0.9531i
5.ModelSim仿真
按照如下图所示进行连接,输入测试数据进行仿真:
仿真结果如下图所示:
将仿真结果存为txt文件,在Matlab里面读出来与Matlab的仿真结果进行比较,代码如下:
clc;
%% 串并转换
test_data = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/test_data.txt')';
display(test_data);
FPGA_S2P2S = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/u2_data_out.txt')';
display(FPGA_S2P2S);
check_S2P = test_data == FPGA_S2P2S;
display(check_S2P);
%% 扰码
FPGA_scram_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/scram_data_out.txt')';
display(scram_out0);
display(FPGA_scram_dout);
check_scram = FPGA_scram_dout == scram_out0;
display(check_scram);
%% 卷积编码
FPGA_conv_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/conv_data_out.txt')';
display(conv_out0);
display(FPGA_conv_dout);
check_conv = FPGA_conv_dout == conv_out0;
display(check_conv);
%% 删余
FPGA_punt_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/punt_data_out.txt')';
display(conv_out);
display(FPGA_punt_dout);
check_punt = FPGA_punt_dout == conv_out;
display(check_punt);
%% 一级交织
FPGA_intv1_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/intv1_data_out.txt')';
display(int_lea_1_out);
display(FPGA_intv1_dout);
check_intv1 = FPGA_intv1_dout == int_lea_1_out;
display(check_intv1);
%% 二级交织
FPGA_intv2_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/intv2_data_out.txt')';
display(int_lea_2_out);
display(FPGA_intv2_dout);
check_intv2 = FPGA_intv2_dout == int_lea_2_out;
display(check_intv2);
%% 调制映射
FPGA_Re_map_dout = readlines('D:/FPGA/OFDM_802.11a_my/TX/matlab/map_Re_data_out.txt','EmptyLineRule','skip')';
FPGA_Im_map_dout = readlines('D:/FPGA/OFDM_802.11a_my/TX/matlab/map_Im_data_out.txt','EmptyLineRule','skip')';
% FPGA_Re_map_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/map_Re_data_out.txt')';
% FPGA_Im_map_dout = load('D:/FPGA/OFDM_802.11a_my/TX/matlab/map_Im_data_out.txt')';
% display(FPGA_Re_map_dout);
% display(FPGA_Im_map_dout);
q = quantizer('fixed','round','saturate',[8,6]);
FPGA_Re_map_dout = bin2num(q,FPGA_Re_map_dout);
FPGA_Im_map_dout = bin2num(q,FPGA_Im_map_dout);
FPGA_Re_map_dout = cell2mat(FPGA_Re_map_dout);
FPGA_Im_map_dout = cell2mat(FPGA_Im_map_dout);
FPGA_map_dout = FPGA_Re_map_dout + 1j*FPGA_Im_map_dout;
display(mod_out.');
display(FPGA_map_dout);
check_map = FPGA_map_dout == mod_out.';
display(check_map);
FPGA调制映射的输出为:
FPGA_map_dout =列 1 至 8-0.9531 - 0.3125i 0.3125 + 0.9531i -0.9531 + 0.9531i -0.9531 + 0.3125i 0.9531 + 0.3125i 0.3125 - 0.9531i -0.3125 - 0.9531i 0.3125 - 0.3125i列 9 至 160.3125 + 0.9531i -0.9531 - 0.9531i 0.3125 - 0.9531i 0.9531 - 0.3125i -0.9531 + 0.9531i 0.3125 + 0.3125i 0.3125 - 0.9531i 0.9531 + 0.9531i列 17 至 24-0.9531 - 0.9531i -0.9531 + 0.9531i -0.3125 - 0.9531i 0.9531 + 0.9531i -0.3125 + 0.3125i -0.9531 - 0.3125i -0.3125 - 0.3125i 0.9531 + 0.3125i列 25 至 32-0.3125 + 0.3125i -0.9531 - 0.3125i -0.3125 + 0.3125i 0.9531 + 0.3125i 0.3125 + 0.3125i 0.9531 + 0.3125i 0.9531 - 0.9531i 0.3125 - 0.3125i列 33 至 40-0.3125 + 0.3125i -0.9531 + 0.9531i -0.3125 - 0.9531i -0.9531 + 0.9531i 0.3125 + 0.3125i 0.9531 - 0.3125i 0.3125 + 0.3125i 0.9531 - 0.9531i列 41 至 480.3125 + 0.3125i 0.3125 - 0.3125i -0.9531 + 0.3125i -0.9531 + 0.3125i -0.9531 + 0.3125i 0.9531 - 0.3125i -0.9531 + 0.9531i -0.9531 - 0.3125i列 49 至 560.9531 + 0.9531i -0.9531 + 0.3125i -0.3125 + 0.9531i 0.9531 - 0.3125i 0.3125 + 0.3125i 0.9531 + 0.3125i -0.9531 - 0.3125i -0.3125 - 0.3125i列 57 至 64-0.3125 - 0.3125i 0.3125 + 0.3125i -0.9531 + 0.9531i -0.3125 - 0.9531i -0.3125 - 0.3125i 0.3125 - 0.9531i 0.9531 - 0.3125i 0.9531 + 0.9531i列 65 至 720.9531 + 0.9531i -0.3125 + 0.9531i -0.9531 + 0.9531i -0.3125 - 0.3125i 0.9531 - 0.3125i 0.3125 + 0.3125i 0.3125 + 0.9531i -0.3125 + 0.9531i列 73 至 800.3125 - 0.9531i -0.9531 - 0.3125i -0.3125 - 0.3125i 0.3125 + 0.3125i 0.9531 - 0.3125i 0.3125 - 0.9531i 0.3125 - 0.9531i 0.9531 + 0.3125i列 81 至 880.3125 - 0.9531i -0.3125 + 0.3125i 0.3125 + 0.3125i 0.9531 - 0.3125i -0.9531 + 0.3125i 0.9531 - 0.9531i 0.3125 - 0.3125i 0.9531 + 0.3125i列 89 至 960.3125 - 0.9531i 0.9531 - 0.9531i 0.3125 + 0.3125i 0.9531 + 0.3125i 0.3125 - 0.3125i 0.9531 - 0.3125i 0.3125 - 0.9531i -0.3125 - 0.9531i
与Matlab仿真结果对比如下:
check_map =1×96 logical 数组列 1 至 411 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1列 42 至 821 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1列 83 至 961 1 1 1 1 1 1 1 1 1 1 1 1 1
两个OFDM符号调制映射之后为96个输出,对比逻辑结果全为‘1’,说明FPGA该模块设计完全正确,作者测试了其他调制方案和数据速率都是正确的,这里不再重复赘述。感兴趣的可以自行进行测试。
原文连接(相关文章合集):OFDM 802.11a的xilinx FPGA实现
6.verilog代码
verilog代码链接