OFDM802.11a的FPGA实现(六)删余模块的FPGA实现(含verilog代码和matla)

1.前言

  在前面执行了卷积编码之后,得到了一个1/2编码速率的卷积编码,在实际的使用当中,802.11a支持不同的编码速率,比如2/3编码,3/4编码,为了能够得到对应的编码速率,需要将卷积编码之后的结构进行删除其中的一些bit。


  不得不先吐槽下《基于XILINX FPGA的OFDM通信系统基带设计》这本书里面的设计思路,一旦输入数据和输出数据速率不一样他就跨时钟。记得作者大二才学FPGA的时候,接触一位大佬就说过,always里面最好都是一种时钟,除非是真的避免不了再考虑。我愿称这本书为始作俑者,网上大部分教程都是按照他的思路来进行设计。

2. 删余的原理

2.1 删余的作用

  无线通信基带信号处理中,为了提高传输效率,在卷积编码后一般要进行删余(puncture)操作,即周期性的删除一些相对不重要的数据比特,引人了删余操作的卷积编码也称作删余卷积码。在编码时进行了删余操作后,需要在译码时进行depuncture,即在译码之前将删余比特位置加以填充。在IEEE 802.11a标准中推荐使用viterbi算法解密。删余的过程如下所示:

2.2 3/4编码速率的删余过程

2.3 2/3编码速率的删余过程

3.删余模块实现

3.1 模块接口

  该模块如下所示:

  数据传输和控制依然采用vaild-ready握手机制,串行输入,删余后串行输出。Rate_Con[3:0]是调制方式和码率控制信号。如下三个表所示,SymbolLen_Con[1:0]是输入调制方式和编码效率一个OFDM符号的长度,如下面第二个表的第4列所示。

表1

表2

表3

3.2 FPGA实现(verilog代码)

  由于卷积编码模块输出的是2bit并行的数据,先要使用前面的并串转换模块,再与删余模块连接进行删余操作。连接方式如下所示:

  1/2直接输出即可,以模2计数器进行循环,输出标号为第0,1个;2/3需要循环删除第4个数据,以模4计数器进行循环输出标号为0,1,2;3/4码率的需要循环删除第4、5个数据,以模6计数器进行循环,输出标号为0,1,2,5。代码如下:

assign		punt_dout_rdy = punt_din_rdy;
assign		punt_en =  punt_dout_rdy & punt_din_vld	;

