OFDM802.11a的FPGA实现(五)卷积编码器的FPGA实现与验证(含verilog代码和matlab代码)

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)8g1=(171)8,码率为 1/2,其生成多项式用二进制表示为 g0 = 1011011,g1 = 1111001,该卷积码可以表示为(2,1,7),即每时钟周期输出两个比特数据,输入 1 个比特数据,约束长度为7。

802.11a中的卷积编码器

  每输入一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的卷积编码的原理之后,就可以着手来进行卷积编码器模块的设计了。

tx_conv_module

  将输入输出以总线的方式聚合在一起,方便在Block Design里面连接。此处具体怎么操作,等实现完发射机部分再来讲解,先挖个坑。
axi_tx_conv_module

  该模块的输入是由上一级模块经过加扰之后的输出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实现

最近更新

  1. TCP协议是安全的吗?

    2024-04-30 18:34:07       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-30 18:34:07       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-30 18:34:07       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-30 18:34:07       20 阅读

热门阅读

  1. Linux通过命令查看系统时间

    2024-04-30 18:34:07       8 阅读
  2. docker打包容器为镜像

    2024-04-30 18:34:07       8 阅读
  3. 深入了解数据结构中的查找算法

    2024-04-30 18:34:07       11 阅读
  4. socat用法记录

    2024-04-30 18:34:07       9 阅读
  5. vue知识

    vue知识

    2024-04-30 18:34:07      15 阅读
  6. SSH远程访问及控制

    2024-04-30 18:34:07       12 阅读
  7. vue3中引用组件提示has no default export问题解决

    2024-04-30 18:34:07       12 阅读
  8. 每日一练 | 华为认证真题练习Day225

    2024-04-30 18:34:07       12 阅读
  9. shell脚本使用小技巧-持续更新

    2024-04-30 18:34:07       13 阅读
  10. 多态案例(制作饮品)

    2024-04-30 18:34:07       12 阅读
  11. 动态规划与搜索算法

    2024-04-30 18:34:07       13 阅读
  12. Springboot项目中对Redis的使用

    2024-04-30 18:34:07       12 阅读