Posts Tagged with "FPGA"

既に発行済みのブログであっても適宜修正・追加することがあります。
Even in the already published blog, we may modify and add appropriately.
posted by sakurai on January 16, 2019

デジタル的に出力すればOKのグラフィック系と異なり、アナログ系のオーディオ系は正しく動作させるのに案外苦労が必要でした。これだけでなく、リアルタイム性やノイズ防止の考慮を含めるともっと大変でしょう。

出来上がったサウンド系階層のブロック図を図79.1に示します。これはソフトマクロで、中にステートマシン、サウンド格納用ROM、パラシリ変換ユニットから構成されます。

図79.1
図79.1 サウンド系階層ブロック図

基本的に左側のステートマシンが、外部から与えられた音色コードに従い、右上のサウンド格納用ROMから8bitPCM wave情報を読み出し、それを右下のパラシリ変換ユニットを用いてDAC用シリアルデータに変換します。

サウンドの難しい点は演奏終了以前に割込みが入ったらどうする等の、時間的な仕様を定義するところです。本来は同時発声チャネルを複数用意し、サウンドを重ね合わせれば良いはずですが、今回は優先順位表(図79.2)を作成し、優先度の高いサウンドが、演奏中の優先度の低いサウンド演奏を中断させる仕様としてみました。優先度の高いサウンドを待たせるとおかしくなるためです。例えばインベーダの移動音が、弾の発射音を中断させても違和感を感じます。マスキング効果を考えれば、重畳しなくても特に問題ないことが実験により判明しました。

図79.2
図79.2 サウンド優先順位表


左矢前のブログ 次のブログ右矢

posted by sakurai on January 6, 2019

ここでアナログ波形をDSOで取得してみます。図78.1のような波形が取得されました。青がシリアルDACデータ、黄色がDACの出力のアナログ波形です。

図78.1
図78.1 DSOアナログ波形

一方で、サウンドデータをAudacityで開いてみると、図78.2のような低音の波形となっています。これはインベーダの進行音です。

図78.2
図78.2 Wave波形

シミュレーション波形やwaveデータ波形は図78.2のようであり、アナログ波形はこのようでなければならないはずなのですが、図78.1ではある閾値以上と以下で波形が折り返されているようです。ここで思いつくのがMSBが反転しているのではないかということです。ここまではwaveデータをそのままDACに入力すれば良いと思っていたので、データ構造を調べてみます。すると、以下の事がわかりました。

  • 8bitPCMデータは符号なし
  • 16bitPCMデータは符号付き

従って、パラシリ部で8bitから16bitへ伸長する際にLSBへのゼロ詰めだけではなく、符号なし⇒符号付き変換を実施しなければなりません。ハードウェアにMSBを反転する修正を加えたところ、図78.3のような正しいアナログ波形が得られました。

図78.3
図78.3 DSOアナログ波形

破裂音はロウパスフィルターが入っていないことだと考えていましたが、波形を見て一目瞭然、符号付き⇒符号なしの変換が抜けていたことが根本原因でした。これで音楽データであってもきれいに再生できるはずです。


左矢前のブログ 次のブログ右矢

posted by sakurai on December 28, 2018

破裂音原因解析

シミュレーション波形を確認すると、アナログ波形がなんだか尖っています。アナログとデジタルの一致性が必要で、そのためにはサンプリング周波数の1/2以上の周波数をカットする必要があります(標本化定理)。

図77.1
図77.1 シミュレーション波形

周波数帯域を制限するには22.05KHz以下をカットするロウパスフィルターを入れる必要がありますが、まずDACチップのデータシートの参考回路図を確認します。

図77.2
図77.2 DACデータシート

図77.2のとおり、アナログ出力にRとCで構成されるロウパスフィルターが入っています。

次にそれがどのように実装されているかを、PMOD DACモジュールのデータシートで確認します。

図77.3
図77.3 PMOD DACモジュールデータシート

出力のロウパスフィルターが入っていないことがわかりました。 サンプリング周波数は44.1[KHz]であったので、ロウパスフィルターの時定数を決定します。 図77.2にCを求める式が書かれており、 $$ C=\frac{50+470}{4\pi\cdot 44.1\cdot 10^3\cdot 50\cdot 470}=40[nF]=0.04[\mu F] $$ となることから、アナログ出力に40nFのキャパシタ(0.04$\mu$Fのセラコン等)を挿入すれば良いことになります。


左矢前のブログ 次のブログ右矢

posted by sakurai on December 20, 2018

データ変換

