FPGAボード(Sipeed Lichee Tang Primer)のAD変換器マクロを、オリジナル16ビットCPUコアMoscoviumマイコンに搭載するテーマの続きです。
前回の記事で、必要な技術検討は終了していますので、詳細設計を進めて行きたいと思います。
以下図にAD変換器ユニットADC124のブロック図を示します。
AFEは仕様上最速の16MHzで駆動するので、変換時間1μsが可能ですが、afeifブロック内ステートマシンのオーバヘッドにより、最小変換時間は約1.25μs/チャンネルとなります。
次に、I/Oレジスタ一覧を示し、解説を続けます。
Addr | Name | R/W | Bit:15〜0 | Memo | |||||||||||||||
0xf0e0 | adcctl | RW | − | − | − | − | − | − | − | − |
AR DY |
AD CE |
− |
CE NB |
CSEL[3:0] | adc control | |||
0xf0e2 | adcint | RW | − | − | − | − | − | − | − | − | CENF[3:0] | CENE[3:0] | interrupt control | ||||||
0xf0e4 | adcperi | RW | PERI[15:0] | conversion period | |||||||||||||||
0xf0e6 | − | − | − | − | − | − | − | − | − | − | − | − | − | − | − | − | − | − | reserved |
0xf0e8 | adcdat0 | R | − | − | − | − | DAT0[11:0] | conversion data 0 | |||||||||||
0xf0ea | adcdat1 | R | − | − | − | − | DAT1[11:0] | conversion data 1 | |||||||||||
0xf0ec | adcdat2 | R | − | − | − | − | DAT2[11:0] | conversion data 2 | |||||||||||
0xf0ee | adcdat3 | R | − | − | − | − | DAT3[11:0] | conversion data 3 |
BUSC出力のセレクト信号はbcs_adcu_nです。上表の範囲でアサートされるので、ADC124ユニット内では、アドレスbadr[3:0]を復号してレジスタを特定しています。このI/Oユニットはバイトアクセス禁止です。必ずワードアクセスしてください。
リセット解除後、AD変換器マクロはパワーダウン状態、PLLは発振停止🚫状態です。AD変換を実行する前に、AD変換器(とPLL)を起動しておく必要があります。
adcctlレジスタのADCEビットをセットすると、AD変換器が起動、PLLが発振開始します。AD変換器の動作準備が整うまでの時間規定が無いので、どのくらいの時間を待てば良いかは不明なのですが、PLLは発振開始してから所望の周波数(16MHz)にロックすると、extlockという信号をアサートするので、それまで待つ必要があります。
※PLLのロックにはある程度時間がかかるので、その間にAD変換器も変換可能な状態になっていると仮定します。本来は、Anlogic社がデータシートなどで起動時間を規定しておくべきです(見当たりませんでした)。
PLLがロックすると、adcctlレジスタのARDYビットに1が立ちます。以下にADC124ユニットの起動コード例を示します。
// start up adc124
ldwi r7,adcctl
ldbiu r0,adc_adce
stw [r7],r0
ldw r0,[r7]
andi r0,adc_adce
beq error_no_adc // ERROR:ADC124が搭載されていない。
// wait ARDY flag
ldw r0,[r7]
andi r0,adc_ardy
beq pcnt-6
上の処理終了後、AD変換を実行することが出来ます。なお、ADCEビットは一度セットすると、クリアすることはできません。
前節までに解説したADC124ユニット仕様の中で、AD変換に関係する物をまとめておきます。
AD変換器マクロに16MHzクロックを供給して、変換時間は16サイクルですので、仕様上は1μsで変換が終了します。今回のADC124ユニットでは、変換終了後のデータ受け渡しやステートマシンの処理などによってオーバヘッドがあるため、最小変換時間は約1.25μsです。
adcctlレジスタのCSEL[3:0]フィールドで1を立てたチャンネルが、連続変換され、これを「変換セット」と呼びます。
adcperiレジスタにμs単位で指定した時間毎に、変換セット(AD変換)が連続実行される「連続変換モード」と、1回変換したら停止して待機状態となる「シングル変換モード」があります。
シングル変換モード(adcperi=0)では、変換セットを1回実行すると、adcctlレジスタのCENBビットが自動クリアされて、待機状態に戻ります。
以下図は、CENB=1、CSEL[3:0]=0x1、adcperi=0として、チャンネル0だけをシングル変換する様子です。
横方向は時間の経過を示しています。「Channel」欄に「#0」と記した箱は、チャンネル0の変換状態を示しており、横幅は1チャンネル分の変換時間約1.25μsです。
1変換セットの実行が済むと、CENBビットが自動クリアされて待機状態に戻ります。
下図は、CENB=1、CSEL[3:0]=0xd、adcperi=0として、チャンネル0,2,3をシングル変換する様子です。
CSEL[3:0]フィールドで指定したチャンネル0,2,3は、CENB=1となった時に連続して変換が実行されます。adcperi=0なので、1変換セットの実行が済むと、CENBビットが自動クリアされて待機状態に戻ります。
変換間隔を指定するadcperiレジスタ>0の設定にすると、連続変換モードとなります。
下図は、CENB=1、CSEL[3:0]=0x9、adcperi>>1として、チャンネル0,3を連続変換する様子です。
1回の変換セットで、チャンネル0と3が連続変換されます。変換セットの実行が終了してもCENBビットは自動クリアされず、CENB=1を保ちます。時間を計測するカウンタがadcperi[μs]に達すると、再び変換セットが実行されて、チャンネル0,3が連続変換されます。
CENBビットがユーザのI/Oレジスタ書き込みによってクリアされるまで続きます。
下図は、CENB=1、CSEL[3:0]=0xf、adcperi=1として、チャンネル0〜3を連続変換する様子です。
4チャンネル分の変換時間は約1.25μs×4チャンネル≒5μsですが、adcperi=1μsと、それより短い時間を設定されたため、変換セットの変換が終了すると、直ちに次の変換セットが実行されます。結果、上図の様にチャンネル0〜3の変換が連続して実行されます。
これまで、Moscoviumマイコンは1系統の24MHzクロックだけを使って設計してきたので、タイミング制約はとてもシンプルでした(以下)。
MCOC.sdc:
#Created Clock
create_clock -name clk -period 40 -waveform {0 20} [get_ports {clk}]
上の通り、24MHzにマージンを取って、25MHz(周期40ns)のクロックをclk入力ポートに設定して、以上終了でした。
今回、PLLを使って16MHzクロックを生成し、AD変換器のアナログフロントエンドと、その制御ブロックafeifに16MHzクロックを供給します。また、16MHz⇔24MHz間は非同期設計していますので、フォルスパス設定が必要となります(↓)。
MCOC_adc.sdc:
#Created Clock
create_clock -name clk -period 40 -waveform {0 20} [get_ports {clk}]
create_clock -name clk16m -period 60 -waveform {0 30} [get_nets {adc/clk16m}]
#Set False Path
set_false_path -from [get_clocks {clk}] -to [get_clocks {clk16m}]
set_false_path -from [get_clocks {clk16m}] -to [get_clocks {clk}]
16MHzクロックclk16mにもマージンを持たせて、約16.67MHz(60ns)を設定してあります。
16MHz⇔24MHz間をフォルスパス設定したので、誤って同期的に信号をやり取りしている箇所があっても、タイミングエラーは一切レポートされなくなります。ツールのサポートが期待できない、と言う事なので、非同期設計は慎重に!
以下リンクより、AD変換器を搭載したMoscoviumマイコンMCOC115AD0408のデザインをダウンロードできます。FPGAボード(Sipeed Lichee Tang Primer)への書き込み手順はこちらを参照してください。
以下に、コンパイル(論理合成・配置配線)結果をまとめておきます。
AD変換器を使った具体的なアプリケーションを作る前に、まずはちゃんと機能する物だか、AD変換器マクロの動作確認を兼ねて実験してみたいと思います。
TD IDEのデータシートでは、変換精度関係が全く触れられておらず、不明ですので、手持ちの12ビットDA変換器モジュール(MCP4725)(下図)を使い、簡易評価してみます。
AD変換器の変換精度評価(方法及び指標)については、「#8-2 逐次比較型AD変換器を作る」で解説済みです。
12ビットAD変換器に対して、同じ12ビットDA変換器なので、DNLやINL等、階段状の変換結果が必要な指標は評価できません。本ページでは、絶対精度、オフセット誤差、フルスケール誤差に関してのみ評価することとします。
Moscoviumで動作させる評価用プログラムを以下にリンクしておきます。
評価用プログラム:test_adc.asm
※アセンブルに必要なインクルードファイルは、こちらからダウンロードしてください。
Moscoviumのシリアルモニタから、以下のコマンドを受け付けるようになっています。
MCOC115AD0408を書き込んだFPGAボードと、MCP4725を以下表に従って接続してください。
FPGAボード | 接続 | MCP4725 |
3.3V | → | VCC |
GND | ⇔ | GND |
N11(adc_ch0) | ← | OUT |
P2(stws_scl) | ⇔ | SCL |
R2(stws_sda) | ⇔ | SDA |
以下図に実験中の様子を示します。
実験サンプル:【 】内はシリアルモニタからの送信データ
【daco,0】
OK: daco=0x0000 adc=0x0000 [lsb]
【daco,2048】
OK: daco=0x0800 adc=0x07e9 [lsb]
【daco,4095】
OK: daco=0x0fff adc=0x0fdc [lsb]
だいぶ差分が出ていますが(誤差が大きそう……)、なんとなく、期待値に近いデータが返っているようです。一気に全データを取得してみましょう。
【eval】
0,0
1,0
2,0
3,0
:
: (中略)
:
4092,4058
4093,4062
4094,4065
4095,4062
OK: eval finished
Excelでデータを取り込んで、グラフ化してみました(下図)。
横軸に入力アナログ電圧(0〜3.3[V])、縦軸に読み取ったデジタル値(0〜4,095[LSB]、上側)と絶対精度AE[LSB](下側)を取ったグラフです。
AD変換器の評価指標ではありませんが、一次回帰直線の相関係数R2=1と、直線でした。AD変換器(入力アナログ量に応じたデジタル値を出力する機器)としては機能しているみたいです。
評価できた指標は以下の通りでした。
絶対精度: AE=9〜−40[LSB]
オフセット誤差: OE=11.6LSB
フルスケール誤差: FE=20.2LSB
酷いですね、絶対精度AE=−40LSB(MAX)とは……。期待はしていませんでしたが、AE=−40LSBは約5ビット(≒log2 (40))に相当するので、解像度12ビットの内、5ビットは誤差に取られて、正味7〜8ビットAD変換器程度の実力しかありません。「12ビットAD変換器」は、おこがましいです。
そもそも、逐次比較型で12ビットAD変換器なんて、相当厳しいのですよ……。見た目のスペック「解像度12ビット、変換時間1μs」はカッコ良いですが、全く実力が伴っていませんでした。
FPGAボード搭載の、AD変換器特性規定も無い様なAD変換器なんて、初めから期待はしていませんでした。まあ、性能としてはこんな所なのでしょう。ただ、約1.25μsで変換終了する高速AD変換器なので、変換精度が必要なアプリケーションでないなら、そこそこ使えるでしょう(1^^;)。