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

2016年6月

HyperFFT回路を実機で動かしてみて心境の変化

2016/6/30

シミュレーションで正しいとわかったので、ハードウェアFFTを実際のFPGAにインプリメントしてみました。

FPGAにロジアナコアを入れて、JTAGで見た実機の信号と、シミュレーション時のパターンが完全に一致しました!

Icchi


これはうまくいっているかも・・と喜んだのも束の間。

同じデータを変換しても、たまにビットが変わることが確認されました。

どうやら、スピードグレード-1のFPGAをスピードグレード-3として論理合成していたので、実際にはスピードが間に合っていなかったと思い、検証を続けていたのですが、どうやら原因はそれだけではないことがわかってきました。

FFTエンジンを回すと、Linuxがいきなりカーネルパニックしたり。まだメインメモリにはアクセスしていないから、Linuxは関係ないはずなのに・・

rain

どうやら、原因がわかってきました。

この回路は、Radix-8のバタフライ演算を1クロックで計算するため、216個のDSP48Eが400MHzで動いています。すると消費電力がハンパない。

BRAM216個だったら全然驚かないのですが、DSP48Eが216個はかなりきます。

SLICEやBRAMとは比べ物にならないほど電流を食うのかもしれません。

発熱でさらに電力が増えると、電源電圧が低下する。

どうやらこのFFT回路は、今までにCosmo-Zで作ったどんなデザインより消費電力が多いようです。狭い基板に詰め込みすぎて、電源が足りなくなって全力が出せない。まるでU.S.S.ディファイアントのような基板です。

sun

クロック400MHzで動かして51.2μ秒で計算するというのはあきらめました。

ハイエンドなFPGAには乗算器いっぱい(数千個とか)あるから、これを有効活用するためにDSP48Eを全力でぶんまわす数値計算アプリを作ろう!という考えは正しくないと思えてきました。

自分の中で何かが変わりました。GPUとFPGAのどっちが速いかなんてことを考えるのはあまり意味がありません。結局は電力です。

クロック上げてDSPいっぱい動かして最高速度を極めるよりも、クロック下げて広い面積で処理したほうが、同じ性能でもトータルの消費電力をされられるかもしれません。

これからはエコ設計でいこう。

ワットあたりの処理能力というのを追究してみたいと思う次第です。

sun

結局、クロック250MHzで動かして、ちょっと遅めの82μ秒で計算することにしたら、電源も発熱もかなり落ち着いて安定しました。

 

Hyper FFT回路が論理的に正しいことを確認

2016/6/29

Radix-8、周波数間引き、改良型アルゴリズムの「Hyper FFT回路」がようやくZYNQの7Z030に入りそうという見通しが立ってきました。

このFFT回路は、216個の乗算器がクロック400MHzで一斉に動作し、Radix-8のバタフライ演算を1クロックで処理します。32768ポイントのFFTが51μ秒しかかからないという恐ろしい速度のFFT回路です。

しかし、クロック400MHzだといろいろな箇所で論理合成が通りません。タイミングエラーが出てしまいます。

わかてきたことは、Block RAMって意外と遅いってことです。普通にXILINXのCoreGeneratorでBRAMを作ると、400MHzで通りません。XILINXのデータシートではBRAMは400MHzで動くはずなのに、困ってしまいますよね。

どうすればよいかというと、CoreGenのオプションで、下のところをチェックを入れればいいようです。

Bram_option_2

BRAMのプリミティブの中にある出力レジスタを有効にしたり、ユーザ回路部分にSLICEを使ってレジスタを入れてくれるようです。今まで、レイテンシが増えるだけじゃん・・って思っていたのですが、なんと、これを入れるとタイミングエラーが解消しました。

レイテンシと引き換えに周波数を上げられるのですね。

あと、256→32にビット幅を変換するBRAMを作ったりすると、ユーザロジックが使われるので遅くなる場合があるようです。その場合もこのオプションで改善できました。

これをZYNQに実装して、パイプラインを入れまくってクリティカルパスを緩くしたところ、なんとかタイミングエラーが出ないようになりました。クロック-クロック間が2.5nsって思った以上に厳しいですね。

