製品情報>ZYNQ搭載 ADCボード「Cosmo-Z」>開発日記>2016年9月

2016年9月

Cosmo-Zの新しいソフトウェア開発

2016.09.20

現状のCosmo-Zのソフトウェアは、Web経由での操作や、Linuxのコンソールからの操作、WindowsやLabViewの専用アプリからの操作など、いくつかのアプリが用意されています。

CosmozwebappCosmozlinCosmozwin

これらのアプリの構造は、下の図のようになっています。

 

Cosmoz_hier

基本的にはZYNQ Linux上で動くコンソールのアプリがベースとして動いていて、WindowsアプリはTCP/IP経由でコマンドを送って動いているにすぎません。

また、この構造だと、コマンドの解釈ルーチンと、ハードウェアを操作する部分が一体となっているので、ユーザがプログラム全体を把握して、独自の機能を追加するのが極めて困難になってきています。

Cosmozapp

 

そこで、アプリからハードウェアを操作している部分、コマンドを解釈している部分、レジスタやメモリ操作の手順を実行している部分を分けて、APIの形で整理することにしました。

新しいアプリの構造は次の図のようになります。

Cosmoz_hier2_2

まず、Cosmo-ZのアプリからFPGA内のレジスタやメモリを操作する部分をHAL層として分離します。

具体的には

  • 物理メモリへのRead/Write
  • FPGA内蔵レジスタへのRead/Write
  • 割り込みのハンドリング

のような低レベルの処理です。

そして、ユーザAPIからはHAL層を隠ぺいし、「サンプリング周波数の変更」「波形キャプチャの実行」などの高レベルな処理をユーザに解放することにします。

こうすることで、Cosmo-ZのプログラムはZynq Linuxの上で動くだけではなく、Windowsのアプリとして、VisualStudioやBorland C++で作ることができるようになります。

 

例えば、Windows PC上で動作するCosmo-Z APIが、「波形キャプチャ」という関数を呼び出されたら、

  • FPGAのレジスタの○番に○○を書く
  • FPGAのレジスタの○番が○になるまで待つ
  • メモリの○番地から読み出し

という処理を行っているのですが、このレジスタの読み書きはWindows PC上で実行されるわけではなく、TCP/IPを通じてターゲットボードのZYNQ Linuxへ送られ、ZYNQ Linux上のCosmo-Zのアプリがそのレジスタ/メモリ操作を行い、生のデータをWindows PCに送り、Windows PC上でデータを解釈して結果を組み立てるという仕組みです。

 

MPPCアレイの設計 

青函トンネルでの実験により、プラスチックシンチレータとMPPCで宇宙線(おそらくミューオン)を観測することができることがわかったので、今度は2次元にならべたものを作ろうと思います。

MPPCは遮光と温度が大事なので、プラスチックではなくアルミで箱をちゃんと作ります。

今回は、6cm×6cm×1cmのプラスチックシンチレータを、縦横に4個×4個並べて、16個入りのユニットを作ります。

Asm1

1つ1つのシンチレータの部屋はアルミの壁で分離されていて、互いに光が漏れないようになっています。

Asm2

金属加工屋さんに見積もりを依頼したら、だいたい10万円くらいでできそうです。16個のシンチレータとMPPCとアンプ基板を合わせても、100万円はかからないでしょう。

 

これが完成すれば、宇宙線(おそらくミューオン)がどこを通ったかがわかるはずです。この箱を最低2レイヤー並べれば、宇宙線が飛来した方向がわかるでしょう。

そんなに簡単にはできないとも言われましたが、やってみないとどうして簡単にできないのかもわからないので、チャレンジしてみる価値はあると思っています。

 

Vivado版Cosmo-ZでMCA動作

2016.09.16

Vivado版の新デザインのCosmo-Zで、MCAを長時間走らせてみた。

2台の「プラスチックシンチレータ&MPPC検出器」をつないでバックグラウンドを8時間測定。

Mcanewcosmoz

