MATLABでの畳み込み符号器、ターボ符号器の表現方法

この記事のまとめ:
  • 畳み込み符号器として、RSC符号器そのものや、畳み込み符号器の生成多項式の表現方法についてまとめています。
  • MATLABでの畳み込み符号化の方法についてまとめています。
  • RSC符号器として、LTEで使われているターボ符号器について簡単に説明しています。
背景

MATLABを使って久しぶりに畳み込み符号器 (Convolutional Encoder) を使おうと思ったら、生成多項式の表現方法を忘れてしまっていたので、poly2trellisの使い方も合わせてまとめてみました。

基本的にはMATLABのドキュメンテーションの“誤りの検出と訂正”のページに非常に分かりやすく説明されていますが、使い方について説明がないところもあるのでそのあたりを中心にまとめています。

畳み込み符号器の種類

畳み込み符号器には下記の2つの符号器があります。

  • NSC (Non Systematic Convolutional) 符号器
  • RSC (Recursive Systematic Convolutional) 符号器

本記事ではRSC符号器について主に見ていきます。

RSC符号器

RSC符号器は、例えば次のような構成で、systematicと呼ばれる第一出力 は入力 と同じ系列です。第二出力 はフィードバック系とフィードフォワード系を持つ符号器です。

RSC encoder example

RSC符号器は次の3つのパラメーターで表現することができます。

  • 拘束長: 出力シンボルが影響される直近の情報シンボル数
  • 生成多項式: フィードバック系とフィードフォワード系構成、MATLABでは8進数行列で表す
  • 符号化率: 入力シンボルに対する出力シンボルの比

上の例では拘束長が4で、生成多項式行列が [13 15] で、符号化率 の符号器となります。

生成多項式行列

上のRSC符号器の生成多項式行列がなぜ [13 15] なのかということについて、表現方法を覚えていないと少し紛らわしいのでどのように理解をすればよいかを見てみます。

はじめに次のようなフィードバック系とフィードフォワード系すべてが接続された系を考えます。

Fully connected RSC encoder with parameters

それぞれのパラメーター について並べて、出力の有無を2進数で表現し、それらを8進数に変換することを考えます。最初のRSC符号器の例で考えると次のように表すことができます。

そして、MATLABで用いる生成多項式行列表現は一般的にはフィードバック系、フィードフォワード系の順で並べるので [13 15] となるわけです。

MATLABでの畳み込み符号化方法

続いてMATLABで畳み込み符号化を行う方法を見てみます。

主に使う関数、もしくはシステムオブジェクトは次の2つです。

なお、利用にはどちらもCommunications System Toolboxが必要です。

poly2trellis関数

上記の畳み込み符号化を行ってくれる関数やシステムオブジェクトで畳み込み符号器を表現する際、引数として生成多項式行列ではなく、MATLABトレリス構造体を用います。生成多項式行列をMATLABトレリス構造体に変換してくれるのがpoly2trellis関数です。

poly2trellis関数の公式ドキュメントを見るとわかりますが、RSC符号器を作る場合には、ConstraintLengthCodeGeneratorFeedbackConnectionの引数が必要です。

最初のRSC符号器のトレリス構造体を生成する場合には次のように表現します。

trellis = poly2trellis(4, [13 15], 13)

ここからはこのpoly2trellis関数でやりがちな間違いについて見てみます。

それでは誤って次のようにFeedbackConnection引数を忘れると何を示すでしょうか。

trellis = poly2trellis(4, [13 15])

FeedbackConnection引数を忘れるとNSC符号器となってしまいます。つまり、次のようなNSC符号器です。

NSC encoder example

次に、FeedbackConnection引数を”15”としてしまった場合どうなるでしょうか。

trellis = poly2trellis(4, [13 15], 15)

この場合には、次のような符号器となり、”15”を表す接続がフィードバック系として扱われるのですが、第二出力がsystematicになることに注意が必要です。

Opposite RSC encoder

convenc関数とcomm.ConvolutionalEncoderオブジェクト

