OFDM通信传输系统中QAM
秋招IC项目,自用留存,不保证正确,仅供参考。
为什么要用QAM
也就是说我们可以通过控制幅度与相位这两个参数来控制我们最终输出的波形。而通过之前的学习,我们知道,OFDM传输的实质就是让不同频率(频率之间必须是谐波,如果不是谐波,在一个周期内积分的结果不是0,也就不是正交的)的正弦余弦波乘上幅度信息,再通过IFFT将这一系列谐波相加之后进行传输。而我们要传输的信息就隐藏在正弦波的幅度上,也就是说,我们必须要把我们要传输的信息转换成幅度和相位这两个参数。
怎么用QAM
星座图与映射
我们要传输的信息是一串比特流,那么怎么将一串包含了1,0的比特流转化成我们需要的幅度和相位信息呢,这就要用到星座图。
星座图中的每个蓝点都代表一组的I和Q,同时对应了一组A和φ(
为什么每个蓝点能对应一组A和φ,看这篇文章最详细解读QAM 调制)。以1000为例,通过映射表我们可以将这4个bit的数据转化成一个数字。
10映射为3,00映射为-3,这样我们就将这这4个bit的信息转化成了我们需要的Q/I信息。接下来要做的就是要对我们映射后信号进行归一化。
归一化
为什么要进行归一化我没在网上找到较权威的解释,chatgpt告诉我,进行归一化是为了提高信号的稳定性,抗干扰性和能效,从而增强通信系统的性能。
进行归一化的操作主要是让我们映射后的I/Q信号除以某个数(归一化因子)。归一化因子有两种选择,\sqrt{2} 与 \sqrt{10} 。先说\sqrt{2},这同样是chatgpt告诉我的。
根号2(√2)是一个常用的归一化因子,用于使信号的平均功率达到单位功率(1)。这种归一化方式有几个好处:
-
符号点功率一致性:通过除以√2,每个符号点的功率都被调整为相同的值,这有助于确保所有符号点在传输过程中受到相同的待遇,提高了信号的可靠性和抗干扰性。
-
易于解调:接收端需要知道符号点的平均功率,以正确地解码信号。通过使用√2作为归一化因子,接收端可以轻松地知道符号点的平均功率为1,从而简化了解调器的设计。
-
功率效率:归一化到单位功率有助于确保在传输过程中不浪费过多的功率。如果不进行归一化,可能需要更大的功率来传输相同的数据,这会导致不必要的功率浪费。
但是在《基于xilinx FPGA的OFDM通信系统基带设计》这一本书中,选择归一化因子是\sqrt{10}。我的理解是在星座图中,距离原点最远的坐标是(3,3),而一个\sqrt{10}的圆能包裹住所有的点。所有点的归一化都是在以这个圆为基准。所以是除以\sqrt{10}。这样以来归一化后的值既小于1,每个幅度的区别有尽可能地大。
归一化后的数据就是调制后的Q/I值,Q/I数据分别进行A/D转换,得到两路模拟电平信号,用于和正弦余弦信号相乘,从而实现调制。
具体实现归一化的方法是通过matlab中的fi()和bin()。
也就是说将00这2bit的数据转换成16bit的数据(1100001101001001)
verilog代码实现
parameter map_dataa = 16'b1100001101001001; // -3/√10
parameter map_datab = 16'b1110101111000011; // -1/√10
parameter map_datac = 16'b0001010000111101; // 1/√10
parameter map_datad = 16'b0011110010110111; // 3/√10
always@(posedge clk or negedge reset) begin
if(!reset) begin
div_cnt <= 2'd0;
map_en <= 1'b0;
end
else begin
if(din_valid) begin
div_cnt <= div_cnt + 1'b1;
if(div_cnt == 2)
map_en <= 1'b1;
else
map_en <= 1'b0;
end
else begin
div_cnt <= 2'd0;
map_en <= 1'b0;
end
end
end
always@(posedge clk or negedge reset)
begin
if(!reset)begin
din_men<=0;
end
else if(din_valid) begin
din_men<={din_men[2:0],qam_din};
end
end
reg [15:0] imag_men;
reg [15:0] real_men;
reg dout_en;
always@(posedge clk or negedge reset)
begin
if(!reset)begin
imag_men<=0;
real_men<=0;
dout_en<=0;
end
else begin
if(map_en)begin
case (din_men[1:0])
2'b00:real_men<=map_dataa;
2'b01:real_men<=map_datab;
2'b10:real_men<=map_datac;
2'b11:real_men<=map_datad;
default : real_men <= 0;
endcase
case (din_men[3:2])
2'b00:imag_men<=map_dataa;
2'b01:imag_men<=map_datab;
2'b10:imag_men<=map_datac;
2'b11:imag_men<=map_datad;
default : imag_men <= 0;
endcase
dout_en<=1'b1;
end
else begin
imag_men<=0;
real_men<=0;
dout_en<=0;
end
end
end
关于16QAM的私货
在我看来,16QAM就是将较短的信息bit扩展成较长信息。这样做的目的主要有两个
- 符较短的信息在传输的过程中,一旦发生错误,对于整个传输系统都是致命的。因为我们不仅没办法将错误的信息恢复出来,更重要的是我们不知道信息在传输的过程中有没有出错。经过QAM之后,当我们解调出来的数据不是我们一开始设定的4个映射值,我们就知道我们在传输的过程中出现了错误,并可以根据错误位置尝试将错误恢复过来。
- QAM可以在有限的频谱带宽中传输更多数据,因为通过幅度和相位两个变量,使得载波承载两倍的信息,在16QAM中不太明显,但是在256QAM中就很明显了。