MPPCは温度にすごく敏感なので、設置場所に注意しないと(他の機器の排熱や空調で)結果に差がでてしまうが、今回はうまくいった。

2つのスペクトラムはぴったり重なる。

中央の少し盛り上がっている部分が40Kによるもの。それ以上はだいたい宇宙線と思われる。

 

Cosmo-ZのVivado化が完成

2016.09.15

ようやく、Cosmo-Zの(ほぼ)全機能をVivadoへ移植できました。

Cszv1

ちゃんと波形のキャプチャも、

Cszv3

マルチチャネルアナライザも動きます。

Cszv2


 

VivadoでのZYNQの割り込み

2016.09.13

Cosmo-ZのVivado版デザインで、波形のキャプチャができるようになったわけなのですが、どうも1回キャプチャすると止まってしまいます。

なんと、割り込みが発生していない疑い。

そもそもZYNQの割り込みはかなりの謎仕様で、IRQ0が割り込みの何番につながっているか、よくわかりません。

ISEのときは、例の画面で割り込み0と1を使うようにしておくと、

Irq_1

ZYNQのPL→PS割り込みは、割り込み番号91~84と、68~61にあるようなのですが、IRQ(0)の割り込み番号は90番に割り当てられます。(91番ではない)

おそらく、IRQ0→#90、IRQ1→#91になっているのでしょう。

 

VivadoでのZYNQ場合はさらに複雑で、何番に割り当てられるかは全くわかりません。

Zynq_irq

少なくとも、IRQ_F2P(0)は#91でも#90でもないようです。しかし、デバイスドライバはIRQ #90をハンドルするように作ってしまっているので、何としても90番の割り込みを発生させたいところです。

そこで、IRQ_F2P(0)からIRQ_F2P(15)の16bitを全部一緒にドライブすることを考えました。そうすれば、#61~#68と#84~#91の全部が発生するから、#90の割り込みも発生するだろうというわけです。

ところが、ZYNQのIRQ_F2Pは[0:0]で定義されてしまっていて、

Zynq_irq2

このバス幅を変える設定箇所はGUI上にはありません。

では、どうやって変えるかというと、割り込み信号を出力している側のモジュールで16ビットの幅にしてやればよいようです。簡単にやるには、xlcontatを使います。

Zynq_irq4

接続したらValidate Designを行うと、ZYNQの入力ポートが自動的に16bitに変わります。割り込みの信号をドライブするバスが16bitだと、割り込み信号も16bitになるようです。パラメータの伝搬というそうです。

これで無事に90番の割り込みが(も)発生するようになりました。

 

Cosmo-Z Vivado版で波形キャプチャができた!

2016.09.11

 

ZYNQ搭載ADCボード、Cosmo-Z(コスモゼット)のVivado版デザインで波形キャプチャができた。

まだ、CPUモジュールと、ADCブロックとキャプチャモジュールを組み合わせただけだけど、

Csz_capture_2

このとおり、波形がキャプチャできました。

Csz_capture2
 

 

Vivadoで3ステートバッファ!?

2016.09.10

Vivadoでトライステートバッファ作ろうとしているのですが、HDLで作ったIPモジュールの中で、

pad_bp <= o when (dir = '1') else 'Z';
i <= pad_bp;

というような記述してもCriticalWarningが出てしまいます。

Tricell

メッセージは、「Converted tricell instance 'U0_i1447' to logic」でした。

このU0_i1447というのは、デザインによって変わります。

つまり、tricellのロジック(おそらく3ステートのロジック)を普通のロジックに変更したよ、というCritical Warningのようです。

実機で動作させてみると、出力はちゃんとできているようですが、入力はできていないようです。

もちろん、ISEでは普通に動いていたのに、なぜでしょうね。

sun

プリミティブのIOBUFを使ったら双方向ができました。

