guruguru123’s diary

かなり雑な作業日記です。

DACドライブブロックの作成(2)

前回guruguru123’s diaryDAC(MCP4726)ドライブブロックを作成し、シミュレーションは上手くいったが、実機では動作しなかった。

書き込みのクロックを100kHzにして、オシロスコープで100kHzクロックとシリアルデータを観測してみた。すると、スタートビットとストップビットのところに入れてあった遅延が働いていないことがわかった。

シミュレーションでは

sdi <= '0'  after 4000 ns when p.start_bit = '1' else ...

と書いても動いてくれるが、実機ではこれは反映されない?

 

ということなので遅延記述をなくしてスタート、ストップビットの記述を行った。スタート、ストップビットはかなり強引だが、とりあえずクロック分周用のカウンタにかませて出力するようにした。

f:id:guruguru123:20180116185910p:plain

オシロで波形を確認するとスタート、ストップビットが出ていることが確認できた。

DACを駆動してみると出力が得られたため、0から4096まで連続で書き込みするものを作成した。100kHzでは駆動できたため、400kHzのファストモード、3.6MHzのハイスピードモードでも駆動試験をしていく。

f:id:guruguru123:20180116190434j:plain

DACドライブブロックの作成

今回用いるのは12bitのD/AコンバータであるMCP4726。以前駆動しようとしたLTC2624は今回置いておいてこっちを動かしてみる。

MCP4726はI2Cで出力データ指定を行うようだ。I2Cは以下サイトを参考にした。

電子工作室

MCP4726のデータシートにデータ転送の例があったため、これに倣って出力していく。転送周波数はDCMで出力できる1.6MHzを分周して260kHzを使う。プルアップ抵抗は10kΩ。f:id:guruguru123:20180113181615p:plain

シミュレーション結果が以下画像。

f:id:guruguru123:20180113181606p:plain

実機でのテストを行ったがまた上手くいかない。原因を探っていく。

コマンドの追加

コマンド受付機構の改良 - guruguru123’s diaryでコマンド受付機構の改良をおこなったため、各機能ブロックを修正しながらコマンドを追加していく。

 

追加したコマンドと継続して利用するコマンドを以下に挙げる。例ではTeraTermからコマンドを送っている。コマンドは入力してEnterキーを押すと受け付ける。もしそのコマンドがない場合はまたコマンドを要求する。入力間違えした場合も以下画像のようにEnterを押して復帰させる。改行コードは送信をCRにする(CR+LFを解釈させるのが面倒であったため)。

f:id:guruguru123:20180111154653p:plain

 

srst:システムリセット

コマンドを受け付けると、RS232C通信ブロック以外の機能ブロックをリセットする。また、起動時にシステムリセットが行われる。

 

cmdl:コマンドリスト

現在使用可能なコマンド一覧をRS232Cにて出力する。

f:id:guruguru123:20180111154816p:plain

 

dds1:DDS単発駆動

コマンドを受け付けると、DDSの40bitチューニングワードを16進数10文字で要求する。10文字入力されるとそれに従ってDDSを駆動する。

f:id:guruguru123:20180111155044p:plain

 

dac1:DAC単発駆動

コマンドを受け付けると、DACの12bit出力用データを2進数12文字で要求する。12文字入力されるとそれに従ってDACを駆動する。(シミュレーションの結果も正しく、信号も確認済みだが、実機での試験がうまくいっていない。)

f:id:guruguru123:20180111155707p:plain

 

sdw1:SDRAM単発書き込み

コマンドを受け付けると書き込みアドレスと書き込むデータを要求。データは16進数で16文字の64bit。アドレス、データが入力されるとSDRAMへ書き込む。単発といってもバースト動作4でSDRAMを動かしているため実際には4つのアドレスに書き込みを行っている。

f:id:guruguru123:20180111155545p:plain

 

sdr1:SDRAM単発読み出し

コマンドを受け付けると読み出しアドレスを要求。入力後指定したアドレスのデータを読み出しRS232Cで出力。こちらも書き込みと同様4つのアドレスを読み出している。

f:id:guruguru123:20180111155556p:plain

 

adcr:ADC駆動

コマンドを受け付けると書き込み開始アドレスを要求。入力後、その時点から100MHz/4の周波数をリファレンスクロックとしてデータを100回取り込む。周波数の分周と取り込むデータの数は任意に変更できる。f:id:guruguru123:20180111155815p:plain

 

serr:SerDes経由のデータ受信

コマンドを受け付けると書き込み開始アドレスを要求。SerDes_EN信号がアクティブの間信号を受信しSDRAMへ書き込みを行う。SerDes_ENがディスエーブルされた時点で受信終了。

f:id:guruguru123:20180111171958p:plain

 

reqr:SDRAM読み出し、DDS,DAC駆動

コマンドを受け付けると読み出し開始アドレスと終了アドレスを要求。入力後、格納されたデータに従ってDDSとDACを駆動する。読み出していく間隔は目で確認するために1秒ほどにしてあるが6クロックくらいにすることもできる。

