ZYNQ搭載の高速ADCボード「Cosmo-Z」(コスモゼット)は、
FPGAをユーザがカスタマイズすることができる高速データ収集装置です。
Cosmo-Zをカスタマイズしてユーザ回路でデータを処理するやり方の例を紹介します。
ダウンロードとプロジェクトの生成
まずは「Cosmo-ZのFPGAソース公開とビルド方法」の記事を読み、ダウンロードとプロジェクトの生成を行ってください。
Vivadoのプロジェクトを起動すると、以下のようなBlockDesignが現れます。
信号処理系統の説明
Signal Processブロックの説明
上の図で左下にあるSignalProcessをクリックして開きます。
SignalProcessは階層構造になっていて、様々なモジュールが中に入っています。
SignalProcessブロックでは、ADCBlock→Filter→UPP(汎用パルス処理)→TRIGGER→trigdelay(トリガディレイ)→captureという順に信号が流れていきます。
ユーザがカスタマイズできるのは、FilterとTRIGGERの2種類です。
Filterをカスタマイズすることで、
- ADCで計測された信号をFPGAでリアルタイム処理するために取り出す
- 独自のリアルタイム処理するフィルタを追加
することができます。
信号の規格
各ブロックを接続している信号はAXI Streamという標準的なバス規格ですが、バスのビット幅はADC_MAXCH × ADC_BITSでパラメタライズできるようになっています。
ADC_MAXCHはADCのチャネル数、ADC_BITSはADCのビット数で、デフォルトではADC_MAXCH=8、ADC_BITS=12となっています。
この値を変更するには、BlockDesignのトップにあるコメントを書き換え、
Tcl窓にNahiConfigByComment
と入力します。
Tclスクリプトが走り、プロジェクト内のすべてのモジュールのADC_BITSとMAX_ADCCHが一斉に書き換えられます。
それに伴い、AXI Streamのビット幅も自動的に調整されます。
Filterブロックをカスタマイズしよう
BlockDesignにあるFilterブロックを開けてみると、実は、中身は空っぽです。
このFilterは、BlockDesignの階層になっていて、ユーザが自分で回路を作りこむようになっています。
モジュールの追加
プロジェクトのsrcの中にあるdata_combine.vhdとdata_slice.vhdを追加します。
追加したら、BlockDesignの何もないところで右クリックし、Add moduleを行ってRTLソースを追加します。
SliceとCombine
SLICEはCosmo-Zの計測データが流れているAXI Streamを1つ1つのチャネルのデータに分解してくれるものです。
※XILINXのコアにも似たようなのはあるのですが、SLICEが12bit単位とか14bit単位とかできなさそうです。
Sliceの中身
Sliceモジュールの中身は
tvalid_o <= tvalid_i;
tdata0_o <= tdata_i(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0);
tdata1_o <= tdata_i(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1);
tdata2_o <= tdata_i(ADC_BITS * (2 + 1) - 1 downto ADC_BITS * 2);
tdata3_o <= tdata_i(ADC_BITS * (3 + 1) - 1 downto ADC_BITS * 3);
tdata4_o <= tdata_i(ADC_BITS * (4 + 1) - 1 downto ADC_BITS * 4);
tdata5_o <= tdata_i(ADC_BITS * (5 + 1) - 1 downto ADC_BITS * 5);
tdata6_o <= tdata_i(ADC_BITS * (6 + 1) - 1 downto ADC_BITS * 6);
tdata7_o <= tdata_i(ADC_BITS * (7 + 1) - 1 downto ADC_BITS * 7);
Combineモジュールの中身は
tvalid_o <= tvalid_i;
tdata_o(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) <= tdata0_i;
tdata_o(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) <= tdata1_i;
tdata_o(ADC_BITS * (2 + 1) - 1 downto ADC_BITS * 2) <= tdata2_i;
tdata_o(ADC_BITS * (3 + 1) - 1 downto ADC_BITS * 3) <= tdata3_i;
tdata_o(ADC_BITS * (4 + 1) - 1 downto ADC_BITS * 4) <= tdata4_i;
tdata_o(ADC_BITS * (5 + 1) - 1 downto ADC_BITS * 5) <= tdata5_i;
tdata_o(ADC_BITS * (6 + 1) - 1 downto ADC_BITS * 6) <= tdata6_i;
tdata_o(ADC_BITS * (7 + 1) - 1 downto ADC_BITS * 7) <= tdata7_i;
です。本当に単純にばらしたりくっつけたりしているだけです。
デフォルトの直結で動作させた場合
まずは分解したデータをそのままつないで結合するデザインを作ります。
いきなりですがこれを論理合成してFPGAに書き込んで動かしてみます。
論理合成の途中経過は省略します。
Cosmo-ZのCH1にはファンクションジェネレータから100kHzの正弦波を、CH2にはTTLレベルのトリガ信号を入れます。
CH3~CH8はオープンにしています。
Webオシロで見てみると、茶色の線(CH1)には正弦波が、赤色の線(CH2)には矩形波が映っています。
CH3~CH8には何も入力していないのでノイズが見えています。
CH3~CH8に、FPGA内部の配線をつなぐ
CH3~CH8はコネクタには何もつながっていないので、ノイズしか入ってきませんでした。
ノイズを見てもしようがないので、FPGAの中でCH1とCH2の信号をコピーしてつないでみましょう。
結果は下の図のとおり。CH3,4,5にはCH1のコピーが、CH6,7,8にはCH2のコピーが入りました。
まとめ
Filterブロックの中から信号を取り出すことで、計測したままのデータをそのまま扱うことができます。