adc_sclk_op   : out std_logic;
adc_sdio_ip   : in  std_logic;                    -- ADCチップへ
adc_sdio_op   : out std_logic;                    -- ADCチップへ
adc_sddir_o   : out std_logic                     -- 1ならsdio出力
・・・
adc_sdio_inst : IOBUF port map (
	IO => adc_sdio_bp,
	O => adc_sdio_i,
	I => adc_sdio_o,
	T => not adc_sddir
);

sun

何はともあれ、今手掛けているCosmo-ZのデザインのVivado再設計プロジェクトが、CPUとADC周辺までは完璧にできました。

Csz_adc1

全体はこんな感じ。

Csz_adc2

 
 

 

Number of Nodes with overlapsについて

 2016.09.08

 ADCから受け取った信号をAXIで読み出せるような回路を書いていたら、VivadoのRoutingが急に遅くなった。ログを見ると 

Number of Nodes with overlaps = ??

というメッセージが出ている。

調べてみると、フォーラムにそれらしき記事がある。

https://forums.xilinx.com/t5/General-Technical-Discussion/What-is-quot-Number-of-Nodes-with-overlaps-quot-parameter-in/m-p/526817#M20549

よくわからないけど、複数のクロックが使われている信号があると遅くなるようだ。

Cosmo-ZではADCのクロックや、AXI GPのクロック、AXI HPのクロックと3つのクロックが使われている。

これらのクロック間でのタイミング解析をしないようにするには、XDCファイルにフォルスパスというのを設定すればいいようだ。

基本的な書き方は、

set_false_path -from [get_clocks クロック1] -to [get_clocks クロック2]
set_false_path -from [get_clocks クロック2] -to [get_clocks クロック1]

でいいのだけど、そのクロックがMMCMの出力であるような場合は、名前を探すのが大変になる。

set_false_path -from [get_clocks [get_clocks -of_objects [get_pins cosmoz_top_i/adcblock_0/U0/inst_adcclkgen/inst_clkmult/inst/mmcm_adv_inst/CLKOUT0]]] -to [get_clocks clk_fpga_1]
set_false_path -from [get_clocks clk_fpga_1] -to [get_clocks [get_clocks -of_objects [get_pins cosmoz_top_i/adcblock_0/U0/inst_adcclkgen/inst_clkmult/inst/mmcm_adv_inst/CLKOUT0]]]
set_false_path -from [get_clocks [get_clocks -of_objects [get_pins cosmoz_top_i/adcblock_0/U0/inst_adcclkgen/inst_clkmult/inst/mmcm_adv_inst/CLKOUT0]]] -to [get_clocks clk_fpga_0]
set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks [get_clocks -of_objects [get_pins cosmoz_top_i/adcblock_0/U0/inst_adcclkgen/inst_clkmult/inst/mmcm_adv_inst/CLKOUT0]]]
set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks clk_fpga_1]
set_false_path -from [get_clocks clk_fpga_1] -to [get_clocks clk_fpga_0]

 

 

ZYNQでQSPI ROMを使う方法

2016.09.01

ZYNQ搭載のADCボード「Cosmo-Z」には、128MbitのQSPI ROM(N25Q128A11)が乗っています。

N25q128


これまでのCosmo-Zでは、QSPI ROMはLinuxから認識されないため、活用してこれなかったのですが、ようやくその原因と使いかたがわかりました。

sun

ZYNQのLinuxをビルドすると、QSPI ROMのデバイスドライバ(MTD: Memory Technology Driver)は標準で入っています。なので、カーネルから認識されない原因はデバイスツリーにありました。

Cosmo-Zのデバイスツリーを、dtcを使って逆コンパイルしてみてみると、