ROMに入れるデータをVivadoで読めるCOEフォーマットに変換します。以下はwaveの16進ダンプファイルをCOEのデータ部に変換するコマンドです。これにヘッダとトレーラを付ける修正を行いROMデータとします。

$ od -An -t x1 -v input.wav|sed -e 's/ /,/g' >output.coe

シミュレーション

詳細設計に基づきシミュレーションを実施し、波形を確認し、不具合を修正するというループに入ります。 Vivadoはアナログ波形も表示可能であり、シミュレーションでアナログ波形を確認します。

もちろん全体だけでなく、細かいクロック毎の動きを見ていきます。ステートマシンが期待通りのステート遷移をしているか、LRCLKとシリアルビットデータの並びはDAC仕様に合っているかなどを見ていきます。

図76.1
図76.1 シミュレーション波形

実験

FPGAにビットファイルをダウンロードし、実験します。STARTスイッチを押すと、それなりの音が出ますが、元のファイルをPCで再生した音と若干異なるようです。なにか破裂音が混ざっています。元の音はインベーダが破壊された時の音なので、破裂音が混ざっていても構いませんが、もし音楽だったら聴くに堪えないでしょう。


左矢前のブログ 次のブログ右矢

posted by sakurai on December 10, 2018

設計指針

設計指針を記述していきます。

  • サウンドデータはwaveフォーマットでROMに8bit単位で格納する。フォーマットは非圧縮PCM、8bit、モノラル、11.025KHzサンプリング
  • FSMはFSMCLKで動作する。FSMCLK=176.4KHz(=1/8*SCLK)。
  • 8bitサウンドデータの読み出しは、FSMからアドレスを与えることで行う。
  • FSMから並列直列変換(以降パラシリ)にROMデータを供給する。
  • パラシリでは8bitデータをDACの要求する16bitデータに伸長する。具体的にはROMデータを上部8bitに詰め、下部8bitはゼロを詰める。
  • パラシリのシフトはSCLK(=BCLK)で行う。SCK=1.4112MHz。
  • パラシリの1フレームはLRCLKの立下りで開始する。LRCLK=44.1KHz(=1/32*SCLK)。
  • 変換されたシリアルデータは1SCLK遅らせてDACに出力する。

アーキテクチャ設計

以上の指針からブロック図を書くと以下のようになります。

図75.1
図75.1 サウンドコントローラブロック図

詳細設計

上記ブロック図(アーキテクチャ設計)をもとに、ブロック内部をRTLで記述したものを下図に示します。 SCKはシリアルクロック(=ビットクロック)ですが、内部クロックモードを使用するために、コンスタント出力としています。基本的にZynqを除き、ブロック図と一致しています。

図75.1
図75.1 Vivadoのブロック図


左矢前のブログ 次のブログ右矢

posted by sakurai on November 30, 2018

前回の続きです。

設計制約

設計制約をリストアップします。

  • LRCLKの1周期に対し、L=16bit, R=16bitの32bitのシリアルデータが必要であり、シリアルデータはSCKでシフトされるので、SCK=LRCLK*32。ただしこのSCKは、DACに供給しなければDAC内部で発生されます。
  • データフォーマットより、サンプリングレートは16進数で16'h2b11=11025、すなわち11.025KHz。LRCLK=Fs(サンプリング周波数)とのことで、LRCLK=11.025KHzとしたいところですが、下図において、LRCLK=11.025KHzが存在しないので、データのほうを4倍のインターポレーションすることにし、LRCLK=44.1KHzとします。
  • 上記関係式よりSCK=1.4112MHz。
  • マスタークロック(MCLK)は下図のように、256, 384, 512, 768, 1024倍等の任意性がありますが、ここでは256倍の11.2896MHzを使用します。

図74.1
図74.1クロック表

タイミングチャート

クロックに関する設計制約がだいたい解決したので、タイミングチャートを書いていきます。基本的にハードウェアベースのサウンド出力であるため、FSMによるフォーマット解析を行います。タイミングチャートは以下のとおりです。

図74.2
図74.2 タイミングチャート

ステートマシンのクロックFSMCLKは図74.2のように、ステートアドレス、ステートデータ、データアドレス、データデータの4クロックで1サウンドデータの読み出しになることから、4*FSMCLK=2*16*SCLK、これよりFSMCLK=176.4KHz。

DACが要求する16bitデータ×2ch(L, R)の32bitデータについては、データソースが8bitモノラルであるため、8bitデータをMSB側に詰め、残りは0詰めし、16bitとします。LとRには同じデータを供給します。