convenc関数とcomm.ConvolutionalEncoderオブジェクトの違いは、設定できるオプションの違いです。

これらの違いは関数とオブジェクトの違いそのものといって過言ではないのですが、符号器内の状態維持が必要のない符号化であればconvenc関数で実行可能で、それ以外はcomm.ConvolutionalEncoderオブジェクトを使う、といった使い分けです。

オプションの違いは次の通りです。

オプション convenc ConvolutionalEncoder
パンクチャリング
初期状態入力
終端方法 ×
リセット入力 ×
出力リセットの遅延 ×
最終状態出力 ×

また、これらで生成したデータ系列は、出力系ごとに出力されるわけではなく、 といったように入力シンボルごとの出力系の結果が並んで出力されます。

出力系ごとに分離したい場合は次のように実行すればよいです。

u = randi([0 1], 10, 1);
trellis = poly2trellis(4, [13 15], 13);
c = convenc(u, trellis);
 
systematic = c(1:2:end);
convdata = c(2:2:end);
ターボ符号器

最後に、RSC符号器として最も代表的な例として、ターボ符号器について簡単に見てみます。

そもそもRSC符号器はターボ符号器 (Trubo Encoder) で使われたことで有名になっ多といわれています。ターボ符号器では、RSC符号器を使うことでNSC符号器に比べて高いパフォーマンスが得られることが一般的に知られています (Wikipediaより)。

実は、最初に挙げたRSC符号器の例は、LTEで使われているターボ符号器として採用されているRSC符号器と同じ構成のものです。

LTEで使われているターボ符号器の構成は次の通りです。

Turbo encoder

二つのRSC符号器があり、上段のRSC符号器は何の変哲もないRSC符号器ですが、下段のRSC符号器には、インターリーブした入力信号を入力として使います。また、下段のsystematicは上段のsystematicをインターリーブしたもののため、出力としては基本的には使いません。

その他、LTEでは終端処理についての規定がありますので、詳細は3GPP TS36.212 5.1.3.2.2 Trellis termination for turbo encoder をご参照ください。

MATLABでターボ符号器化を行う場合、comm.TurboEncoderシステムオブジェクトを使うと便利です。

最後にcomm.TurboEncoderを使ってターボ符号化を行う場合と、comm.ConvolutionalEncoderを使ったターボ符号化を行う手順を載せておきます。

%% Parameter settings
L = 10; % data length
 
trellis = poly2trellis(4, [13 15], 13):
state = 1; % state for the interleaver
interleaver = randintrlv(1:L, state);
 
%% Data generation
u = randi([0 1], L, 1); 
 
%% Use comm.TurboEncoder
hTurboEnc = comm.TurboEncoder( ...
    'TrellisStructure', trellis, ...
    'InterleaverIndicesSource','Input port');
 
ct = step(hTurboEnc, u, interleaver);
numTails = log2(trellis.numStates)*2;
ct_sys = ct(1:3:L*3);
ct_sec = [ct(2:3:L*3); ct(L*3+1:L*3+numTails)];
ct_thd = [ct(3:3:L*3); ct(L*3+numTails+1:end)];
 
%% Use comm.ConvolutionalEncoder
hConvEnc = comm.ConvolutionalEncoder( ...
    'TrellisStructure', trellis, ...
    'TerminationMethod', 'Terminated');
 
cc = step(hConvEnc, u);
cci = step(hConvEnc, u(interleaver));
cc_sys = cc(1:2:L*2); % same as 'cc_sys'
cc_sec = [cc(2:2:L*2); cc(L*2+1:end)]; % same as 'cc_sec'
cc_thd = [cci(2:2:L*2); cci(L*2+1:end)]; % same as 'cc_thd'

気が向いたら畳み込み復号のアルゴリズムの記事も書こうと思います。


今回は以上です。 最後まで読んでいただき、ありがとうございます。
関連記事



コメント

このブログの人気の投稿

LinuxでのnVidia GPUのオーバークロック・電力チューニング方法