目录
- 1.前言
- 2.卷积编码
- 2.1卷积编码基本概念
- 2.2 802.11a卷积编码器
- 2.3 卷积编码模块设计
- 2.4 Matlab设计与ModelSim仿真验证
1.前言
前面一节完成了扰码器的FPGA设计与Matlab验证,这节继续对卷积编码器进行实现和验证。
2.卷积编码
2.1卷积编码基本概念
卷积码编码器实质上是一个有限状态的线性移位寄存器。这个移位寄存器由若干个寄存器单元组成,且寄存器单元按一定的规则连接到代数运算单元,将运算结果作为编码比特输出。
一个简单的卷积编码器的结构如下图所示:
R1, R2, R3, 是三个寄存器,输入数据进行过这个卷积编码器将在下方输出结果。
卷积编码的输出有如下关系:
假设输入的数据是0110,那么经过卷积编码器之后的结果可以由如下表格给出:
Input | R1 | R2 | R3 | Output |
---|---|---|---|---|
INIT | 0 | 0 | 0 | 000 |
0 | 0 | 0 | 0 | 000 |
1 | 1 | 0 | 0 | 111 |
1 | 1 | 1 | 0 | 110 |
0 | 0 | 1 | 1 | 010 |
如果将卷积编码的这个过程在一个图来表示可以按照如下的方式来标注:
网格图中,具有相同状态的节点合并在一起;当输入比特为零时用实线表示,当输入比特为 1 时用虚线;支路上标注的码元为输出比特;最左侧为卷积编器的低两个寄存器的值。
n:编码器每次输出的码元个数;
k:编码器每次输入的信息码元个数,一般 k=1;
N:约束长度,在 k=1 的情况下,表示编码器的输出与本次及之前输入的 N个码元相关;
那么上图所示的卷积编码结构可以描述为(3,1,3);其编码效率为 k/N,则该卷机编码的效率为 1/3。
2.2 802.11a卷积编码器
卷积编码使用的生成多项式是 g 0 = ( 133 ) 8 , g 1 = ( 171 ) 8 g0 = (133)_{8}, g1= (171)_{8} g0=(133)8,g1=(171)8,码率为 1/2,其生成多项式用二进制表示为 g0 = 1011011,g1 = 1111001,该卷积码可以表示为(2,1,7),即每时钟周期输出两个比特数据,输入 1 个比特数据,约束长度为7。
每输入一bit的数据,将会依次输出A,B两bit的数据。
输出数据A的生成多项式为:
S
A
(
x
)
=
x
6
+
x
5
+
x
3
+
x
2
+
1
S_A(x)=x^6+x^5+x^3+x^2+1
SA(x)=x6+x5+x3+x2+1
输出数据B的生成多项式为:
S
B
(
x
)
=
x
6
+
x
3
+
x
2
+
x
1
+
1
S_B(x)=x^6+x^3+x^2+x^1+1
SB(x)=x6+x3+x2+x1+1
因此,可以使用6个移位寄存器实现卷积编码。每输入1比特数据,将会依次输出数据A和B,输出的数据变为2比特,实现了1/2码率的卷积编码。
2.3 卷积编码模块设计
在了解了802.11a的卷积编码的原理之后,就可以着手来进行卷积编码器模块的设计了。
将输入输出以总线的方式聚合在一起,方便在Block Design里面连接。此处具体怎么操作,等实现完发射机部分再来讲解,先挖个坑。
该模块的输入是由上一级模块经过加扰之后的输出bit。在这个模块当中经过卷积编码,最终输出2bit的卷积编码数据。数据传输仍然使用前面提到的vaild-ready握手机制。首先将输入的bit移入到移位寄存器当中,根据生成多项式计算输出,之后对移位寄存器进行移位,不断重复上述操作。
assign conv_dout_rdy = conv_din_rdy ;
assign conv_en = conv_dout_rdy & conv_din_vld ;
always@(posedge clk or negedge rst_n ) begin
if(!rst_n) begin
shift_reg <= 0;
conv_dout <= 0;
conv_dout_vld <= 0;
end
else if( conv_en ) begin
conv_dout[0] <= shift_reg[5] + shift_reg[4] + shift_reg[2] + shift_reg[1] + conv_din;
conv_dout[1] <= shift_reg[5] + shift_reg[2] + shift_reg[1] + shift_reg[0] + conv_din;
conv_dout_vld <= 1;
shift_reg <= {shift_reg[4:0],conv_din}; //移位寄存器
end
else begin
conv_dout_vld <= 0;
end
end
2.4 Matlab设计与ModelSim仿真验证
Matlab有现成的函数可以实现卷积编码,代码如下:
%% 卷积编码
conv_in = scram_out0;
L = 7; %卷积编码约束长度
trellis = poly2trellis(L,[133,171]);
conv_out0 = convenc(conv_in,trellis);
测试数据按照前面文章的方法生成,如下:
test_data =
列 1 至 25
1 1 0 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1
列 26 至 50
0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 0 1 0
列 51 至 75
1 1 0 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 1
列 76 至 100
1 0 0 1 1 0 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 0 0 1
列 101 至 125
0 1 0 1 0 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 1 1 1
列 126 至 144
1 1 1 1 1 0 0 0 1 0 0 1 1 1 0 1 1 1 1
卷积编码后的输出如下:
conv_out0 =
列 1 至 25
1 1 0 1 0 0 0 1 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1 1 1
列 26 至 50
0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 1 1 0 0 1 1
列 51 至 75
1 0 0 0 1 0 1 1 1 0 1 1 0 1 1 0 0 0 1 1 0 0 1 0 0
列 76 至 100
0 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 0 0 1 0 0 0 1
列 101 至 125
0 1 1 1 0 1 1 1 0 1 1 0 1 1 0 0 0 1 0 1 0 0 0 0 1
列 126 至 150
0 0 0 0 1 0 0 0 1 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0
列 151 至 175
0 0 1 0 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0
列 176 至 200
0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 0 1
列 201 至 225
1 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 0 1
列 226 至 250
0 0 0 1 1 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 1 1 0 0
列 251 至 275
0 1 1 0 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1 0 1
列 276 至 288
1 1 1 0 0 0 1 1 1 0 0 1 1
按照如下连接进行仿真:
仿真截图如下:
FPGA仿真时卷积编码的输出如下:
FPGA_conv_dout =
列 1 至 25
1 1 0 1 0 0 0 1 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1 1 1
列 26 至 50
0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 1 1 0 0 1 1
列 51 至 75
1 0 0 0 1 0 1 1 1 0 1 1 0 1 1 0 0 0 1 1 0 0 1 0 0
列 76 至 100
0 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 0 0 1 0 0 0 1
列 101 至 125
0 1 1 1 0 1 1 1 0 1 1 0 1 1 0 0 0 1 0 1 0 0 0 0 1
列 126 至 150
0 0 0 0 1 0 0 0 1 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0
列 151 至 175
0 0 1 0 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0
列 176 至 200
0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 0 1
列 201 至 225
1 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 0 1
列 226 至 250
0 0 0 1 1 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 1 1 0 0
列 251 至 275
0 1 1 0 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1 0 1
列 276 至 288
1 1 1 0 0 0 1 1 1 0 0 1 1
为了验证是否和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);
check_conv输出全为1,表示Matlab结果和ModelSim仿真结果一致。
check_conv =
1×288 logical 数组
列 1 至 37
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
列 38 至 74
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
列 75 至 111
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
列 112 至 148
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
列 149 至 185
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
列 186 至 222
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
列 223 至 259
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
列 260 至 288
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
如果结果不对,可以先去检查前几步的输出是否正确,然后再去MoselSim中去抓信号DeBug。
原文连接(相关文章合集):OFDM 802.11a的xilinx FPGA实现