FPGAボード(Sipeed Lichee Tang Primer)を使って設計しているオリジナル16ビットCPUコアMoscoviumについて、粗方のI/Oユニットは揃えてきたつもりですが、アナログ出力可能なI/Oユニット、DA変換器が無かったな、と。
前回、デジタルフロントエンドの設計まで終わらせたので、今回はΔΣ型DA変換器のアナログバックエンドを設計して、評価まで完結しようと思います。
FPGAボード単体ではアナログ回路を形成できないので、ΔΣ型DA変換器のアナログバックエンドだけは外付け回路で作製します(下図)。
※LTspiceのシミュレーション用回路図です。fPDM=24MHzで、繰り返し周期が最長となるPCM(8ビット)=1LSBを想定したパルスを印加しています。シミュレーション自体は、これと言って面白くないので省略します。
基本的には、CR回路を使ったアナログLPFを通せば終了です。CR回路の次段(Vlpf)に直接、電流負荷を接続してしまうと、次段のインピーダンスによってCR回路の特性が変わってしまうため、ボルテージフォロアで受けて出力(Vo)しています。
LPFの遮断周波数fc=1÷(2π×CR)≒24.5kHzですが、音声信号の出力20〜20k[Hz]を想定した遮断周波数に設定してあります。
もっと出力周波数が遅くて良い場合、時定数CRを大きくしてfcを低下させることで、DA変換精度を向上することができます。ですがその分、アナログ電圧が安定するまでの時間は伸びるので、ご注意ください。
逆に、もっと出力周波数を上げたい場合には、時定数CRを小さくして、出力したい周波数以上にfcを設定しないと、LPFで遮断されてしまいます。この場合、脈動電圧幅が大きくなってDA変換精度が低下することにも留意が必要です。
なお、上図の回路だと、ボルテージフォロアとして使ったオペアンプLM358の電流駆動能力によって、アナログ出力Voの電流駆動能力が決まります。多分、数10mA程のはずです(オペアンプのデータシートなどで確認してください)。
PCMのビット幅N、PCMの出力周波数fPCM、PDM出力周波数fPDM、クロック分周比CLKS[3:0]=Mと置くと、fPDMとfPCMの間には、概ね以下の関係が成り立っています。
fPDM÷2N÷(M+1)≒fPCM
PDMの繰り返し周期は、出力するPCM値が1LSBまたは2N−1[LSB]の時、最長の2Nサイクルとなります。以下図を使って、LPFの動作とDA変換精度の関係を説明します。
PDM=1の間、LPF(CR回路)は充電されて電圧が上昇、PDM=0の間は、LPFは放電して電圧が低下します。このせいで、本来出力すべきアナログ電圧をIDEALだとすると、上側にMAX、下側にMINまで脈動します。
MAX−IDEALが正側の最大誤差、IDEAL−MINが負側の最大誤差となります。
LPFの時定数CRに関して述べると、CR→小で出力電圧の変動幅が大きくなって変換誤差→大、CR→大で出力電圧の変動幅が小さくなって変換誤差→小、となります。時定数CRは、遮断周波数fcを決定するパラメータでもあるので、変換誤差と遮断周波数のどちらを優先するのか?によって対処方法が変わってきます。
ビット幅N、クロック分周比Mによって、PDMの繰り返し周期が変化するので、以下の様な取捨選択も存在します。
用途や特性に応じて、折り合いをつけて使ってください。
忘れていましたが、前回設計したデジタルフロントエンド(PCM→PDM変換回路)部分の論理シミュレーションを実行しておきましょう。
iverilogを使って、シミュレーションしてみました(下図)。
ΔΣ型DA変換器DAC121ユニットのdacdatレジスタに正弦波を書き込んで、その時のPDM出力を観測しました。正弦波PCM値(dacdat[11:0])の小/大が、PDM出力(pdmo)に於ける1の粗/密に変換されています。
想定通りのPDM出力を得られているので、後段にアナログバックエンドを接続すれば、所望のアナログ電圧を出力することができるでしょう。
評価用のプログラムを以下にリンクしておきます。
評価用プログラム:test_dac.asm
アセンブルしてFPGAボードに書き込んでください。シリアルモニタから以下のコマンドを受け付けています。
シリアルモニタコマンド仕様:
FPGAボードと、外付けにブレッドボードなどへ作り込んだアナログバックエンド回路、USB⇔UART変換モジュール(FTDI等)を、以下表の様に接続してください。
FTDIモジュール | 接続 | FPGAボード | 接続 | アナログバックエンド回路 |
GND | ⇔ | GND | ⇔ | GND |
TXD | → | uart_rxd | ||
RXD | ← | uart_txd | ||
5V | → | Vcc | ||
dac0_pdmo(port_iop[4]) | → | pdmo | ||
adc_ch0 | ← | Vo |
ΔΣ型DA変換器DAC121ユニットの出力dac0_pdmo(デジタル信号)を、アナログバックエンドに接続します。そこから、アナログ出力VoをFPGAボードのAD変換器ADC124ユニットの入力端子adc_ch0に戻して、デジタル値として読み取ります。つまり、DA変換器の出力をFPGAボード搭載のAD変換器で評価する接続です。
実験サンプル:【 】内はシリアルモニタからの送信データ
【dactl,12,0】
OK: dactl
ΔΣ型DA変換器を12ビット解像度、最速の出力クロック(=24MHz)に設定しました。
【daco,0】
OK: daco,0 (adci=0)
【daco,2048】
OK: daco,2048 (adci=2007)
【daco,4095】
OK: daco,4095 (adci=4095)
ΔΣ型DA変換器から、オフセット電圧(0LSB)、中間電圧(2,048LSB)、フルスケール電圧(4,095LSB)を出力しました。Moscoviumからの応答に、AD変換器で読み込んだデジタル値が表示されています。まあまあ、出力した値が読み出せている様では、ありますね。
【dactl,8,3】
OK: dactl
【eval】
EVAL
0,25
1,0
2,43
3,53
:
: (中略)
:
252,4018
253,4062
254,4067
255,4093
END
OK: eval
ΔΣ型DA変換器の解像度を8ビットに変更して、一気に精度データを取得しました。以下図に、ΔΣ型DA変換器の評価結果を示します。
こちらで解説した指標について以下表にまとめ、考察を続けます。
指標 | 測定値 | 単位 | ||
オフセット誤差 | Eofs | 1.563 | LSB | |
フルスケール誤差 | Eful | 0.813 | LSB | |
微分非直線性誤差 | DNL | -13.188 | 14.750 | LSB |
積分非直線性誤差 | INL | -13.688 | 6.875 | LSB |
絶対精度 | AE | 12.625 | LSB |
考察:
追加実験サンプル:【 】内はシリアルモニタからの送信データ
【dactl,8,0】
【eval】
評価結果を以下グラフに示します。
上のグラフだと、絶対精度AE≒19.8LSBと、最初のグラフに比べて絶対精度がさらに低下しています。
最初のグラフと何が違うか?と言うと、【dactl】コマンドの第二引数が3 → 0に変わっています。第二引数は、PDM信号の出力クロックの設定です。
最初のグラフは、fCPU÷(3+1)=6MHzでPDM信号を出力した。
2個目のグラフは、fCPU÷(0+1)=24MHzでPDM信号を出力した。
つまり、最初のグラフの方がPDM信号の出力周波数が低いので、その分、発生するEMIノイズレベルとしては低くなっています。結果として、ΔΣ型DA変換器の絶対精度が向上した様です。つまるところ、PDM出力のデジタルノイズが測定系に悪さをしているのですね。
今回は、アナログ回路を扱うのに不利なFPGAボードだったので仕方がないのですが、本来であれば、アナログバックエンドまで含めてオンチップに構成して、高速なデジタルPDM信号がチップの外に出てこないようにしないと、自分が発生させたデジタルノイズ📢によって、ΔΣ型DA変換器の変換精度を低下させてしまう結果となります。
総括すると、変換精度はさておき、DA変換器としては機能している様なので、FPGAボードを使った「試作」目的で使うのであれば十分耐え得ると判断しました。
ΔΣ型DA変換器は、クロック周波数を上げて行くと比較的簡単に解像度(ビット数)を上げることができるのですが、CR回路の出力電圧変動や、高速なデジタル信号によるEMIノイズなどの課題を対策しないと、結局変換精度を低下させることになってしまうみたいです。中々難しいですね……。