理解:
本工程采用的是signal域 1/2卷积编码,data域 3/4编码,所以整体为多速率的卷积编码,可以有速率选择。
模块有二个时钟,一个是输入时钟,一个是输出时钟(按照所得速率不同而不同)。
signal域,输入时钟(20M),输出时钟(40M)。
data域, 输入时钟(60M),输出时钟(80M)。
模块思想是:首先生成1/2码率的卷积码,然后缓存起来,根据不同的速率要求,给予不同的输出方式。
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中数据的方向