ps7-qspi@e000d000 {
    clock-names = "ref_clk", "pclk";
    clocks = <0x2 0xa 0x2 0x2b>;
    compatible = "xlnx,zynq-qspi-1.0";
    interrupt-parent = <0x3>;
    interrupts = <0x0 0x13 0x4>;
    is-dual = <0x0>;
    num-cs = <0x1>;
    reg = <0xe000d000 0x1000>;
    xlnx,fb-clk = <0x1>;
    xlnx,qspi-mode = <0x0>;
    #address-cells = <0x1>;
    #size-cells = <0x0>;
    flash@0 {
        compatible = "n25q128";
        reg = <0x0>;
        spi-tx-bus-width = <0x1>;
        spi-rx-bus-width = <0x4>;
        spi-max-frequency = <0x2faf080>;
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        partition@qspi-fsbl-uboot {
            label = "qspi-fsbl-uboot";
            reg = <0x0 0x100000>;
        };
        partition@qspi-linux {
            label = "qspi-linux";
            reg = <0x100000 0x500000>;
        };
        partition@qspi-device-tree {
            label = "qspi-device-tree";
            reg = <0x600000 0x20000>;
        };
        partition@qspi-rootfs {
            label = "qspi-rootfs";
            reg = <0x620000 0x5e0000>;
        };
        partition@qspi-bitstream {
            label = "qspi-bitstream";
            reg = <0xc00000 0x400000>;
        };
    };
};
ps7-qspi-linear@fc000000 {
    clock-names = "ref_clk", "aper_clk";
    clocks = <0x2 0xa 0x2 0x2b>;
    compatible = "xlnx,ps7-qspi-linear-1.00.a";
    reg = <0xfc000000 0x1000000>;
};

となっています。

問題だったのは、上のn25q128と書かれた部分です。ここをn25q128a11に変えればMTDドライバは問題なく認識され、

m25p80 spi0.0: n25q128a11 (16384 Kbytes)
1 ofpart partitions found on MTD device spi0.0
Creating 1 MTD partitions on "spi0.0":

と、表示されます。MTDドライバは、n25q128でも、n25q128aと書いてもでもだめで、n25q128a11の型番の末尾の11までちゃんと区別しているようです。

さて、QSPIドライバの使い方は、XILINXのWikiにあるのですが、

http://www.wiki.xilinx.com/Zynq+QSPI+Driver

これを試してみましょう。ただ、このWikiの内容はQSPI ROMを5つのパーティションに分けているのですが、Cosmo-ZではQSPIからのブートはしないので、このQSPIを16MBのフラットな領域として扱おうと思います。

したがって、デバイスツリーのflash@0とかいうところで、

partition@qspi-all {
    label = "qspi-all";
    reg = <0x0 0x1000000>;
};

と書いておきます。こうすると、0番地から16MBの領域がqspi-allというパーティションになり、起動時には

Creating 1 MTD partitions on "spi0.0":
0x000000000000-0x000001000000 : "qspi-all"

と表示されます。

cat /proc/mtd

で見てみると、

zynq> cat /proc/mtd
dev:    size   erasesize  name
mtd0: 01000000 00010000 "qspi-all"

と表示されます。

QSPIのFlashROMは、そのまま生で使うか、ファイルシステムを作るかが選べるようです。ファイルシステムを作る場合はまず、

flash_eraseall -j /dev/mtd0

でフラッシュを一度消去します。

そして、

mkdir /qspi

でマウント用のディレクトリを作り、

mount -t jffs2 /dev/mtdblock0 /qspi

でマウントします。jffs2というのは、ウェアレベリングしながら扱ってくれるフラッシュROM用のファイルシステムだそうです。

これでマウントできるので、あとは、普通にファイルを何でも放り込むだけです。ただし、結構遅いです。

私はQSPI ROMに、ボードのシリアル番号や、ADCのキャリブレーションデータ、回路のカスタマイズの有無など、ボード1枚1枚ごとに固有の情報を入れておこうとおもいます。

zynq> ls -al
total 1
drwxr-xr-x    2 root     root             0 Jan  1  1970 .
drwxr-xr-x    4 root     root             0 Jan  1  1970 ..
-r--r--r--    1 root     root           180 Jan  1  1970 adcconf
-rw-r--r--    1 root     root             4 Jan  1  1970 serialnum

  

 


© 2017 TokushuDenshiKairo Inc. All rights reserved