Fft_timing_met

sun

さて、論理的な検証のほうですが、シミュレーション上は51μ秒で計算できるのが確かめられました。

Fft_51us_sim_2 

しかし、計算結果が正しくありません。

細かいところを波形を見ていてもわかりにくいので、textioを使って、結果のテキストに書き出すようにしてみました。

やりかたは、まずtextioを読み込みます。

use ieee.std_logic_textio.all;
use std.textio.all;

それから、適当なところでfile型のオブジェクトと、line型の変数を宣言します。

file wf_x : text open write_mode is "read_x.txt"; --出力ファイル
variable wl : line;

ファイルに書き込むには、まずline変数(以下の例ではwl)に文字列をセットして、writelineでファイルに書き出す、という形になります。

write(wl,"x read data",left);
writeline(wf_x,wl); --行をファイルに書き出し
write(wl,"stage raddr x0       x1       x2       x3       x4       x5       x6       x7",left);
writeline(wf_x,wl); --行をファイルに書き出し

このとき、writeという関数を使うと、line変数に""で囲った文字列や、VHDL上の信号、変数などを書き出すことができます。writeは万能です。

16進数で書き出したいときにはhwriteという関数を使います。

if(x_valid = '1') then
  write(wl,f_tmp(14 downto 12),left,6);
  hwrite(wl,f_tmp(11 downto 0),left,6);
  hwrite(wl,x0_o,left,9);
  hwrite(wl,x1_o,left,9);
  hwrite(wl,x2_o,left,9);
  hwrite(wl,x3_o,left,9);
  hwrite(wl,x4_o,left,9);
  hwrite(wl,x5_o,left,9);
  hwrite(wl,x6_o,left,9);
  hwrite(wl,x7_o,left,9);
  writeline(wf_x,wl); --行をファイルに書き出し
end if;

上のような書き方をした場合、アドレスと、x0_o~x7_oまでの信号の値が書き出されます。

x read data
stage raddr x0       x1       x2       x3       x4       x5       x6       x7
000   000   00000000 00001000 00002000 00003000 00004000 00005000 00006000 00007000 
000   001   00000001 00001001 00002001 00003001 00004001 00005001 00006001 00007001 

こうして生成されたファイルと波形を見ると、一致しているのがわかります。

Textio

テキスト出力は便利ですので、長いデータのデバッグが必要になったらぜひ試してみてください。

sun

C言語のソフトで作った計算途中経過と、シミュレータが吐き出した結果を見比べてみて、いろいろ直しました。

まだシミュレーションだけど、HyperFFT回路動きました!計算結果も正しいようです。

普通にFFT回路をFPGAに作ると、アドレスの計算とか、ステージ(ループ)間での無駄な待ち時間が生じてしまうのですが、私のアルゴリズムはそういう無駄が一切なく、20480クロックで結果が出ます。

 

Cosmo-ZのVivado化(3)

2016/6/28

Cosmo-ZのデザインのVivado化を進めています。

Vivadoがわからない私に代わって、学生のアルバイトさんが進めています。

 

ついに、Vivadoで作ったデザインでCosmo-Zが動いたようです。いままで動かなかった原因は、リセットのピンのつながりがISEとVivadoで違っていたからのです。

 

Cosmoz_reset

 

 

CPUはIPインテグレータになったので、その周りのモジュールのIP化を始めました。

まずはADCデコードモジュールです。最大750MHzでやってくるLVDS信号を、位相を調整しながら受信するモジュールです。

Adc_ip

おおっ!なんかパラメータでチャネル数を変えられるようになっているぞ!

Adc_generic

 

だんだんわかってきました。

ISEのときにはパッケージで以下のような型を定義して、ADCのチャネル数×ビット数の二次元のバスを作っていたけれども、VivadoのIPにするにあたってはこれはできないようです。

type t_adcdata_array is array((MAX_ADCCH - 1) downto 0) of std_logic_vector(ADC_BITS-1 downto 0);

なので、ADCチャネル数を変えるとバス幅が変わる、太いのバスを作って何とかするようです。

 

Cosmo-ZデザインのVivado化(2)

2016/6/22

