2021/12/04

Tang Primer (EG4S20) の ADC を使ってみる

はじめに

RISC-V に興味があって Tang Primer を買ったのが 2020年5月頃。ADC をいじろうとするも、やりかけてお蔵入りに。記憶あいまいだけどある程度のところまで進んでました。安価な Tang Primer の ADC も使えるようになれればいいなということで、とりあえず今回は実際に動かすところまでやってみました (2021年11月末)。
そういえば当初は家にある激安電子ドラムのカスタマイズに使おうと思ったんだっけ。なんもしてない。。

Tang Primer

Anlogic の EG4S20 を搭載した Sipeed の FPGA 開発ボードです。
国内だと、スイッチサイエンスさんや、Shigezoneさんで入手できます。

使い方は Tang Primer の上記 URL の Getting Started を見ていただければ。あとはググれば試されている方の情報見つかります。本もあるようですね。

EG4S20  の ADC


EG4S20 の ADC は 8-channel 12-bit 1MSPS ですが、詳細はデータシートをみてみます。
データシートは以下からダウンロードできます。
以下、Eagle_DataSheet_V2.8_english.pdf から抜粋しました。

電気的特性


ADCモジュールの端子機能


タイミングチャート


以上です。

VREF は Tang Primer では 3.3V 固定です。従って 0-3.3V が 0-4095 に対応します。またADC のクロックは最大 16MHz。16 cycle で変換終了するので、ちょうど 1MSPSになります。

動作は SOC に 1パルス与えると動作開始で、EOC 1パルスでれば終了です。チャネルの選択は SOC より前に選択して EOC が立つまで保持ということかな。アナログのマルチプレクサの切り替えになると思うので早めに切り替えておくに越したことはないと思います。

Sampling Pulse と書かれている部分は多分、Sample/Hold 回路が開いている時間だと思うのですが、ここの長さは制御できないようです。まぁ、中の回路はクロック同期なんでしょうから、例えばこの期間のクロックを伸ばせば多分時間延ばせるのではないかと思います。なのでちょっとしたクロックゲーティング回路を足せば実現できるのでは?でもEG4S20に CG (Clock Gating)セルなんてあるんでしょうかね。Latch と AND または OR で作れなくはないけどタイミング合うかな。。

ADC IP Core の生成

RTL を書く前に IP core を生成します。とはいっても ADC のモジュール EG_PHY_ADC の有効にしたいチャネルを入れたラッパーをインスタンスするだけのようです。手置きしても大丈夫っぽいですが、Generator を使います。EG_PHY_ADC はパラメータで各チャネルのEnable, Disable を切り替えるようです。

EG4S20 _DataSheet_V1.5_english.pdf の 4.1 Special IP use にごく簡単に生成方法が書かれています。有効にしたいチャネルを選択するぐらいです。途中 File (ファイル名)と Component name (module 名)を指定するところがあります。adc など何でもいいとは思いますが、同じ名前にしておいてもいいでしょう。好みですが。あと Add to project ウィンドウでプロジェクトに入れる?と確認するところはチェックを入れてOKしておけばプロジェクトに取り込まれます。ファイルはデフォルトでプロジェクトのフォルダの下の al_ip フォルダ以下に置かれます。

選択したチャネルのピンアサインは固定で、IO Constraint で与えることはできません。また選択したチャネルにアサインされたピンは、IO Constraint から他の機能にアサインできなくなります。TD (Tang Dynasty) の HDLBit Flow で Optimize RTL まで実行すると IO Constraint で選択できるピンから消えます。

Tang Primer の端子アサインについては、sipeed-tang-primer-pins.pdf で確認できます。

SPI + ADC の仕様

ADCの動作を確認するため、SPI client?(今どきはなんとよべば) I/F をくっつけてみます。SPI は CPOL=0, CPHA=0 のモード0 で。ビット幅は 16bit とします。お手軽に SS が下がったら ADC を起動して、5bit 目から ADC 12bit の結果を MISO(いやこのネーミングもどうすれば。。)に出力します。ADC の結果は符号なしなので、とりあえず最初の上位 4bit は 0 出力で埋めておきます。ちなみに ADC 終了の eoc は見てません。SPI のクロックが早すぎると間に合いません。


タイミングチャートは Google のスプレッドシートでw

