FPGA 版 FM 音源 (29) -- 49 kHz → 44.1 kHz サンプリング・レート・コンバータ (2)

サンプリング周波数を 49.5158 kHz から 44.1 kHz へ変換する回路は、次の 2 点、

  • 信号レベルの約 1 dB の低下 (およびそれにともなう S/N 比の悪化)
  • 加減算回路のビット幅が 6 ビット増加 (16 ビット幅から 22 ビット幅へ)

を許容できれば、44.1 kHz レートでの乗算回路なしで実現できます。
4 月 10 日付けの記事では、SRC クロック (2.8224 MHz) のレートで、

0.0=0/57, 1/57, ... , 56/57, 57/57=1.0

の係数を発生させていき、出力サンプリング周波数 44.1 kHz のレートでの乗算をともなう線形補間演算によって出力サンプルを計算していました。
これを、49.5158 kHz レートでの新しい入力サンプルが到着した時点で、最初に (入力サンプル × (1/57)) を計算しておき、順次それを足し合わせていけば、出力サンプリング・レートでの乗算は必要なくなります。
ただし、この方法でも、「初回」の 1/57 の乗算は必要になります。
分母に「57」があるのが問題なので、全体に「57」をかけ、

0 倍、1 倍、2 倍、 ... 、56 倍、57 倍

を順次計算する方法にすれば、「累加演算」だけで求めることができます。
しかし、そのままではデータの数値が 57 倍になっているので、何らかの数で割って、もとの数値のレンジに戻してやらなければなりません。
本当の「割り算」ではなく、6 ビット右シフトで 1/64 にすれば、データの数値としては元の値の 57/64 になるので、元の値の絶対値を超えません。
その数値の減少幅は、

20 × log10(57/64) = 20 × -0.0503 = -1.006 [dB]

となります。
累加演算の過程で、もとの数値の 57 倍まで達するので、その値を保持するためには、加減算回路およびレジスタのビット幅を 6 ビット増やす必要があります。
入出力データが 16 ビットなら、回路に必要なビット幅は 22 ビットとなります。
この方式での回路を下に示します。

49.5158 kHz のレートで到着する入力サンプルを保持しておくレジスタが「REG0」と「REG1」です。
「最新」のサンプルは REG0 に保持され、これを「NEW」と呼ぶことにします。
最新からひとつ前のサンプルは REG1 に保持され、これを「OLD」と呼ぶことにします。
新しいサンプルが到着するたびに、それまでの「OLD」サンプルは捨てられ、「NEW」だったサンプルは REG1 に送られて「OLD」として扱われ、最新サンプルは REG0 に入ります。
アキュムレータ・レジスタ「ACC0」は NEW 側のサンプルを順次加算し、「ACC1」は OLD 側を順次減算していきます。
57 倍にアップ・サンプルされたサンプル点をインデクス「i」の値 0 から 56 で区別し、i が 56 → 0 への変化のタイミングで入力サンプルが更新されるものとします。
アキュムレータ・レジスタの入力側のマルチプレクサは、i = 0 〜 55 の間は加算器 (減算器) 出力側を選択してアキュムレーション・ループを構成し、i = 56 のタイミングでは、「初期値」をロードするように作用します。
ACC0 の初期値は「0」、ACC1 の初期値は (57*OLD) となります。
インデクス i と ACC0、ACC1 の内容との関係の表を下に示します。

 i  ACC0  ACC1 (ACC0 + ACC1)
 0   0 57*OLD 57*OLD
 1   NEW 56*OLD 56*OLD +  NEW
 2  2*NEW 55*OLD 55*OLD +  2*NEW
 3  3*NEW 54*OLD 54*OLD +  3*NEW
.
.
.
.
.
.
.
.
.
.
.
.
54 54*NEW  3*OLD  3*OLD + 54*NEW
55 55*NEW  2*OLD  2*OLD + 55*NEW
56 56*NEW   OLD    OLD + 56*NEW

44.1 kHz の出力サンプリング周波数のタイミングで ACC0 と ACC1 を読み込んで加算し、6 ビット右シフトにより数値を 16 ビット幅に納めてシリアル DAC インターフェース回路に渡します。