Cosmo-ZデザインをVivadoに移行して、動いたようです。

先週試したときに動かなかった原因は、リセットやクロックの接続、ペリフェラルのアドレス、などがだったようでした。

○○のモジュールに行くクロックは△△で、というのを直したところ、動くようになったとこのとです。

Cszvivado

 

リセット信号は、ISEの時にはaxis_resetという信号だったのが、Vivadoではperipheral_aresetn[0:0]になったり、ISEのときにはCPUのコアから出る信号がprocessing_system7_0_…という冗長な名前だったのが、Vivadoではスッキリしています。

正確には測っていませんが、論理合成時間も半分くらいに減ったような気がします。

sun

リソースの使用率

8chのCosmo-ZをVivadoで論理合成したときは、

Cszvivado3

Cszvivado4

でした。

ISEでは、

Number of Slice Registers   16,085/157,200   10%
Number of Slice LUTs   16,083/78,600  20%
Number of occupied Slices  6,985/19,650  35%
Number of RAMB36E1/FIFO36E1s  58/265  21%
Number of RAMB18E1/FIFO18E1s 16/530  3%
Number of DSP48E1s  72/400 18%

だったので、リソース利用量が格段に減っています。特にDSP48が32個も減っているのが気になります。

これで良いのかどうか不安になります。(何か大事なものが削除されていないだろうか、という意味)

sun

困ったことがもう1つあって、PHYにリセット信号を作っていたタイマーが動かなくなったことでした。