counter_in #(.CNT_NUM(3'd6),
		.ADD(1'b1))
u_counter(
.clk		(clk				),	
.rst_n		(rst_n				),
.En_cnt		(punt_en | cnt_last	), 
.cnt_din	(cnt_max			),     
.cnt		(cnt				),	
.cnt_last	(cnt_last			)
);

//output count max 
always@( posedge clk or negedge rst_n ) begin    
    if(!rst_n) 
        cnt_max <= 3'd1;
    else  begin 
        case ( Rate_Con )
			4'b1101,4'b0101,4'b1001: begin   //rate 1/2
				cnt_max <= 3'd1;
			end
			4'b1111,4'b0111,4'b1011,4'b0011: begin //rate 3/4
				cnt_max <= 3'd5;
			end
			4'b0001: begin		//rate 2/3
				cnt_max <= 3'd3;
			end 
			default: cnt_max <= cnt_max;
        endcase
    end  
end 

always@( posedge clk or negedge rst_n ) begin   
	if(!rst_n)begin
		punt_dout <= 1'b0;
		punt_dout_vld <= 1'b0;
	end
	else if(punt_en)begin
		case (cnt)
			0,1,2,5 : begin 
				punt_dout <= punt_din;
				punt_dout_vld <= 1'b1;
				end
			3,4		: begin 
				punt_dout <= 1'b0;
				punt_dout_vld <= 1'b0;
				end
			default : begin 
				punt_dout <= punt_dout;
				punt_dout_vld <= punt_dout_vld;
				end
		endcase
	end
	else if(punt_dout_vld & punt_din_rdy)
		punt_dout_vld <= 1'b0;
end

   //SymbolLen_Con
always@(posedge clk or negedge rst_n ) begin
    if(!rst_n)
        SymbolLen_Con <= 0;   
    else begin 
        case ( Rate_Con )
		4'b1101,4'b1111: begin
            SymbolLen_Con <= 2'b00;  //Len==48
        end
        4'b0101,4'b0111: begin
            SymbolLen_Con <= 2'b01;   //Len ==96
        end
        4'b1001,4'b1011: begin
            SymbolLen_Con <= 2'b10;  //Len ==192
        end 
        4'b0001,4'b0011: begin
            SymbolLen_Con <= 2'b11;  //Len ==288  
        end
        default:SymbolLen_Con <= 2'b00;
        endcase
    end  
end

3.3Matlab仿真

%% 删余
switch(code_rate)   %卷积编码速率控制
    case 12  
        conv_out = conv_in;%做卷积编码
    case 8  
        puncpat = [1;1;1;0];    %打孔方式
        trellis = poly2trellis(L,[133,171]);
        conv_out = convenc(conv_in,trellis,puncpat);
    case 6
        puncpat = [1;1;1;1];
        trellis = poly2trellis(L,[133,171]);
        conv_out = convenc(conv_in,trellis,puncpat);
    case 9
        puncpat = [1;1;1;0;0;1];
        trellis = poly2trellis(L,[133, 171]);
        conv_out = convenc(conv_in,trellis,puncpat);
    otherwise
        disp('code_rate_error');
end

  测试数据如下:

test_data =

  列 1 至 25

     0     1     0     0     0     0     0     1     1     0     0     0     0     1     0     1     0     1     1     0     0     0     1     1     1

  列 26 至 50

     1     1     0     0     1     0     0     1     1     1     1     1     1     1     0     1     0     1     1     0     1     1     0     1     0

  列 51 至 75

     0     0     1     0     1     1     1     1     0     1     0     1     1     0     1     1     1     0     0     1     0     0     0     0     1

  列 76 至 100

     0     0     1     0     0     0     0     1     0     1     0     1     0     0     1     0     1     1     1     1     1     0     1     0     1

  列 101 至 125

     1     1     0     1     0     1     1     0     1     1     1     1     0     1     0     0     1     1     1     0     1     0     1     0     0

  列 126 至 144

     0     0     1     0     0     0     0     1     0     0     1     1     0     0     0     1     0     0     1

  16-QAM调制,3/4码率,编码删余后的数据如下:

conv_out =

  列 1 至 25

     0     0     0     1     0     1     0     1     1     0     0     0     0     0     0     1     0     0     0     0     0     0     1     1     1

  列 26 至 50

     1     1     0     1     1     0     1     1     1     0     0     1     1     1     0     0     0     1     0     1     1     1     0     0     0

  列 51 至 75

     0     0     1     0     0     0     1     1     0     1     0     1     1     1     0     1     1     1     1     1     1     1     0     0     1

  列 76 至 100

     0     1     0     0     0     0     0     0     0     0     1     0     1     1     0     1     1     0     1     0     0     1     1     1     1

  列 101 至 125

     0     0     1     1     0     1     0     0     0     1     1     1     0     1     1     1     1     1     0     1     0     0     0     1     0

  列 126 至 150

     1     0     1     0     1     0     0     1     0     1     1     1     0     0     0     0     1     1     0     1     0     1     0     0     0

  列 151 至 175

     0     0     1     1     1     1     0     1     0     1     1     0     0     0     1     0     0     0     1     1     0     1     1     1     1

  列 176 至 192

     1     1     1     1     0     0     0     0     1     1     1     0     1     0     0     0     0

3.4 ModelSim仿真

  仿真截图如下:


  16-QAM调制,3/4码率,FPGA实现编码删余后的数据如下:

FPGA_punt_dout =

  列 1 至 25

     0     0     0     1     0     1     0     1     1     0     0     0     0     0     0     1     0     0     0     0     0     0     1     1     1

  列 26 至 50

     1     1     0     1     1     0     1     1     1     0     0     1     1     1     0     0     0     1     0     1     1     1     0     0     0

  列 51 至 75

     0     0     1     0     0     0     1     1     0     1     0     1     1     1     0     1     1     1     1     1     1     1     0     0     1

  列 76 至 100

     0     1     0     0     0     0     0     0     0     0     1     0     1     1     0     1     1     0     1     0     0     1     1     1     1

  列 101 至 125

     0     0     1     1     0     1     0     0     0     1     1     1     0     1     1     1     1     1     0     1     0     0     0     1     0

  列 126 至 150

     1     0     1     0     1     0     0     1     0     1     1     1     0     0     0     0     1     1     0     1     0     1     0     0     0

  列 151 至 175

     0     0     1     1     1     1     0     1     0     1     1     0     0     0     1     0     0     0     1     1     0     1     1     1     1

  列 176 至 192

     1     1     1     1     0     0     0     0     1     1     1     0     1     0     0     0     0

  和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);

  验证结果如下:

check_punt =

  1×192 logical 数组

  列 1 至 38

   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

  列 39 至 76

   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

  列 77 至 114

   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

  列 115 至 152

   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

  列 153 至 190

   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

  列 191 至 192

   1   1

  输出显示192个逻辑‘1’表示FPGA得到的结果与Matlab仿真结果完全一致,经过测试其他7种调制和编码方式结果都是正确的,这里就不在进行赘述了。

4总结

  结合上一节的卷积编码器,本模块用FPGA实现了1/2,3/4,2/3编码效率的卷积编码器的删余操作,需要回顾前面知识请点击链接:原文连接(相关文章合集)OFDM 802.11a的xilinx FPGA实现

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-26 20:38:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-26 20:38:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-26 20:38:02       87 阅读
  4. Python语言-面向对象

    2024-04-26 20:38:02       96 阅读

热门阅读

  1. SpringBoot Filter过滤器的使用篇

    2024-04-26 20:38:02       39 阅读
  2. js转换成Number类型的方法与规则

    2024-04-26 20:38:02       33 阅读
  3. Kafka 监控之分层存储监控和 KRaft 监控指标

    2024-04-26 20:38:02       27 阅读
  4. 3个要点全面提升SQL数据安全

    2024-04-26 20:38:02       34 阅读
  5. Linux 三剑客之AWK

    2024-04-26 20:38:02       31 阅读
  6. 常用路由交换协议

    2024-04-26 20:38:02       33 阅读
  7. MYSQL 8.0的Linux - Generic版本安装

    2024-04-26 20:38:02       37 阅读