FPGA 版 FM 音源 (50) -- YMF297 (OPN3/OPL3) 測定 (15) -- EG クロック・プリスケーラ (2)

2016 月 11 月 18 日付けの記事 (→こちら) で述べた EG クロック・プリスケーラの動作は、よく考えればレート・マルチプライア (rate multiplier) そのものでした。
パイプライン方式で複数オペレータを実現する場合に各オペレータ固有の内部変数として 8 進レート・マルチプライアの状態を保持する必要があると思っていましたが、EG クロック・プリスケーラをレート・マルチプライアで実現すれば、ひとつのプリスケーラ・ハードウェアを全オペレータで共有でき、内部変数を持つ必要はなくなります。
FPGA / CPLD での RTL 記述、およびソフトウェアによる実現に適した計算方法を下に示します。 (対象はローレートのみ)

ローレート、つまり RATE <= 12 に対して fs クロックを分周する 12 ビットのバイナリ・カウンタが必要ですが、Rof の処理も含めるとさらに 2 ビット拡張して 14 ビット幅の演算が必要になります。
左の図で「COUNTER」と書いてあるのは、ソフトウェアでは普通の変数を順次インクリメントすることでカウンタを実現することを意味し、FPGA / CPLD の RTL 記述ではレジスタ変数に対して「+」演算子によりインクリメントすることでカウンタを実現することを意味しています。
実際に HDL で実現されるカウンタの内部回路の詳細については気にしないことにします。
左の図で「z-1」と表現してあるのは、1 サンプル前のカウンタの内容のコピーです。
ソフトウェア的には単なる変数、ハードウェア的には 14 ビット幅の D-FF です。
カウンタの現在値と、1 サンプル前の値 (の反転) とから、ビットごとの AND を取ってカウンタの各ビットの「立ち上がり」エッジを検出しています。
左の図の上半分で作成されバレル・シフタへ入力される信号のタイミング・チャートを下に示します。


それぞれ fs 1 周期分のパルス幅の、互いに重なり合わないパルス列となっています。
レートの値によりバレル・シフタで選び出した連続する 3 ビットの信号を Rof の値により合成して最終的に EG クロック・イネーブル信号を得ます。
下に例を示します。

上半分の青いトレースがバレル・シフタ出力の 3 つの波形です。
b0 が Rof == 0 に対する基本のレートで、Rof の値にかかわらず常に出力へミックスされます。
そして、Rof[0] == 1 なら b2 の信号がミックスされ、Rof[1] == 1 なら b1 の信号がミックスされます。
Rof のビットの並びと、クロック・プリスケーラの出力のビットの並びは互いに逆になっています。
上の図の下半分の赤色のトレースが Rof と波形の「ミックス」との対応を示しています。
パルス出力可能なポジションが全部で 8 個ある中で、

  • Rof == 0 では 4 パルス
  • Rof == 1 では 5 パルス
  • Rof == 2 では 6 パルス
  • Rof == 3 では 7 パルス

出力されています。
これは 2011 年 2 月 1 日付けの記事(→こちら) のレート・マルチプライア部の「CLK_EN」の真理値表と「位相」は異なりますが同じことを表しています。
前傾の計算方法を C プログラムで実現した例を下に示します。 (ローレートのみを考慮)

uint32_t psc_cnt = 0; // prescaler counter
uint32_t psc_z1  = 0; // 1 sample delay

// Calculate prescaler clock enable by rate multiplier
uint32_t calc_psc_en(int rate, int rof)
{
  uint32_t psc_en;

  rof = (((0x01 & rof) << 2) | (0x02 & rof) | 0x01);  
  psc_z1 = psc_cnt++;   // 1 sample delay and increment
  psc_en = (~psc_z1 & psc_cnt); // pos edge detect 
  return(0 != (rof & (psc_en >> (12 - rate))));
} // uint32_t calc_psc_en();

ビット逆順になっている「rof」のビットを「マスク・パターン」に変換している部分以外は、非常に簡単な処理で済んでいます。
次回は FPGA / CPLD で実現されるカウンタの中身までゲート・レベルで記述する場合について述べます。