f:id:guruguru123:20180111161145p:plain

 

 

DDS単純駆動

今まで作った機能を統合するにあたり、DDSを単純駆動する機構も改良した。

 

コマンドをdds1とし、これを受け付けると16進数で10文字の40bitデータを要求する。10文字受け付けた時点でAD9851を駆動する。下図はデータ指定の様子。

f:id:guruguru123:20180102232925p:plain

また、前回(DDS,DAC用データ格納アドレス指定 - guruguru123’s diary)で作ったアドレス指定の仕方がわかりにくかったため、bit数を表示するようにした。

f:id:guruguru123:20180102232929p:plain

DDS,DAC用データ格納アドレス指定

DDSとADコンバータ用のデータをSerDes経由で受信を行い、SDRAMへ格納する際に、今までは0番地から書き込みしていたものを、アドレスを指定して書き込みができるように改良していく。

具体的には以下画像のようにRS232Cでアドレスを指定する。これはSDRAMからの読み出しの際のアドレス指定の様子だが、書き込みも同様である。reqwおよびreqrのコマンドを受付ると始めに書き込み、読み出し開始アドレスを聞かれる。これが終わるとreqwの場合はSerDesの受信をデータが終わるまで受信を行う。reqrの場合は読み出し終了アドレスを聞かれて、入力が終わると読み出しが開始される。

f:id:guruguru123:20171226162851p:plain

このときbankを2bit、rowを12bit、colを6bitで指定する。それぞれbit数がわかっているため、以下のように文字列を出力するようにした。アドレス幅はgenericで指定するようにしていく。

f:id:guruguru123:20171226165746p:plain

アドレス指定する機構ができたため、SerDes受信だけでなくユーザが単発のデータをSDRAMに書き込みするコマンドもできそうだ。

これに追加して、SDRAMに書き込みすることなくDDS、DACをパラメータを直接書き込みするコマンドも作っていく。

 

前回のところで書き忘れたが、文字列を送信する際には文字列に付随してカウンタにその文字数を指定する必要がある(n.num_dがそのカウンタ)。

f:id:guruguru123:20171226165556p:plain

コマンド受付機構の改良

DDSやADコンバータ、DAコンバータの駆動回路を統合するために、コマンドを増やす作業が必要になった。コマンドはRS232_C通信で送っているが、今までは送信、受信ともにデータを16進数として内部で処理をしており、文字列解釈の記述量が多くなってしまっていた。

そこで、新しいデータタイプを作ってうまく処理をし、記述量を減らせないかと考えた。

type ascii is ('1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',':','?','!','-');

type ascii_vector is array (Natural range <>)of ascii;

というようにasciiというユーザ定義のデータタイプと、それのベクタであるascii_vectorを作った。

しかし、これをモジュールファイルに書き込んだのでは入出力で用いることができなかった。そこで、これを記述したパッケージを作って対応した。パッケージファイルの中身は以下の通り。

f:id:guruguru123:20171223230217p:plain

これをモジュール内で有効にするにはライブラリworkと作成したパッケージをuseで宣言しなければならない。

library work;
use work.ascii_pac.all;

これをトップモジュールと有効にしたいモジュールに記述するとユーザ定義のデータタイプを使うことができる。

これを用いることで送信の際の文字列指定が容易になった。これを元にコマンドを増やしていく。コマンドは以下のステートに追加するだけでよい。

f:id:guruguru123:20171226165144p:plain

ADC受信回路:実機試験

ADC受信回路:シミュレーション - guruguru123’s diary

でシミュレーションを行い、正しく動作しそうなので、実機でテストを行った。

使うADコンバータはAD9294。以下リンクはデータシート。

http://www.analog.com/media/jp/technical-documentation/data-sheets/AD9214_JP.pdf

24ピンのうち10ピンがデジタル出力であり、これをPapilioのI/Oポートに接続する。

ENCODE(13ピン)はエンコードクロックの入力であり、これにはPapilioから100MHzを供給する。

PWRDN(14ピン)もPapilioのI/Oに接続して制御する。

DFS/GAIN(2ピン)はデータ・フォーマット・セレクトおよびゲイン・モード・セレクトでAGNDに接続した。AGNDに接続するとオフセット・バイナリのデータフォーマットでアナログの入力範囲が1Vp-pになる。

REFSENSE(3ピン)は通常AGNDに接続、とあるのでAGNDに接続。こうすると4ピンのREFが出力になる。

そのほかは電源、グラウンドなど。

アナログ電源は安定化電源から3Vを供給し、デジタル出力ドライバの電源はPapilioの5V出力を変圧して3.3Vにして使用した。

動作させると、動くことには動くが電圧の受付範囲が1Vp-pより低くなっているような気がする(差動入力をしっかり作っていないため)。

差動入力の段を作り込めばしっかり動いてくれそうだ。

Papilioのほうは以前実機テストして問題なく動き、今回も動作が確認できた。