インタポレーションのやり方は線形補完する方法と、同じデータを繰り返す方法がありますが、もともと16bit@44.1KHz表現可能なDACに対して8bit@11.025KHzという荒い音質であることから、同じ32bitデータを4回繰り返すことにします。

以上で設計制約から来るクロック周波数とタイミングチャートが確定したので、これに基づいてFSMを設計します。


左矢前のブログ 次のブログ右矢

posted by sakurai on August 20, 2018

次はサウンドです。音を出すには可聴周波数帯域の適当な振幅のアナログ信号を出力します。そのために前述したPMOD-I2SというDACが必要になります。

製品データシート: https://reference.digilentinc.com/_media/reference/pmod/pmodi2s/pmodi2s_rm.pdf

使用DACデータシート: https://www.mouser.com/ds/2/76/CS4344-45-48_F2-472818.pdf

このデータシートによればステレオの24ビットオーディオDACとのことで、ゲームサウンドには高級すぎますが、それほど高価ではないのでこれを使うことにします。インタフェースはI2Sというシリアルデータです。 マニュアルに掲載されているシリアルデータフォーマットを次の図に示します。

図54.1

16bitデータ2ch(L, R)の32bitデータをシリアルでDACに供給しますが、注意点は図のように1ビットズレていることです。

入力としては、waveファイルをデコードし、シリアルデータを出力するようなモジュールを作成します。以下に入力のwaveフォーマットを示します。 http://sky.geocities.jp/kmaedam/directx9/waveform.html

このwaveをデコードするFSMを設計します。以下にサンプルのwaveフォーマットを示します。

図54.2

入手したwavファイルのサンプリング周波数とデータ精度がバラバラで、ハードで扱うには厳しいので、全て11.025KHz、8bit、Mono、メタデータ無しに変換しておきます。そのコマンドは以下のとおり。

$ ffmpeg -i input.wav -ac 1 -ar 11025 -acodec pcm_u8 -fflags +bitexact -flags:v +bitexact -flags:a +bitexact output.wav

次回に続きます。


左矢前のブログ 次のブログ右矢

posted by sakurai on August 7, 2018

必要な機材を以下に示します。

図53.1

FPGAのPMODコネクタに接続するVGAインタフェース及びオーディオインタフェースはdigilent社から購入したものです。以下にそれらのページを示します。

PMOD VGA Video Graphics Array:
https://store.digilentinc.com/pmod-vga-video-graphics-array/

PMOD I2C Stereo Audio Output:
https://store.digilentinc.com/pmod-i2s-stereo-audio-output/


左矢前のブログ 次のブログ右矢

posted by sakurai on August 3, 2018

通常はデュアルポートメモリのA側はCPUを用いてプログラムから読み書きすることになります。言うまでもなくソフトウェアにより、複雑なシーケンスを制御しやすいためです。ところがFPGAはハードウェアといえどもプログラム可能なハードウェアであり、ましてHDLにより設計することから、フルハードウェアで描画マスタを構成することにトライしようと思います。

テーマは今年40周年を迎えた「スペースインベーダー」です。フルハードウェア(ソフトウェアを一切使用しない)でこれが動けば、たいていのものはハードウェアでできるのではないでしょうか。

Vivadoによりグラッフィックコントローラに描画マスタをハードウェアで構成したものを以下の図に示します。

図52.1

これが動作しているところを、以下の図に示します。

図52.2

左矢前のブログ 次のブログ右矢

posted by sakurai on July 30, 2018

前回までで、VRAMの内容を定常的に表示するグラフィックディスプレイコントローラの設計が完了しました。割愛していますが、シミュレーションを駆使し、動作の確認を行っています。

このままでは描画マスタを設計していないため、静止画を表示することしかできませんが、Bitstream中に初期VRAMデータを埋め込むことが可能です。ブロック図でデュアルポートメモリをダブルクリックすると、以下の画面が現れ、"Other Options"の"Memory Initialization"にファイル名を入力します。

図51.1

ここでは、dual port memoryの初期データファイルとして、スペースインベーダーの画像を取り込むことにします。データは以下のようなフォーマットで構成します。Vivadoにはデータがフォーマットに沿っているかの確認を行うコマンドがあり、validateを実行し、正しいデータかどうか確認した後にwrite bitstreamを行います。

図51.2

以下にGDCを起動したところの図を示します。残念ながら、描画マスタを設計しておらず、表示マスタのみが動作しているため、画像は静止しています。

図51.3

左矢前のブログ 次のブログ右矢


ページ: