4.4.8 多码速卷积码硬件结构与实现

理解: 

 

本工程采用的是signal域 1/2卷积编码,data域 3/4编码,所以整体为多速率的卷积编码,可以有速率选择

模块有二个时钟,一个是输入时钟,一个是输出时钟(按照所得速率不同而不同)。

signal域,输入时钟(20M),输出时钟(40M)。

data域, 输入时钟(60M),输出时钟(80M)。

模块思想是:首先生成1/2码率的卷积码,然后缓存起来,根据不同的速率要求,给予不同的输出方式。

 1.Convolution Encoder模块

 

 

1、参考【GB 15629.1101-2006 第11部分 无线局域网媒体访问控制和物理层规范.pdf】,其中第6.3.5.5节有规定使用哪一种卷积编码器。(标准已经规定好了)

2、这个其实就是(2,1,7)卷积码,k0 = 1,n0 = 2,N = 7,该码的生成多项式为(171,133)。

为什么是171(8进制)?

 171(8进制) = 1111001(2进制)

其中输出数据B,分别是 0,1,2,3,6条线有效,多项式写法为 S=x^6 + x^3 +x^2+x^1+x^0(也就是1)。

按照有效为1,无效为0来说,此S可以表示为 1111001,也就是第0、1、2、3、6位的x有效。

如果还是不太清楚,可以去看看通信原理,M序列的产生以及多项式表达方式。

matlab多码速matlab实现:

%%-----------------------------------------------
%函数:1/2码速卷积编码,输入1比特,输出2比特
%%-----------------------------------------------
function CONVOLUTION = Convolution (input_data)
%生成多项式,S(x)=x^6+x^5+x^3+x^2+1;S(x)=x^6+x^3+x^2+x^1+1;
%g0 = [1 0 1 1 0 1 1];
%g1 = [1 1 1 1 0 0 1];
g0 = [0 0 0 0 0 0];
g1 = [0 0 0 0 0 0];
DataNum = length(input_data);
%分别对输入数据进行卷积后模二运算;
j=1;
%1/2码率输出,输出形式为A0B0A1B1A2B2......
for i=1:1:DataNum
    %OutA = mod((conv(input_data(1,i),g0)),2);
    %OutB = mod((conv(input_data(1,i),g1)),2);
    OutA = xor(g0(1,1),g0(1,2));
    OutA = xor(OutA,g0(1,4));
    OutA = xor(OutA,g0(1,5));
    OutA = xor(OutA,input_data(1,i));
    OutB = xor(g1(1,1),g1(1,4));
    OutB = xor(OutB,g1(1,5));
    OutB = xor(OutB,g1(1,6));
    OutB = xor(OutB,input_data(1,i));
    NewData2(1,j) = OutA;
    NewData2(1,j+1) = OutB;
    j=j+2;
    g0=circshift(g0,[0,-1]);
    g1=circshift(g1,[0,-1]);
    g0(1,6)=input_data(1,i);
    g1(1,6)=input_data(1,i);
end
CONVOLUTION = NewData2;
%%-----------------------------------------------
%删余函数
function [punc_patt, punc_patt_size] = get_punc_params(code_rate)
% 打孔参数
if strcmp(code_rate,'R3/4')         % 六个删除两个,由1/2得到3/4
   % R=3/4, Puncture pattern: [1 2 3 x x 6], x = punctured 
   punc_patt=[1 2 3 6];
   punc_patt_size = 6;
elseif strcmp(code_rate, 'R2/3')    % 四个删除一个,由1/2得到2/3
   % R=2/3, Puncture pattern: [1 2 3 x], x = punctured 
   punc_patt=[1 2 3]; 
   punc_patt_size = 4;
elseif strcmp(code_rate, 'R1/2')    % 标准编码器码流,不必打孔
   % R=1/2, Puncture pattern: [1 2 3 4 5 6], x = punctured 
   punc_patt=[1 2 3 4 5 6];
   punc_patt_size = 6;
else
   error('Undefined convolutional code rate');
end
%%------------------------------------------------
%发送模块编码主函数,1/2码率编码,3/4码率删余
function punctured_bits = tx_puncture(input_data, code_rate)
% 打孔,调整传输速率
 [ CONVOLUTION ]= Convolution (input_data)
[punc_patt, punc_patt_size] = get_punc_params(code_rate);

