Tech と Culture

テクノロジーとカルチャー

IDCTハードウェア概要

JPEG処理に用いられる二次元DCTは一次元DCT二回の演算に分割することができます。
その他にも演算負荷を軽くするためのアルゴリズムが大量に提案されてきています。

IJGのデコードソフトウェアdjpegは、実行時オプションでどのようなDCT演算を使うかを指定することができます。何も指定されない時は、LLMと呼ばれるアルゴリズムを使用するようです。この関数は、jidctint.cにあります。
まず、ハードウェア概要を考え、この関数をハードウェアアルゴリズムと同等のものに書き換え、コンパイルして実行し問題なく動画がXwindow上で再生されるかをチェックします。

DCTアルゴリズム詳細の説明は省きますが、ここで行われている演算は以下のようなものです。
dct2.png
なお入力行列Rは、各要素に対して逆量子化と言われる係数を掛けてから演算を開始する必要があります。最後に128を足しているのはレベルシフトと呼ばれるもので、JPEGエンコード時にこれだけのレベルシフトを行う規定があるため、それを元に戻しています。

ここで行列の左半分に対して右半分は符号を除けば対称となっています。
偶数列は符号を含めて対称。奇数列は符号のみ反転。
よって行列演算時の乗算は、うまく回路設計を行えば半分の4回で済みます。

DCT部分をどのようにハードウェア化するかはアルゴリズムのバリエーションと同様多数のバリエーションがありますが、今回は、DesignWave誌2008年1月号の方法をそのまま使用することとします。といってもただ単に行列演算をそのままハードウェア化しただけで、係数の対称性を利用して乗算器を半分にしただけです。多くの人が最初に考える素直な構造だと思われます。

最初にハードウェア全体の流れは以下のようになります。
dct4.png
AHBインターフェース越しに64個のデータを受け取ります。ここはダブルバッファにして、後段が読み出している最中に空いている側のメモリに書き込めるようにします。本来ならば、MCU単位でハフマンデコードは行われますので、MCU分のデータすべてを送り込んだ方が性能はかなり良いことが予想できます。しかし、最終的にハフマンデコーダをハードウェア化した時に、64画素分で後段に送るつもりなので、そのことを見越してこのサイズで設計してみます。
次にそれぞれの要素に対して逆量子化します。逆量子化のテーブルはAPBバス越しに設定できるようにします。すでにIOCTLでアプリケーションからレジスタ設定する要素技術は習得したので、それを使用して、ソフトウェアが逆量子化テーブルを解読した時点で書き込むようにコーディングします。
そして、そのまま1次元DCTを二回行います。それぞれ、Y,Cb,Cr用のメモリに結果を書き込みます。
次段のYCbCr-RGB変換モジュールが画面のサンプリングファクタにしたがって、そのメモリをリードして変換していきます。4:2:2なら、Cb,Crメモリは同じアドレスから2回続けて読むことになります。
処理単位が以前は画面の一行単位でハードウェアにデータ転送していましたが、今回からはMCU単位となります。よって、YCbCr-RGB変換モジュールのアドレス生成ブロックも作り直さねばなりません。画面サイズ等は以前は決めうちでしたが、今回からソフトウェアが画面サイズデータ等を取得したときにIOCTL等を使って設定するようにコーディングします。これによって異なる画面サイズがソフトウェアに入力されても常に動画がデコードされてフレームバッファに表示できるようになります。

このハードウェア構造は高速ですが、面積が大きくなることが予想されます。とりあえず、一次元DCT部分を設計してみて、あまりに大きくてFPGAに入らないようでしたら、その時対策を考えます。一次元DCTのハードウェアを一つにして、ループさせる方法等、性能は劣化しても面積を減らす方法はいろいろありそうです。

一次元DCTのハードウェア詳細は次のようなものです。
dct3.png

左側から逆量子化した行列要素がバーストでどんどん入力されてきます。それぞれの値に対して8個の行列要素掛け算が行われますが、係数行列の対称性を利用して乗算器は4個にしてあります。その演算を8回繰り返すと出力行列の一行分のデータ演算が終了します。途中には丸めや、係数演算後の符号コントロール等が入ります。8個の計算結果もバーストで出力します。
符号をどのタイミングで変更するかや、最後の計算結果をいつとりこんで、いつシフトさせるか等はコントローラのFSMが指示を出します。
またFSMは後段のready信号と前段に対するrequest信号出力やそれに対する応答を受けていつFSMを動作させるかを決定します。
二回目のDCTには、最後の丸めでレンジリミットが必要となります。またレベルシフトの128加算も必要となります。それに対して、一回目のDCTはバースト入力に対する逆量子化乗算が必要となります。