ZYNQ搭載高速ADCボード「Cosmo-Z」のユーザ回路追加(前編)

ZYNQ搭載の高速ADCボード[「Cosmo-Z」(コスモゼット)](http://cosmoz.jp/)は、
FPGAをユーザがカスタマイズすることができる高速データ収集装置です。
Cosmo-Zをカスタマイズしてユーザ回路でデータを処理するやり方の例を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/89c1df88-baa4-952f-ecd1-f226b7b6295c.png)

# ダウンロードとプロジェクトの生成
まずは「[Cosmo-ZのFPGAソース公開とビルド方法](https://qiita.com/nahitafu/items/6298c27802432ba31f34)」の記事を読み、ダウンロードとプロジェクトの生成を行ってください。
Vivadoのプロジェクトを起動すると、以下のようなBlockDesignが現れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/9e868841-e107-8a6b-2c68-bda882e2d09a.png)

# 信号処理系統の説明
## Signal Processブロックの説明
上の図で左下にあるSignalProcessをクリックして開きます。
SignalProcessは階層構造になっていて、様々なモジュールが中に入っています。
SignalProcessブロックでは、ADCBlock→Filter→UPP(汎用パルス処理)→TRIGGER→trigdelay(トリガディレイ)→captureという順に信号が流れていきます。

ユーザがカスタマイズできるのは、**Filter**と**TRIGGER**の2種類です。
Filterをカスタマイズすることで、

- ADCで計測された信号をFPGAでリアルタイム処理するために取り出す
- 独自のリアルタイム処理するフィルタを追加

することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/ecc324ca-c6bd-22d6-29d5-d0cdffcae122.png)

## 信号の規格

各ブロックを接続している信号はAXI Streamという標準的なバス規格ですが、バスのビット幅はADC_MAXCH × ADC_BITSでパラメタライズできるようになっています。
ADC_MAXCHはADCのチャネル数、ADC_BITSはADCのビット数で、デフォルトではADC_MAXCH=8、ADC_BITS=12となっています。
この値を変更するには、BlockDesignのトップにあるコメントを書き換え、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/c630f342-9dbc-932a-9222-db0df68b0835.png)

Tcl窓に`NahiConfigByComment`と入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/37eee775-2b8c-fe21-4af1-62aafdc13137.png)

Tclスクリプトが走り、プロジェクト内のすべてのモジュールのADC_BITSとMAX_ADCCHが一斉に書き換えられます。
それに伴い、AXI Streamのビット幅も自動的に調整されます。

# Filterブロックをカスタマイズしよう

BlockDesignにあるFilterブロックを開けてみると、実は、中身は空っぽです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/7ea7bb72-d22a-5502-b512-97b7cf66fb93.png)

この**Filter**は、BlockDesignの階層になっていて、ユーザが自分で回路を作りこむようになっています。

## モジュールの追加
まず、FilterブロックをIPインテグレータで開いたら、　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/f9237a55-bbcf-ec4d-ec45-8337fd1d153a.png)

VivadoのSourcesにある＋ボタンをクリックし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/1740e73c-afcd-0d9e-aa1e-89b00717c4d4.png)

Add or Create Designを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/9ec32a01-0992-cbee-3dfa-9b01111219ae.png)

プロジェクトのsrcの中にあるdata_combine.vhdとdata_slice.vhdを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/3319c783-4a8b-61b3-d8b9-0eae1a6b6e4e.png)

追加したら、BlockDesignの何もないところで右クリックし、Add moduleを行ってRTLソースを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/c7dca368-be0d-6003-0c72-c44108591356.png)

以下のような2つのモジュールが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/31f7c0c1-7604-c6e1-930c-65bbcd076434.png)

## SliceとCombine
SLICEはCosmo-Zの計測データが流れているAXI Streamを1つ1つのチャネルのデータに分解してくれるものです。
※XILINXのコアにも似たようなのはあるのですが、SLICEが12bit単位とか14bit単位とかできなさそうです。

### Sliceの中身
Sliceモジュールの中身は

```vhdl
    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モジュールの中身は

```vhdl
    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;
```
です。本当に単純にばらしたりくっつけたりしているだけです。

## デフォルトの直結で動作させた場合
まずは分解したデータをそのままつないで結合するデザインを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/b243a9fc-8aba-5df8-ca25-c3bd13d89747.png)

いきなりですがこれを論理合成してFPGAに書き込んで動かしてみます。
論理合成の途中経過は省略します。

Cosmo-ZのCH1にはファンクションジェネレータから100kHzの正弦波を、CH2にはTTLレベルのトリガ信号を入れます。
CH3~CH8はオープンにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/5bfaafa5-9841-d0dc-bc1f-0ac88520ec1e.png)
Webオシロで見てみると、茶色の線(CH1)には正弦波が、赤色の線(CH2)には矩形波が映っています。
CH3~CH8には何も入力していないのでノイズが見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/972a43d5-58bd-de2c-9bc0-4a3bba9a68c2.png)

## CH3~CH8に、FPGA内部の配線をつなぐ
CH3~CH8はコネクタには何もつながっていないので、ノイズしか入ってきませんでした。

ノイズを見てもしようがないので、FPGAの中でCH1とCH2の信号をコピーしてつないでみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/50cd9eab-3acf-d2be-4655-1bca452b88ae.png)

結果は下の図のとおり。CH3,4,5にはCH1のコピーが、CH6,7,8にはCH2のコピーが入りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542455/9ed5685e-360b-098b-657c-2b918cca747f.png)

# まとめ
Filterブロックの中から信号を取り出すことで、計測したままのデータをそのまま扱うことができます。

[後編に続く](https://qiita.com/nahitafu/items/ba572706bf30e793139b)