クロックは Tang Primer のボードには 24MHz の Xtal が載ってます。これから 16MHz 以下の ADC clock を作ればいいので 1/2 分周して 12MHz のクロックを ADC に与えることにします。この条件で SPI は 2MHz 程度で動作します。

端子アサインは以下の通りにしました。
N11: ADC0 (ADC 入力)
K14: CLK_IN (24MHz Xtal)
C15: MISO
C16: MOSI (使いません)
B16: SCLK
B15: SS
K16: XRES_IN (Tang Primer の USER スイッチ。プルアップされてます)

Simulation

回路が出来たので検証します。ADC モジュールのビヘイビアがあるのでそれを利用します。
ビヘイビアは以下の場所にあります(Windows の場合)。

C:\Anlogic\TD4.6.4\sim

TD でテストベンチのトップとか、Model Sim 用の do ファイルとか作ってくれるのですが、自前でテストベンチ用意して、Icarus verilog (iverilog) で検証してみました。

ところで ADC モジュールのビヘイビア、eg_phy_adc.v の中身を見ると、Channel select signal s に与えた値を dout に出す仕様のようです。s のチェックにはなるのですが、SPI 含めてデータがちゃんと通るかどうかを見るために、テストベンチでは ADC の出力データを決めている sample_B を外からフォースしてシミュレーションしてみます。1bit だけ立てて SPI で読み込み、を 12bit 繰り返します。

GtkWave

うまくいってるようです。よしよし。

論理合成と書き込み

端子アサインは FPGA Flow の User Constraints -> IO Constraint から指定して、適当な名前で保存しておきます。



タイミング制約は FPGA Flow の User Constraints -> SDC Constraint で作成。途中経過出すと長くなるので、作成した制約の中身は以下のような感じ。create_clock だけやっときました。


合成は緑の丸に三角のボタンで。あっという間です。特にバイオレーションとかもないので、下矢印のアイコンをクリックして書き込みです。イレースして、Flash に書き込みます。

動かしてみる

合成結果を書き込んだ Tang Primer を実際に動かしてみます。
ADC の入力はパルジェネとか安定化電源持っていないので、M5Stack の DAC を使って生成しました。12bit の ADC に対して 8bit の DAC では役不足だし、正確な出力も作れず、校正された計測機器は持ち合わせていないので、ファンクション確認程度になります。
また Tang Primer に実装した ADC は SPI I/F を持っているのでもう一つ用意した M5Stack で SPI をポーリングで動かして ADC のデータを取り込んでみました。
DAC の出力は Faces に付けたエンコーダーパネルでグリグリすると変わるのがわかると思います。だいたい。。同じ値ということで。

 

今回お試ししたデータ

Git に上げておきます。


RTL 検証・合成環境


RTL

src, al_ip フォルダに入っています。
adc_top.v
トップレベル階層です。adc_core と spi がインスタンスされています。
spi.v
SPI I/F 部分です。
adc_core.v
EG_PHY_ADC をインスタンスしています。

テストベンチ

simulation フォルダに入っています。
tb_spi_test.v
テストベンチのトップです。adc_top.v をインスタンスしています。
run_spi.bat
テストベンチ実行用バッチファイルです。実行すると iverilog でシミュレーションを走らせて検証を行います。tb_spi_test.vcd が生成されますので、GtkWave などで波形を確認できます。

実行環境

Windows10 で実行しました。
TD 4.6.4 64-Bit
Verilog simulation iverilog 11.0 (devel)
VCD 波形表示 v3.3.100

M5Stack プログラミング環境


m5stack フォルダに入っています。
ADC_SPI_IF.ino
Tang Primer と SPI 接続する側です。ポーリングした結果をディスプレイに表示します。
SCLK(G5), MISO(G17), MOSI(G16), SS(G22)
MOSI は使っていません。
DAC_Controller.ino
Tang Primer の ADC の入力信号を DAC で作ります。Faces のエンコーダーパネルを使う前提のコードです。出力中のデータを画面に表示します。
DAC1(G26)

Arduino IDE 1.8.13 で確認しています (なぜかこちらは Mac で。Windows でもきっと問題ないです)。M5Stack ディレクトリに .ino ファイルを置いています。
SPI master (MOSI はいらない) と DAC がそれぞれひとつずつ使えればいいので、M5Stack シリーズならほぼなんでもいいと思います。多少書き換えは必要とは思いますが。エンコーダーパネルを使いましたが、ボタンで値の上下でもいいですね。