こういう回路でPHYチップに短いリセット信号を送っているのですが、Vivadoに移行したらうまく動かなかったとのことでした。

    process(clk100m) begin
        if(clk100m'event and clk100m = '1') then
            if(phy_timer(phy_timer'left) = '0') then
                phy_timer <= phy_timer + 1;
            end if;
            if(phy_timer = 0) then
                phy_resetn <= '0';
            elsif(phy_timer(phy_timer'left) = '1') then
                phy_resetn <= '1';
            end if;     
        end if;
    end process;
    phy_resetn_op <= phy_resetn;

このタイマーで使っている信号phy_timerを宣言しているところの

signal phy_timer  : std_logic_vector(19 downto 0);
signal phy_resetn : std_logic;

にしたら動くようになったとのことです。

signal phy_timer  : std_logic_vector(19 downto 0) := (others => '0');
signal phy_resetn : std_logic;

どうやら信号の初期値が0になっていないようだとのことなのですが、VHDLの信号の宣言に初期値を書いてはいけないと昔、教わったのですが、今は書かなければならないのでしょうか。

 

FPGAで作るHyperFFTのアルゴリズム

2016/6/21

FPGAでハードウェアFFTを行う回路を作りたいわけなのですが、事情により、0.8ms以内に32768ポイントのFFTを行わなければなりません。

32768ポイントのFFTは、245760回のバタフライ演算が必要ですが、クロック400MHzで1クロック=1演算として動かしたとしても614μ秒かかってしまいます。実際にはメモリの読み出しと書き込みが入るので、1クロックでメモリに読んだり書いたりした場合、2.4msかかってしまうことが予想されます。

普通にFFTをしていては絶対に間に合わないわけなのです。

FFTの計算上のボトルネックは何かを考えてみましょう。

sun

よくある通常のFFT(時間軸間引き、Radix-2のクリーチューキー型)のアルゴリズムを考えてみます。

Fft1_2

この例では16ポイントのFFTなので、ステージは4まであります。

  • 最初のステージ
    • 隣のデータとバタフライ演算
    • 1回の繰り返しを8回繰り返す
  • ステージ2
    • 2つ隣のデータとバタフライ演算
    • 2回の繰り返しを4回繰り返す
  • ステージ3
    • 4つ隣のデータとバタフライ演算
    • 4回の繰り返しを2回繰り返す
  • ステージ4
    • 8つ隣のデータとバタフライ演算
    • 8回の繰り返しを1回繰り返す

このようになります。

このアルゴリズムの欠点は2個あって、計測に応用するのであれば入力データは時系列でならんでいるから、ビットリバースを行うと時間がかかってしまいます。

また、大きなサイズのFFTでは、後ろのステージにいくほど計算すべきデータのアドレスが離れてしまうので、一度に読み出せなくなります。DDRメモリの読み出しなどでメモリの読み出し時間が長くなってしまいます。

読み出すべきアドレスがバラバラに変わるので、メモリのバス幅を広くしようとしても、複数のデータを同時に読み出すことができません。

メモリの利用効率が悪いので遅くなります。

sun

最初の問題は、私が考えた改良型FFTのアルゴリズムを使うと、解決できます。

データの流れはこのようになるので、

Fft2

すべてのステージで

  • 隣のデータとバタフライ演算をする
  • N/2離れたアドレスに書き込み

という、アドレスの規則性が出てきます。

常に隣合うデータを読み込んで計算すればよいので、バタフライ演算回路とメモリの関係は下の図のようになります。

Fft3

J=A*W+B、K=A*W-B

というバタフライ演算を行う場合、演算結果のJとKを2つのブロックRAMに分けてかき、ブロックRAMから次のAとBを読み出す際には2倍のバス幅で読み出すことができます。

このため、メモリの利用効率が良くなり、バタフライ演算器を止めることなく回すことができます。

sun

一方、計測データなど、入力データが時系列で並んでいる場合には、周波数間引きというアルゴリズムを使うと良いでしょう。

周波数間引きのアルゴリズムでは、入力は順番に並んでいて、結果がビットリバースになります。

Fft4

周波数間引きの場合は、バタフライ演算の式は

J=A+B

K=(A-B)*W

となります。

sun

上で紹介したアルゴリズムはFFTのための演算回数を減らすことはありませんでした。そのため、32768ポイントのFFTでは、依然として245760回のバタフライ演算が必要です。

この演算回数を劇的に減らすのがRadix-4やRadix-8という計算手法です。

普通のアルゴリズムで8ポイントのFFTをすると、2つのデータを12回のバタフライ演算で処理してやる必要がありました。

バタフライ演算は入力が決まってしまえば出力は一意に決まるので、この計算を8入力8出力の関数として考えることができます。

つまり、

Fft5

ということです。

中間の結果をメモリにストア/ロードしなくてよいので、速くなります。

Radix2の場合のバタフライ演算量は 245760回で、メモリの読み書きが491520回必要だったので、400MHzでメモリを読み書きした場合は1.2msかかりましたが、

Radix8にすると、、バタフライ演算量は32768/8×5= 20480となって、メモリの読み書きが20480回になります。400MHzで動かし、1クロックで8個分のデータを一気に読みだせば、51usで計算できることになります。

なんと、24倍に高速化できる計算になります。

ただし、この高速化の恩恵を受けるには、8個分のデータを1クロックでメモリから取ってきたり、1クロックで書き込まなければならないので、通常のFFTのアルゴリズムではできません。私の考えた改良型FFTでなければ、メモリが詰まってしまうことになるでしょう。

やりたいことは、

  • Radix-8で高速化し
  • 改良型FFTで、メモリのボトルネックを解消し、
  • 周波数間引きで、計測データを時間ロスせずに連続して変換する

ということです。

sun

32768ポイントのFFTをわずか51μ秒で実行する超高速FFT。

はたして、できるでしょうか?

XILINXのAXI Stream複素数乗算回路

2016/6/20

FPGAで高速フーリエ変換回路を作りたいと思い、XILINXのCoreGeneratorの中にある複素数乗算回路を試しています。

Cmult0

CoreGenのMultipliersの中にある、5.0のAXI4 Streamのものです。

実数部と虚数部はデフォルトのまま、ともに16bitにします。

Cmult1

出力の幅はフォルトでは33になって、実数虚数合わせてなぜか80bitになるようです。

Cmult2

ここでよくわからないのが、Latencyの設定です。AutomaticにするとLatency 6になりますが、Manualにすると0~6まで変えることができます。

sun

数の表現

FFTなどで使うような-1~+1までの数を表現したい場合、16bitの固定小数点では下記のように符号1ビットで、有効数字15bitで表します。

Cmult9


この表現だと、+1は0x7fff、-1は0x8001、+0.5は0x3fff、0は0x0000となります。

このような数を2個、16bit & 16bitの組にして、複素数乗算器に入れると、80bitの信号が出てきますが、[70:55]と[30:15]を切り出すと、元のとおり16bit & 16bitの複素数の乗算結果が得られます。

Cmult10

sun

パイプライン化の検証

Latency 0にしてシミュレーションしてみたところ、入力を与えるのと同時に結果が出てきました。

 

Cmult3

Latency 1にすると、入力が与えられた次のクロックで出てきます。

Cmult4

Latency 2すると、入力が与えられた次の次のクロックで出てきます。

Cmult5

気になるのは、このコアの中身はパイプライン化されているかどうかです。Latencyが大きいと、もしかすると、1つの乗算器を何回も使いまわすようなことをしているかもしれません。

乗算器の使いまわしをしていてパイプライン化されていないとすると、連続してデータを与えることができないので、困ってしまいます。シミュレーションで試したところ、Automaticに設定してレイテンシ6の回路を作り、1クロックごとに異なるデータを与えても問題ないようでした(下の図)。

Cmult7

つまり、中身はパイプライン化されています。

sun

リソースの使用量

リソースはどのくらい使っているのかというと、ZYNQの030に実装してみたところ、

Cmult6

でした。なぜDSP48Eの使用数が3個なのかはわかりません。複素数の乗算なら4回の掛け算だと思うのですが、謎です。レイテンシを変えていっても変化はありませんでした。

気になるリソースの使用率は、

Latency 1の場合

Number of Slice Registers 1
Number of occupied Slices 1
Number of DSP48E1s        3

Latency 2の場合

Number of Slice Registers 2
Number of occupied Slices 2
Number of DSP48E1s        3

Latency 3の場合

Number of Slice Registers 2
Number of occupied Slices 2
Number of DSP48E1s        3

Latency Auto(6の場合)

Number of Slice Registers 66?
Number of occupied Slices 66?
Number of DSP48E1s        3

と、ほぼDSP48のみだけで動いているようなのですが、レイテンシを増やしていくとSLICEも使うようになります。

sun

速度の見積もり

どのくらいの速度で動くかというと、Latency2,3の場合CLK 400MHzにするとタイミングエラーが出ました。Latency 1の場合はタイミングエラーが出ないのですが、

Latency 1にして、ユーザロジックで入力と出力にレジスタを入れたところ、

Cmult8

のようになったので、おそらく解析できていないのだと思います。

コアの中がどういう回路なのかはわかりませんが、上のタイミングエラーのレポートを見る限り、fanoutが大きい気がするので、Latencyをautoにしないと最高速度での動作はできないのかもしれません。

ちなみに、Latency=Auto(6)にしたところ、667MHzでもタイミングエラーはでませんでした。

sun

まとめ

  • XILINXのAXI Stream複素数乗算器は、ちゃんと動く
  • レイテンシはAuto (=6)のままにしないと、400MHzの動作でもタイミングエラーが出る
  • 虚部・実部を16bit & 16bitで表現した場合、結果の[70:55]と[30:15]を切り出せばよい

MCAでK40の効果を見てみる

2016.6.18

Cosmo-Zにプラスチックシンチレータとフォトマルをつなぎ、この写真のような感じで、測りました。

片方のシンチレータの真横に塩化カリウム(40Kの放射線源として)を置き、もう一つのシンチレータは少し離しておきました。

Mca_3

このような配置で、K40ありと、K40なし、でそれぞれ10時間測ってみました。

Mca0618nok

Cosmo-ZのMCAで取ったデータをCSVでエクスポートできるようにしたので、EXCELでグラフにできます。

まず、塩化カリウムありの場合を見てみます。CH4が塩化カリウムの試薬に近い方です。

Withk40_2

次は塩化カリウムなしの場合です。2つのグラフがほとんど重なっています。

Nok40

高さ250あたりのところに違いがあるので、差を取ってみます。

Diffk40

塩化カリウムの試薬に近いほうのCH4では、試薬の有無によって大きな差が出ました。横軸の200あたりにK40の影響と思われるピークが見えていますが、ピークがはっきりしないですね。

プラスチックシンチレータなので、この程度かもしれません。

ちなみに、2インチのNaIを某社に発注中です。

 

波形表示範囲を選択して拡大

2016.6.16

Cosmo-ZのWindowsアプリで、生波形表示の際に範囲を選んで拡大・縮小ができるようにした。まるで125Mサンプル/秒のオシロのようだ。

 

Cosmo-ZがハードウェアMCAになった

2016.6.15

ZYNQ搭載のADCボード「Cosmo-Z」を32chのハードウェアMCA、つまり放射線計測器にする開発を進めています。

Mca_1

まず、MCAでスペクトラムを表示させて、任意の部分を拡大できるようにしました。Windows MDIアプリなので、波形と同時に表示させたり、スペクトラムの全体と、一部を拡大して、特定のチャネル(エネルギー)のカウント数を詳しく見たりするということもできるようになってきました。

sun

シンチレータを2個用意して、TFAを調整してだいたいのゲインを合わせます。

そして、片方(CH4,黄色の線)のほうのシンチレータの横に塩化カリウムを置きます。中のカリウム40が1.3MeV程度のγ線を出してくれるので、少し差が出てきます。

Mca_3


わずか100秒程度でも、MCAに表示されたスペクトラムに差が出てきました。

Mca_2

 

マルチチャネルアナライザが完成に近づく

2016.6.14

マルチチャネルアナライザの開発がだいぶん進んだので、バックグラウンドのスペクトラムを見ています。昨年の春にジャンクで購入した2つのフォトマルは、ゲインがかなり違うし、直線性も怪しいことがわかってきた。

 

 

Cosmo-ZデザインのVivado化

2016.6.14

アルバイトの学生さんが、Cosmo-ZのデザインをVivado化することに挑戦してくれています。

ISEのデザインをVivadoに移行するわけなのですが、PSが出してくるAXI HPはAXI3の仕様になっていて、バーストサイズが16しかないと言っていました。

ISEのときにはEDKが自動的にAXI HP0ポートにInterconnectを入れてくれたけれども、Vivadoでは自分でInterconnectを明示的に入れなければならないということで、結構ハマっていたようです。

 

そして、無事に移行できたようなのですが、うまく起動しないとのこと。

実際に試してみると、起動時のinit.shの中で止まってしまいます。どうやらcosmoz.elfを起動した瞬間に止まってしまうようで、おそらくAXIバスにつながったGPIOを読みにいって、応答がなくて固まっているのかな・・という気がしました。

また、Vivadoのレポートを見ると、

Cosmozvivado

LUTの使用率が16%で、BRAMが21%となっています。

ISEで作ったときには、LUTは95%、BRAMは99%だったので、何かがごっそり抜けている感じがします。

来週中にはVivado化されたCosmo-Zが動くかな・・と期待しています。

 

32chのマルチチャネルアナライザ

2016.6.13

Windowsで動く最大32chのマルチチャネルアナライザが出来てきた。

 

Windows版アプリの開発続き

2016.6.11

Cosmo-Zで32個の入力の好きなチャネルを選んで波形が見られるようになった。32chのデジタイザとしてちゃんと動くようになった。

 

CH1とCH4にシンチレータをつないで計測してみる。ディスクリをかけてC.P.S.(計数率)が急激に減ったところ、つまりノイズをカットしたところに合わせるという操作が簡単にできるようになった。今日の午後からMCAを作る。

 

Cosmo-Zで32chのパルス波形計測が可能になった

2016.6.10

ようやく、Cosmo-Zで32chのパルス波形の計測が可能になりました。(従来は8chまでだった・・)

「パルス波形計測モード」とは、放射線のように、たまにしか来ない信号を測るときに、信号がない期間も記録しておくと無駄なので、トリガが入った前後の波形だけを記録するというモードです。

テスト波形生成回路で、チャネルごとに高さの変わる波形を作り、信号のある時間だけ波形を取ってみると・・

Testwave_32ch

おおっ。全チャネル記録されていました。

このテスト波形は、毎秒180回くらいのレートで作り出しています。1つの波形の記録に800バイトくらい必要なので、1秒ごとに約4.6MBのデータが溜まっていきます。

宇宙線の検出なら十分に間に合うでしょう。

ところで、Cosmo-ZのFPGA、XC7Z030に32ch分の放射線用波形処理回路とMCA(マルチチャネルアナライザ)を入れたらSLICEの使用率が90%になった。まだまだいける?

XC7Z030の使用率が93%までいった。顧客からはVivadoに移行するように言われているが、ISEで頑張る。大丈夫、まだいける。ここからが勝負だ。

 

AXI HPポートのタイミングを緩和する

2016.6.9

長い間悩んできたタイミングエラーがあります。

ZYNQのPS-PL間のインタフェースで起きているタイミングエラーなのですが、

Timerr_1

実は、Cosmo-Zでは多数のADCの信号を束ねるために、64bitのFIFOの後、8:1マルチプレクサを通じてAXI HPポートに送っています。

図にするとこんな感じです。

Timerr_3

見るだけでも気が遠くなりそうなロジックです。

エラーレポートを見ると、PSが出してくるaxi_hp0_WREADYから、FIFOのRD、そしてデータへと続くパスが250MHzのクロックで間に合わないということのようです。

Timerr_2

sun

そこで、前から気になっていたオプションを試してみました。

 

EDK(古くてスマン)を開いて、AXI HP0の設定を開きます。

Timerr_4

その中にある、Use register slice on W channelの設定を、BYPASSからFULLY_REGISTEREDに変えます。

Timerr_5

これをすると、おそらく、AXI HP0のWチャネルにレジスタが挿入されて、タイミングが緩和されるかと思ったのですが・・

ビンゴでした!

Timerr_6

タイミングエラーが解決されて、無事綺麗になりました。

EDKの深いところにあるオプションとか、怖くてなかなか変えられませんが、今回はうまくいったようで良かったです。

 

Cosmo-Zの汎用パルス処理回路が完成

2016.6.8

Cosmo-Zで、放射線計測用のTFA、CFD、Trapezoid Shaper、PeakHold、LinearGate、LLD/ULD、ゲート発生回路が動作するようになりました。

まずは、普通にオシロスコープモード。

Cszapp_1

アナログ入力の部分を指で触ったときの波形です。

手元にシンチレータ+フォトマルがない、という場合でもテストできるよう、FPGAにテスト波形生成回路が入っています。

テスト波形を出してみると、

Cszapp_2

ここで、左のツールボタンにある

Cszapp_3

を押すと、放射線信号処理回路の設定画面が開きます。

Cszapp_4

TFAと書かれた四角をクリックすると、TFA(Timing Filter Amplifier)の設定ボックスが開きます。τdは微分時定数、τpzはポールゼロ回路の時定数、τintは積分時定数、Gainは積分器のゲインです。

Cszapp_5

●BLR(Base Line Restorer)回路

BLRと書かれたボックスの下のチェックボックスをONにすると、ベースライン回復回路(Base Line Restorer)がONになります。BLRは負極性のパルスに対して動作するようになっていますが、「正パルス」と書かれたチェックボックスをONにすることで、正の極性のパルスにも対応できます。

●CFD(Constant Fraction Discrimininator)回路

CFDと書かれた四角をクリックすると、CFD(Constant Fraction Discriminator)の設定ボックスが開きます。CFDは一定の時間遅延させた信号を引くことで、正確なトリガタイミングを生成する回路です。
 τは遅延時間、Ratioは引き算する信号の比率です。特に変更する必要はないでしょう。

Cszapp_6

●Trapezoid Shaper回路

Trapezoidal Shaperと書かれた四角をクリックすると、台形波形整形回路の設定ができます。

Cszapp_7

kは整形後の台形波形の立ち上がり時間、lは台形の頂上の時間、Gainは整形回路のゲイン、τは入力波形の減衰の時定数です。デフォルトの値は、テスト波形に対して最適な値となるように設定さています。

Cszapp_8

●トリガ・ゲートジェネレータ

トリガ・ゲート・ジェネレータは、トリガが入ってから一定時間のゲート信号を生成します。

Cszapp_9

生成されたトリガ信号は、後段のピークホールド回路やリニアゲート回路のゲート信号として使用できます。トリガソースには、同じチャネルのCFD出力、LLD/ULD出力、外部入力が選択できます。

Cszapp_10_2

トリガは、遅延や幅を自由に設定できます。

Cszapp_11

 

このように、波形処理回路の各部をWindowsからコントロールできるようにしました。

 

放射線信号処理回路(DSP)をFPGAに入れた

2016.6.7

放射線の計測で使うTFA、CFD、Shaper、LLD/ULD、PeakHold、LinearGateなどをデジタル化してFPGAに入れた。Windowsの画面から必要なコンポーネントをポチポチ選んですぐ使える感じになってきた。

 

AD7960で作ったAD変換回路のノイズ特性

2016.6.6

AD7960を使って18bitのA/D変換回路を作っています。

Np1084pcb

このボードは18bitのADC(AD7960)が8ch付いていて、フロントエンドはAD8253になっていて、ゲインがx1,x10,x100,x1000で可変であるというものです。

したがって、μVオーダーの微弱な信号から4V程度の信号までなんでも変換できてしまうというものです。

AD7960というのは、1ch入り5Mサンプリングの18bit ADCです。出力はシリアルで出てくるので、最高速度で動かした場合、ディジタル部は250MHz程度のクロックとなるのでLVDSの差動出力になっています。

Ad7960_0

こういうADCを使ったシステムを作るときに、キャプチャソフトまで作ると大変なのですが、先日のテクニックによって、ADCの出力値をFPGA内でデコードして、内蔵ロジアナでキャプチャしてExcelに落とせるようになりました。

入力をGNDに落としてADCの値を見てみます。

Ad7960_1

VREF=4.096Vなので、1LSB≒31μVとなります。

ヒストグラムにしてみると、

Ad7960_2

うーん。サンプル数が少ないので何ともいえませんが、目分量で±3LSB(≒100μV)程度揺らいでいるとみるべきでしょうか。

AD7960のデータシートによれば、この程度のゆらぎはあるようです。

Ad7960_3

データシートによれば、Transition Noiseは1.1LSBとなっています。どの部分が1.1LSBなのかはわかりませんが。

このADCのシステムでノイズを発生させているものは、

  • ADCそれ自身 (35μV)
  • 抵抗(1kΩ)の熱雑音。BW=10MHzとして。13μV。
  • フロントエンドOPアンプ。AD8253・・・10nV/√Hz。BW=10MHzとして、31μV。
  • ADCドライブ用OPアンプ。THS4130・・・1.3nV/√Hz。BW=10MHzとして、4μV。

これらの二乗の和の平方根を取ってみると、√(35^2+13^2+31^2+4^2)≒48。

ノイズは約48μVとなります。

ヒストグラムを見る限り、理論値の2倍程度出ていることになります。

このノイズはどこから来るのか、長いデバッグが始まりそうです。

 

DACを作ったら発振した件

2016.6.2

AD9717(125MHz,14bit,2ch)とOPアンプをいくつか使ってDACを作っています。

しかし、見事に発振してしまっています。

Scope_0

 

回路的にはこんな感じです。

Ad9717_2

AD9717は差動出力で電流出力タイプのDACなので、完全差動アンプのTHS4521を使ってシングルエンドの信号に直し、それをADA4899で増幅してSMAコネクタから出そうというものです。

しかし、見事に発振。

上のオシロの波形を見るとわかると思いますが、電圧が高くなってくると発振し、急激に電圧が変化するところでリンギングを生じています。

sun

前者の発振・・つまり、電圧に依存する発振については差動増幅器からADA4899へとつながる部分の抵抗値を変えることで収まりました。

後者の発振、電圧の変化でリンギング、については、同軸ケーブルをつないだことによる容量性負荷の発振と思われます。

ケーブルへの出力段にADA4899に選んだことが間違いだったのか。

(使用した実績のあるTHS4041CDにしておけばよかった・・・)

超低ノイズで帯域が広いから選んだのですが、まさか、ここで発振するとは。

コンデンサを切って貼っての戦いが始まります。

 

 

 


© 2017 TokushuDenshiKairo Inc. All rights reserved