% Remainder bits are the bits in the end of the packet that are not integer multiple of the puncture window size
num_rem_bits = rem(length(CONVOLUTION), punc_patt_size);

puncture_table = reshape(CONVOLUTION(1:length(CONVOLUTION)-num_rem_bits), punc_patt_size, fix(length(CONVOLUTION)/punc_patt_size));
tx_table = puncture_table(punc_patt,:); % 只取不被打孔的行

% puncture the remainder bits
rem_bits = CONVOLUTION(length(CONVOLUTION)-num_rem_bits+1:length(CONVOLUTION));
rem_punc_patt = find(punc_patt<=num_rem_bits);
rem_punc_bits = rem_bits(rem_punc_patt)';

punctured_bits = [tx_table(:)' rem_punc_bits];
%%-----------------------------------------------


输入:001001

1/2码速:000011011100

3/4码速:00010110 

卷积编码模块代码:

module conv_encoder(clk,aclr,data_in,nd,data_out_v,rdy);

input aclr;
input clk;
input data_in;
input nd;
output [1:0] data_out_v;
output rdy;

reg [6:1] shift_reg;
reg [1:0] data_out_v;
reg rdy;

always @ ( negedge aclr or posedge clk )
  begin 
    if ( ! aclr )
	   begin
		  shift_reg <= 6'b000000;
		  data_out_v <= 0;
		  rdy <= 0 ;
		end

    else 
	   if ( nd )
		  begin
		    data_out_v[0] <= shift_reg[6] + shift_reg[5] + shift_reg[3] + shift_reg[2] + data_in;
			 data_out_v[1] <= shift_reg[6] + shift_reg[3] + shift_reg[2] + shift_reg[1] + data_in;
			 rdy<=1;
			 shift_reg <= { shift_reg [5:1], data_in };
		  end
		else
		  rdy <= 0;

  end



endmodule

 2.‘3/4’码率卷积的实现

(1)1/2卷积码放入缓存

(2)删余

(3)输出

module DATA_conv_encoder(DCONV_DIN,DCONV_ND,RATE_CON,DCONV_RST,DCONV_CLK_I,DCONV_CLK_O,DCONV_DOUT,DCONV_INDEX,DCONV_RDY);
    input DCONV_DIN;
    input DCONV_ND;
    input [3:0] RATE_CON;
    input DCONV_RST;
    input DCONV_CLK_I;
    input DCONV_CLK_O;
    output DCONV_DOUT;
    output [8:0] DCONV_INDEX;
    output DCONV_RDY;

	 wire RST;  
	 wire [1:0] DATA_OUT_V;
	 wire RDY;
	 reg BUF_RDY;
	 reg [1:0] i;
	 reg [2:0] j;
	 reg [1:0] Puncture_BUF_12;
	 reg [5:0] Puncture_BUF_34;
	 reg [3:0] Puncture_BUF_23;
	 reg [9:0] INDEX_TEMP;
	 reg DCONV_DOUT;
	 reg [8:0] DCONV_INDEX;
	 reg DCONV_RDY;

	 //assign RST = ~DCONV_RST;

	 conv_encoder conv_encoder1(
	             .data_in(DCONV_DIN),
				 .nd(DCONV_ND),
				 .clk(DCONV_CLK_I),
				 .aclr(DCONV_RST),
				 .data_out_v(DATA_OUT_V),
				 .rdy(RDY));	 

    always @ ( negedge DCONV_RST or posedge DCONV_CLK_I )	  // Put data into puncture_buffer.
	    begin
		    if ( ! DCONV_RST )
			    begin
				    Puncture_BUF_12 <= 0;//1/2速率_
				 	Puncture_BUF_34 <= 0;//3/4速率_
					Puncture_BUF_23 <= 0;//2/3速率_
					i <= 0;
             end

          else
				 begin
				  if ( RDY )
					case ( RATE_CON )
					  4'b1101,4'b0101,4'b1001:		// Rate is 1/2 .
					     begin
						    Puncture_BUF_12 <= DATA_OUT_V;
							BUF_RDY <= 1;
						  end

					  4'b1111,4'b0111,4'b1011,4'b0011:	 // Rate is 3/4 .
					     begin
						     case (i)
							    2'b00:
								    begin
										Puncture_BUF_34 [1:0] <= DATA_OUT_V;
										BUF_RDY <= 1;
										i <= i + 1 ;
									 end
								 2'b01:
									 begin
										Puncture_BUF_34 [3:2] <= DATA_OUT_V;
										BUF_RDY <= 1;
										i <= i + 1 ;
									 end
								 2'b10: 
									 begin
										Puncture_BUF_34 [5:4] <= DATA_OUT_V;
										BUF_RDY <= 1;
										i <= 2'b00 ;
									 end
								 default: 
									 begin
										Puncture_BUF_34 <= 0;
										BUF_RDY <= 0;	 
										i <= 0;
									 end
							       endcase
                    end 

					  4'b0001:		 // Rate is 2/3 .
					     begin
						     case ( i )
							    2'b00:
								   begin
									  Puncture_BUF_23 [1:0] <= DATA_OUT_V;
									  BUF_RDY <= 1;
									  i <= i + 1 ;		    
									end
                         2'b01:
								   begin
									  Puncture_BUF_23 [3:2] <= DATA_OUT_V;
									  BUF_RDY <= 1;
									  i <= 0 ;		    
									end
								 default:
								   begin
									  Puncture_BUF_23 <= 0;
									  BUF_RDY <= 0;
									  i <= 0 ;		    
									end
                       endcase
                    end				   
					endcase
            else
				  begin
					 BUF_RDY <= 0;
					 Puncture_BUF_12 <= 0;
				 	 Puncture_BUF_34 <= 0;
					 Puncture_BUF_23 <= 0;
					 i <= 0;
              end
				end					   
      end		  

   always @ ( negedge DCONV_RST or posedge DCONV_CLK_O ) 	// Puncture and output the data.
	   begin
		  if ( ! DCONV_RST )
		    begin
			   DCONV_DOUT <= 0 ;
				DCONV_RDY <= 0;
				j <= 3'b000;
			 end
			 
		  else  
		    if ( BUF_RDY ) 
			   case ( RATE_CON )
					  4'b1101,4'b0101,4'b1001:		// Rate is 1/2 .
					     begin
						    case ( j )
							   3'b000:
								   begin
								     DCONV_DOUT <= Puncture_BUF_12 [j] ;
									  DCONV_RDY <= 1;
									  j <= j +1 ;
									end
                                3'b001:
								   begin
								     DCONV_DOUT <= Puncture_BUF_12 [j] ;
									  DCONV_RDY <= 1;
									  j <= 3'b000 ;
									end
                              default:
								   begin
									  DCONV_DOUT <= 0 ;
									  DCONV_RDY <= 0;
									  j <= 3'b000 ;
                           end
							 endcase
 						  end

					  4'b1111,4'b0111,4'b1011,4'b0011:	 // Rate is 3/4 .
					     begin
						     case (j)
							    3'b000,3'b001,3'b010:
								    begin
										DCONV_DOUT <= Puncture_BUF_34 [j] ;
									   DCONV_RDY <= 1;
									   j <= j + 1 ;
									 end 
								 3'b011: 
									 begin
										DCONV_DOUT <= Puncture_BUF_34 [j+2] ;
									   DCONV_RDY <= 1;
									   j <= 3'b000 ;
									 end
								 default: 
									 begin
										DCONV_DOUT <= 0;
										DCONV_RDY <= 0;	 
										j <= 0;
									 end
							       endcase
                    end 

					  4'b0001:		 // Rate is 2/3 .
					     begin
						     case ( j )
							    3'b000,3'b001:
								   begin
									  DCONV_DOUT <= Puncture_BUF_23 [j] ;
									  DCONV_RDY <= 1;
									  j <= j + 1 ;		    
									end
                         3'b010:
								   begin
									  DCONV_DOUT <= Puncture_BUF_23 [j] ;
									  DCONV_RDY <= 1;
									  j <= 3'b000 ;		    
									end
								 default:
								   begin
									  DCONV_DOUT <= 0 ;
									  DCONV_RDY <= 0 ;
									  j <= 0 ;		    
									end
                       endcase 
						  end
						   default:
                                                 begin
                                                 
                                                     DCONV_INDEX <= 0 ;   
                                                 end
				endcase

         else
			  begin
			    DCONV_DOUT <= 0 ;
				 DCONV_RDY <= 0 ;
           end
		end			 

    always @ ( negedge DCONV_RST or posedge DCONV_CLK_O )  	 // Index output.
	    begin  
		   if ( ! DCONV_RST )
		      begin
			     DCONV_INDEX <= 0 ;
				  INDEX_TEMP <= 0;
			   end

			else
			 begin
			  if ( BUF_RDY )
			     case ( RATE_CON )
				    4'b1101,4'b1111:
					    begin
						   if( INDEX_TEMP < 47 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end
				    4'b0101,4'b0111:                
						 begin
						   if( INDEX_TEMP < 95 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end
				    4'b1001,4'b1011:                
						 begin
						   if( INDEX_TEMP < 191 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end                
				    4'b0001,4'b0011:                
						 begin
						   if( INDEX_TEMP < 287 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end
				  endcase
			  else
			    DCONV_INDEX <= 0 ;
          end
		 end						  


endmodule


 

 代码:

module DATA_conv_encoder(DCONV_DIN,DCONV_ND,RATE_CON,DCONV_RST,DCONV_CLK_I,
                            DCONV_CLK_O,DCONV_DOUT,DCONV_INDEX,DCONV_RDY);
    input DCONV_DIN;
    input DCONV_ND;
    input [3:0] RATE_CON;
    input DCONV_RST;
    input DCONV_CLK_I;
    input DCONV_CLK_O;
    output DCONV_DOUT;
    output [8:0] DCONV_INDEX;
    output DCONV_RDY;

	 wire RST;  
	 wire [1:0] DATA_OUT_V;
	 wire RDY;
	 reg BUF_RDY;
	 reg [1:0] i;
	 reg [2:0] j;
	 reg [1:0] Puncture_BUF_12;
	 reg [5:0] Puncture_BUF_34;
	 reg [3:0] Puncture_BUF_23;
	 reg [9:0] INDEX_TEMP;
	 reg DCONV_DOUT;
	 reg [8:0] DCONV_INDEX;
	 reg DCONV_RDY;

	 //assign RST = ~DCONV_RST;

	 conv_encoder conv_encoder1(
	             .data_in(DCONV_DIN),
				 .nd(DCONV_ND),
				 .clk(DCONV_CLK_I),
				 .aclr(DCONV_RST),
				 .data_out_v(DATA_OUT_V),
				 .rdy(RDY));	 

    always @ ( negedge DCONV_RST or posedge DCONV_CLK_I )	  // Put data into puncture_buffer.
	    begin
		    if ( ! DCONV_RST )
			    begin
				   Puncture_BUF_12 <= 0;
				 	Puncture_BUF_34 <= 0;
					Puncture_BUF_23 <= 0;
					i <= 0;
             end

          else
				 begin
				  if ( RDY )
					case ( RATE_CON )
					  4'b1101,4'b0101,4'b1001:		// Rate is 1/2 .
					     begin
						    Puncture_BUF_12 <= DATA_OUT_V;
							 BUF_RDY <= 1;
						  end

					  4'b1111,4'b0111,4'b1011,4'b0011:	 // Rate is 3/4 .
					     begin
						     case (i)
							    2'b00:
								    begin
										Puncture_BUF_34 [1:0] <= DATA_OUT_V;
										BUF_RDY <= 1;
										i <= i + 1 ;
									 end
								 2'b01:
									 begin
										Puncture_BUF_34 [3:2] <= DATA_OUT_V;
										BUF_RDY <= 1;
										i <= i + 1 ;
									 end
								 2'b10: 
									 begin
										Puncture_BUF_34 [5:4] <= DATA_OUT_V;
										BUF_RDY <= 1;
										i <= 2'b00 ;
									 end
								 default: 
									 begin
										Puncture_BUF_34 <= 0;
										BUF_RDY <= 0;	 
										i <= 0;
									 end
							       endcase
                    end 

					  4'b0001:		 // Rate is 2/3 .
					     begin
						     case ( i )
							    2'b00:
								   begin
									  Puncture_BUF_23 [1:0] <= DATA_OUT_V;
									  BUF_RDY <= 1;
									  i <= i + 1 ;		    
									end
                         2'b01:
								   begin
									  Puncture_BUF_23 [3:2] <= DATA_OUT_V;
									  BUF_RDY <= 1;
									  i <= 0 ;		    
									end
								 default:
								   begin
									  Puncture_BUF_23 <= 0;
									  BUF_RDY <= 0;
									  i <= 0 ;		    
									end
                       endcase
                    end				   
					endcase
            else
				  begin
					 BUF_RDY <= 0;
					 Puncture_BUF_12 <= 0;
				 	 Puncture_BUF_34 <= 0;
					 Puncture_BUF_23 <= 0;
					 i <= 0;
              end
				end					   
      end		  

   always @ ( negedge DCONV_RST or posedge DCONV_CLK_O ) 	// Puncture and output the data.
	   begin
		  if ( ! DCONV_RST )
		    begin
			   DCONV_DOUT <= 0 ;
				DCONV_RDY <= 0;
				j <= 3'b000;
			 end
			 
		  else  
		    if ( BUF_RDY ) 
			   case ( RATE_CON )
					  4'b1101,4'b0101,4'b1001:		// Rate is 1/2 .
					     begin
						    case ( j )
							   3'b000:
								   begin
								     DCONV_DOUT <= Puncture_BUF_12 [j] ;
									  DCONV_RDY <= 1;
									  j <= j +1 ;
									end
                        3'b001:
								   begin
								     DCONV_DOUT <= Puncture_BUF_12 [j] ;
									  DCONV_RDY <= 1;
									  j <= 3'b000 ;
									end
                        default:
								   begin
									  DCONV_DOUT <= 0 ;
									  DCONV_RDY <= 0;
									  j <= 3'b000 ;
                           end
							 endcase
 						  end

					  4'b1111,4'b0111,4'b1011,4'b0011:	 // Rate is 3/4 .
					     begin
						     case (j)
							    3'b000,3'b001,3'b010:
								    begin
										DCONV_DOUT <= Puncture_BUF_34 [j] ;
									   DCONV_RDY <= 1;
									   j <= j + 1 ;
									 end 
								 3'b011: 
									 begin
										DCONV_DOUT <= Puncture_BUF_34 [j+2] ;
									   DCONV_RDY <= 1;
									   j <= 3'b000 ;
									 end
								 default: 
									 begin
										DCONV_DOUT <= 0;
										DCONV_RDY <= 0;	 
										j <= 0;
									 end
							       endcase
                    end 

					  4'b0001:		 // Rate is 2/3 .
					     begin
						     case ( j )
							    3'b000,3'b001:
								   begin
									  DCONV_DOUT <= Puncture_BUF_23 [j] ;
									  DCONV_RDY <= 1;
									  j <= j + 1 ;		    
									end
                         3'b010:
								   begin
									  DCONV_DOUT <= Puncture_BUF_23 [j] ;
									  DCONV_RDY <= 1;
									  j <= 3'b000 ;		    
									end
								 default:
								   begin
									  DCONV_DOUT <= 0 ;
									  DCONV_RDY <= 0 ;
									  j <= 0 ;		    
									end
                       endcase 
						  end
				endcase

         else
			  begin
			    DCONV_DOUT <= 0 ;
				 DCONV_RDY <= 0 ;
           end
		end			 

    always @ ( negedge DCONV_RST or posedge DCONV_CLK_O )  	 // Index output.
	    begin  
		   if ( ! DCONV_RST )
		      begin
			     DCONV_INDEX <= 0 ;
				  INDEX_TEMP <= 0;
			   end

			else
			 begin
			  if ( BUF_RDY )
			     case ( RATE_CON )
				    4'b1101,4'b1111:
					    begin
						   if( INDEX_TEMP < 47 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end
				    4'b0101,4'b0111:                
						 begin
						   if( INDEX_TEMP < 95 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end
				    4'b1001,4'b1011:                
						 begin
						   if( INDEX_TEMP < 191 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end                
				    4'b0001,4'b0011:                
						 begin
						   if( INDEX_TEMP < 287 )
							  begin
							    INDEX_TEMP <= INDEX_TEMP + 1 ;
                         DCONV_INDEX <= INDEX_TEMP ;
							  end
							else
							  begin
							    INDEX_TEMP <= 0 ;
                         DCONV_INDEX <= INDEX_TEMP ; 
							  end
                   end
				  endcase
			  else
			    DCONV_INDEX <= 0 ;
          end
		 end						  


endmodule


注意问题:1、matlab中数据的方向

                 2、fpga中数据的方向 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值