1. 程式人生 > >4.3.2 通道編碼 ——卷積碼

4.3.2 通道編碼 ——卷積碼

4.3.2 通道編碼 ——卷積碼  

 通道編碼是為了保證通訊系統的傳輸可靠性,克服通道中的噪聲和干擾而專門設計的一類抗干擾技術和方法。它根據一定的監督規律在待發送的資訊碼元中(人為的)加入一些必要的監督碼元,在接收端利用這些監督碼元與資訊碼元之間的監督規律,發現和糾正差錯,以提高資訊碼元傳輸的可靠性。

 

        其中,稱待發送的碼元為資訊碼元,人為加入的多餘碼元為監督(或校驗)碼元。通道編碼的目的,是以最少的監督碼元為代價,換取最大程度的可靠性提高。

 

常用的通道編碼有線性分組碼、迴圈碼、BCH碼、RS碼和卷積碼等。

 


        在IEEE 802.11a中,主要使用了卷積編碼,卷積碼也是分組的,但它的監督碼元不僅與本組的資訊元有關,而且還與前若干組的資訊元有關。這種碼的糾錯能力強,不僅可糾正隨機差錯,而且可糾正突發差錯。卷積碼根據需要,有不同的結構及相應的糾錯能力,但其編碼規律都是相同的。

 

        下圖以一個約束長度為4、位元速率 R=1/3 的卷積編碼器為例。

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 


 

        IEEE 802.11a協議中規定卷積編碼使用的生成多項式 g0 = 133(8進位制)和 g1 = 171(8進位制),位元速率為1/2。

 

        注: Signal 域的卷積編碼是1/2速率,而Data 域的卷積編碼可以根據不同的速率需要進行刪餘,我們選用的是3/4速率。

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 

 

        摘錄《GB 15629.1101-2006》,關於卷積編碼器的部分:

 

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

        


也許這樣說太空泛了,照例附上程式碼就清楚到底怎麼卷積編碼的了。

 
 

`timescale 1ns / 10ps


//////////////////////////////////////////////////////////////////////////////////
// Create Date: 15:37:29 10/08/2014
// Design Name: convolution
// Module Name: conv_encoder
// Project Name: OFDM base on Xilinx KC705
// Description: OFDM 卷積模組,符合IEEE 802.11a 標準,1/2位元速率卷積輸出。
// 生成多項式為g0 = 133[8],g1 = 171[8],位元速率為1/2。[8]:8進位制
// Revision: 1.0
// Copyright: 《基於xlinx FPGA的OFDM通訊系統基帶設計》
//////////////////////////////////////////////////////////////////////////////////

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

input aclr; // 非同步復位,低電平有效
input clk; // 60Mhz
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 <= 2'b00;
rdy <= 1'b0 ;
end

else
if ( nd )
begin
data_out_v[0] <= shift_reg[6] + shift_reg[5] + shift_reg[3] + shift_reg[2] + data_in; //資料A多項式:S(x) = x^6 + x^5 + x^3 + x^2 + 1
data_out_v[1] <= shift_reg[6] + shift_reg[3] + shift_reg[2] + shift_reg[1] + data_in; //資料B多項式:S(x) = x^6 + x^3 + x^2 + x + 1
rdy <= 1'b1;
shift_reg <= { shift_reg [5:1], data_in };
end
else
rdy <= 1'b0;

end

endmodule

 

1/2位元速率的卷積編碼模組,重要的部分是生成表示式:

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 

 


        來說說刪餘部分,無線通訊基帶訊號處理中,為了提高傳輸效率,在卷積編碼後一般要進行刪餘(puncture)操作,即週期性的刪除一些相對不重要的資料位元,引入了刪餘操作的卷積編碼也稱做刪餘卷積碼。

 

        在編碼進行了刪餘操作後,需要在譯碼時進行depuncture,即在譯碼之前刪餘位元位置加以填充。

 

刪餘編碼規則:

 

R = 3/4

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 

R = 2/3

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 


 

本工程採用的是signal域 1/2卷積編碼,data域 3/4編碼,所以整體為多速率的卷積編碼,可以有速率選擇。

 

模組結構框圖:

4.3.2 通道編碼 ——卷積碼 - fantasy - 悠然見南山

 

 

模組有二個時鐘,一個是輸入時鐘,一個是輸出時鐘(按照所得速率不同而不同)。

signal域,輸入時鐘(20M),輸出時鐘(40M)。

data域, 輸入時鐘(60M),輸出時鐘(80M)。

 

模組思想是:首先生成1/2位元速率的卷積碼,然後快取起來,根據不同的速率要求,給予不同的輸出方式。

 

verilog程式碼:

 
 

`timescale 1ns / 10ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 15:57:29 10/08/2014
// Design Name: convolution
// Module Name: data_conv_encoder
// Project Name: OFDM base on Xilinx KC705
// Description: OFDM 卷積模組,符合IEEE 802.11a 標準,多位元速率卷積輸出。本工程輸出是1/2和3/4位元速率。
// 3/4位元速率由1/2位元速率刪餘處理得到。
// Revision: 1.0
// Copyright: 《基於xlinx FPGA的OFDM通訊系統基帶設計》
//////////////////////////////////////////////////////////////////////////////////

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; // 由Signal域得到的編碼速率,決定截斷方式
input DCONV_RST; // 復位訊號,低電平有效
input DCONV_CLK_I; // 卷積碼輸入時鐘(60Mhz)
input DCONV_CLK_O; // 卷積碼輸出時鐘,根據截斷方式不同,分別為輸入時鐘的3/4倍或2/3倍。(這裡是80Mhz,資料的4/3倍)
output DCONV_DOUT; // 輸出資料
output [8:0] DCONV_INDEX; // 輸出資料計數
output DCONV_RDY; // 輸出資料有效訊號

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;

conv_encoder conv_base(
.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 ) // 將產生的卷積資料存入buff中
begin
if(!DCONV_RST)
begin
Puncture_BUF_12 <= 2'd0;
Puncture_BUF_34 <= 6'd0;
Puncture_BUF_23 <= 4'd0;
i <= 2'd0;
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 + 2'd1;
end
2'b01:
begin
Puncture_BUF_34 [3:2] <= DATA_OUT_V;
BUF_RDY <= 1;
i <= i + 2'd1;
end
2'b10:
begin
Puncture_BUF_34 [5:4] <= DATA_OUT_V;
BUF_RDY <= 1;
i <= 2'd0;
end
default:
begin
Puncture_BUF_34 <= 6'd0;
BUF_RDY <= 0;
i <= 2'd0;
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 + 2'd1;
end
2'b01:
begin
Puncture_BUF_23 [3:2] <= DATA_OUT_V;
BUF_RDY <= 1;
i <= 2'd0 ;
end
default:
begin
Puncture_BUF_23 <= 4'd0;
BUF_RDY <= 0;
i <= 2'd0 ;
end
endcase
end
endcase
else
begin
BUF_RDY <= 0;
Puncture_BUF_12 <= 2'd0;
Puncture_BUF_34 <= 6'd0;
Puncture_BUF_23 <= 4'd0;
i <= 2'd0;
end
end
end

always @ ( negedge DCONV_RST or posedge DCONV_CLK_O ) // 刪餘,即從buff中取對應的資料輸出
begin
if(!DCONV_RST)
begin
DCONV_DOUT <= 0 ;
DCONV_RDY <= 0;
j <= 3'b000;
end

else
begin
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
end

always @ ( negedge DCONV_RST or posedge DCONV_CLK_O ) // 有效資料的個數
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