* AMT-VME [#qff10614] Atlas Muon TDC として開発されたチップを VMEのボードとして実装したものが、AMT-VMEです。 - 制作者、KEKの[[新井氏のページ>http://research.kek.jp/people/araiy/indexj.html]] -- [[AMT chip のページ>http://research.kek.jp/group/atlas/tdc/amt3/index.html]] --- [[AMT-3 chip のマニュアル>http://research.kek.jp/group/atlas/tdc/amt3/AMT3manual_034.pdf]] -- [[AMT-VMEのページ>http://research.kek.jp/group/atlas/tdc/AMT-VME/]] * High rate 環境下で使用する場合の問題 [#f81ce552] AMT-VME ボードは、チャンネル単価が約5000円とこの手のモジュールとしては安価なものです。 そのため、うちの研究室でも多数購入して使用しています。 通常の使用ではあまり顕著では無かったのですが、common stop で高レート環境下で使用すると TDC が想定されない値になるという現象があります。 AMT chip の制作者である新井氏相談後、ボードの制作会社である株式会社アムスクの協力により AMT-VME ボードを制御している DSP 及びCPLD のプログラムを入手できました。 実験データでのTDC分布及び、プログラムの解析の結果分かった事と対策を以下に記します。 ** 現象 [#zcb3b835] *** NKS2実験での測定条件 [#y1871935] 我々は、NKS2実験でドリフトチェンバーの時間測定のために AMT-VME ボードを使用しています。 NKS2 実験は標識化実光子ビームを用いたハドロン物理の研究を行っており、ビームレートは標識化された光子(0.8-1.1 GeV の領域)に対するのカウンターのレートで 1~3 MHz になります。 実際は、標識化されていないものが約2, 3十倍 あり、標識化ビーム 1MHzでドリフトチェンバーでの 1 チャンネル辺りのシングル・レートが平均約10kHz、最大50kHz です。 この環境下で、一台のPC辺り12枚あるいは14枚のAMT-VME ボードを読み出しています。 *** TDC 分布 [#v9c3467f] 測定するTDCのレンジは、Module Control parameter の Time range count という変数を VME 側から指定することで変更可能です。 Time range count は、12 bit の整数で、1カウント 25 ns の時間幅を持っています。 これは、AMT chip 内でのカウンターの時間幅がクロックでそろえてあるからで、40MHz クロックを使用していることによります。 NKS2 実験のシステムでは、チェンバーのシグナルが AMT-VME に入ってから、common stopが来るまで約 1 μs の遅れがありますので、Time range count は、 0x25 (= 37, 925 ns) のレンジに設定しています。 TDC の時間幅は、クロックを PLL で 1/32 にしたものを使用しています。 つまり、TDC 1 ch = 25/32 = 0.78125 ns の時間幅を持っていますので、TDC のレンジは 1200 ch 以下に収まると予想されます。 #ref(AMT-VME/AMT-VME_TDC_distribution_s.png,right,around) 測定されたデータを見てみると、0x1000辺りから 0x1FFFF までと、0xF0000辺りから 0xFFFFFまでの間にもヒットがあります。 結論からいうと、これは common stop が入った後も AMT chip が測定を続けておりそのために出てくるマイナスの値です。 AMT-VME ボードでは、入力 64 ch を 三つのAMT chip で請け負っていて(0-23, 24-47, 48-63 ch に対応、AMT0, AMT1, AMT2 と呼ばれている)、そのほかに common start/stop の時刻測定の為だけに 一つの AMT chip (AMT3 と呼ばれている)が使用されています。 ボード上の DSP プログラムは、四つの AMT chip のステータスを監視していて、AMT3 がレディーになればその時間情報を取り出し、AMT0, AMT1, AMT2 の時間情報を読んだ後に、時間差を計算しデータとして整形したあとメモリに書き込みます。 AMT chip 内での時間のカウンターは 12bit の coarse counter と 5 bit の fine counter、併せて17bit のカウンターを持っています。 一方、DSPの内部では、32bit の整数で処理をした後 20 bit の整数に整形しています。 カウンターのウインドウの位置により、17 bit のマイナスの値に成る場合と、20 bit のマイナスの値に成る場合があり、その結果として 0x1FFFF 以下と 0xFFFFF 以下の 領域二ヶ所に変な値が分布することになります。 common stop のシグナルは、AMT3 に入ると共に、CPLD で処理クロックと同期した後に各 AMT chip の trigger に入力されています。 AMT chip は、trigger にシグナルが入力されると、それまで 内部の Level 1 buffer に貯められていた hit 情報と、trigger matching を行い、条件に合った物だけが Read-out FIFO に送られます。 Matching に関するパラメータは、mask_window, search_window, matching_window の三種類があります。 この三つの変数は AMT chip の CSR レジスタで変更可能ですが、現在アムスクから出荷されているAMT-VMEボードに実装されている DSP プログラムではVME側から変更することが出来ません。 値はそれぞれ、 CSR1: mask_window = 0 (AMT0-3) CSR2: search_window =2038(AMT0-2), 2056(AMT3) CSR3: matching_window = 2030(AMT0-2), 2048(AMT3) に固定されています。 この matching_window は、trigger timing から後に開いている windows ですが、trigger timing のカウンターは、coarse counter に対して、 bounch_count_offset で指定される値分だけ遅らせられます。 AMT-VME ボードでは、bounch_count_offset は、Time range count 分だけマイナス方向にずらしてあります。 NKS2実験では、Time range count は約 1 μs ですので、そこから matching_window の時間だけ AMT chip は ヒット情報を Read-out FIFO に送ります。 つまり、common stop から約 49 μs も後の方にタイム・ウインドウが開いており、common stop 後のヒット時刻を記録し続けることになります。 これが原因となり、非常に高レートの環境下では、マイナス時刻のヒットがTDCとして出てき、イベントサイズの増加とそれ伴う DAQ 効率の低下が問題となりました。 ** 対策 [#tbbd0316] AMT-VME ボード上では、DSPとCPLDの二種類のプログラム可能なチップがあります。DSPは入力とCommon Start/Stop との時間差の計算及びデータの整形と、AMT chip の制御パラメータ(CSRレジスタ等)の値の設定を行っています。 CPLDの方は、DSPからのシグナルをクロックに同期させたあとにAMT chip に送るものと、VME bus とデータをやりとりする為のものとの二つのチップがあります。 マイナスのTDCの値が出ないようにするために思いついたのは以下のことですが、最終的には三番のものを採用しました。 + DSP プログラムの改造(1) -- マイナスのTDCに値に相当するデータが出たら捨てるように if 分を足す。 -- 値は出なくなったが、AMT から出てくるデータ量は変わらないので読み出し時間の短縮にならない。 -- この方法は得にならないのでボツ。 + Common stop が入ったあと AMT chip を止め、測定を行わないようにする -- AMT chip の Measurement Start/Stop は、DSPプログラムが Module Control Parameter の Run Status (DSP address: 0x8F82) の Bit1 を見てコントロールしている。DSPは、DSP IO の CNTRという名前のポート(0xFE00)に対して値を設定し、CPLDがその値を見て Start/Stop のシグナルを AMT chip に送るようになっている。 -- しかし、CPLDのプログラムを見てみると CNTR に Stop が設定された場合に AMT chip に Stop が送るコマンドがコメント・アウトされており、現在の実装では AMT chip の測定を止めることが出来ない。 -- 今回は、DSP プログラムの書き換えツールのみを借りており CPLD のプログラムを変更して試すことが出来なく、この案は断念。 + DSP プログラムの改造(2) -- DSP プログラムは、パラメータ設定モードと測定モードを交互に繰り返すが、最初一回だけパラメータ設定モード中で AMT chip の CSRレジスタの値を設定し chip に送っている。 -- time window に関連するパラメータをVME 側から設定できるように DSP プログラムを変更。 -- AMT chip 内で要らないデータを捨てることが出来るので、DSPでの処理時間が短縮される。 DSP用のプログラムは複数のファイルから構成されていますが、改造したのは &ref(main.c); というファイルのみです。 追加部分は 429: unsigned int *mask_win, *search_win, *match_win; 439: mask_win = (unsigned int*)0x8f91; // mask_window (12 bit) 440: search_win = (unsigned int*)0x8f93; // search_window (12 bit) 441: match_win = (unsigned int*)0x8f95; // match_window (12 bit) 501: // Tohoku Univ. version, added by M.Kaneta 502: if ( (uiRunStatus&0x0200)==0x0200 ) { 503: for (u=0;u<3;u++) { 504: amtcsr_init[u][1] = 0x0fff&(*mask_win); // mask_window 505: amtcsr_init[u][2] = 0x0fff&(*search_win); // search_window 506: amtcsr_init[u][3] = 0x0fff&(*match_win); // match_window 507: } 508: } になります。 なお、各行の最初の数字と:は行番号を示していて、実際のコード(&ref(main.c);)には書かれていません。 プログラム中の uiRunStatus という変数は、アムスク制作の User's Manual (user,s m.pdf) の22ページに記述のある RunStatus に対応します。 マニュアルの記述では、Bit0 - Bit7, Bit28 - Bit30 だけが使われています。 (注意! マニュアルには記述がありませんが、Bit8 にフラグが立つと、「連続測定モード」がテストできる用に実装されています。) オリジナルのプログラムでは使われていない Bit9 が 1 の場合のみ、三つの time window 変数に値が与えられるように実装しました。 504から506行目で、配列変数 amtcsr_init に値を代入しています。 この変数は、AMT chip の CSRレジスタの値を設定するために使われます。 一つ目の配列の添え字は AMT chip の番号、二つ目のものは CSRレジスタの番号に対応しています。 (CSRレジスタについては、"[[AMT2&3 User's Manual (V0.34, Dec. 11, 2009)>http://research.kek.jp/group/atlas/tdc/amt3/AMT3manual_034.pdf]]の p.30から"を参考にして下さい。) Module Control Parameters 等の AMT-VMEボードに関連する変数とVMEアドレスの関係は、[[別のページ>https://spreadsheets.google.com/pub?key=0AqCNir5ySiBLdEIxUUZKZkl0X0JnTzItV2tBN3gxLXc&hl=ja&output=html]]にまとめてあります。 ** パラメータの設定方法 [#ha6a8c16] NKS2実験では、SBS Technologies (Bit3) 社製 PCI-VME アダプタ (Model 618)を用いてVMEからPCでデータを読み出しています。 デバイスドライバ及びVMEデバイスへアクセスするためのライブラリは、東北大学ニュートリノ科学研究センターの[[榎本三四郎氏>http://www.awa.tohoku.ac.jp/~sanshiro/]]の開発した[[vmedrv>http://www.awa.tohoku.ac.jp/~sanshiro/kinoko/vmedrv/index.html]]と[[vmelib>http://www.awa.tohoku.ac.jp/~sanshiro/kinoko/vmedrv/vmeslib.html]]を使用しています。 ドライバとライブラリの関数の使用方法はそれぞれのリンクを参考にして下さい。 AMT-VMEボードへのパラメータの設定方法は、ソフトにより異なりますので、上記以外のドライバ・ライブラリを使用している場合適宜そのドライバに応じて変更する必要があります。 以下に、NKS2実験で用いているDAQプログラムの一部を抜粋・省略したものを載せます。 ここでは、AMT-VMEボードは5枚使用し、それぞれのVMEメモリマップの先頭のアドレスは、define で定義されている変数 AMT? で指定されています。 // 変数定義等 #include <vmeslib.h> #define AMT_ACCESS_MODE VME_A24D32 // アドレス幅 24bit, データ幅 32bit #define AMT_TRANFER_MODE VME_NORMAL // 標準モード (Programmed I/O) #define AMT_CTR_ADDRESS 0x071f00 // VME_BASE (0x060000) + 0x011F00 #define AMT_DAT_ADDRESS 0x072000 // VME_BASE (0x060000) + 0x011F00 + 0x0100 #define AMT1 0x100000 // VMEメモリマップの先頭のアドレス #define AMT2 0x200000 // ボード上のディップスイッチ(SW3, SW4)で設定 #define AMT3 0x300000 // #define AMT4 0x400000 // #define AMT5 0x500000 // #define AMT1ID 1 #define AMT2ID 2 #define AMT3ID 3 #define AMT4ID 4 #define AMT5ID 5 static int AMTList[] = { AMT1, AMT2, AMT3, AMT4, AMT5 }; static int AMTIDList[] = { AMT1ID, AMT2ID, AMT3ID, AMT4ID, AMT5ID }; static const int nAMT = sizeof(AMTList)/sizeof(int); const int* dat_base[30]; int* ctr_base[30]; #define SIZE 0x100 #define DAT_SIZE 0xc000 #define NUM_PART 0x4 // number of patition in a buffer #define MAX_NUM_DATA 0x2000 // max number of nhits in a module #define TIME_RANGE 0x25 VMEMAP* amt_ctr_map[30]; VMEMAP* amt_dat_map[30]; // AMT-VME のマッピング for(i=0; i<nAMT; i++){ // コントロール・アドレスのマッピング if((amt_ctr_map[i] = vme_mapopen(AMT_ACCESS_MODE,AMTList[i]+AMT_CTR_ADDRESS, SIZE))==NULL ){ perror("ERROR : AMT-TDC ctr mapopen()"); exit(EXIT_FAILURE); } // データ・アドレスのマッピング if((amt_dat_map[i] = vme_mapopen(AMT_ACCESS_MODE,AMTList[i]+AMT_DAT_ADDRESS, DAT_SIZE))==NULL ){ perror("ERROR : AMT-TDC dat mapopen()"); exit(EXIT_FAILURE); } // マッピングされた領域の先頭を指すポインタ ctr_base[i]=vme_mapbase(amt_ctr_map[i]); dat_base[i]=vme_mapbase(amt_dat_map[i]); } 上記のプログラムにより、Module Control Parameters の設定が、このプログラムのローカル変数 ctr_base[i] に対して行えるようになります。 各ボードに対して以下の用に設定を行います。 for(i=0; i<nAMT; i++){ *( ctr_base[i] + eRunStatus ) = 0x0000; *( ctr_base[i] + ePcount ) = 0x0000; *( ctr_base[i] + eIcount ) = 0x0000; *( ctr_base[i] + eScount ) = 0x0000; *( ctr_base[i] + eEchoPoint ) = 0x0000; *( ctr_base[i] + eAMTStatus ) = 0x0000; *( ctr_base[i] + eTimeRange ) = TIME_RANGE; *( ctr_base[i] + eModuleID ) = AMTIDList[i]; *( ctr_base[i] + eCHenable1 ) = 0xffffffff; *( ctr_base[i] + eCHenable2 ) = 0xffffffff; *( ctr_base[i] + eNumPartition ) = NUM_PART; // *( ctr_base[i] + eRunStatus ) = 0x0e; // 0000 0000 0000 1110 rising and falling // *( ctr_base[i] + eRunStatus ) = 0x06; // 0000 0000 0000 0110 rising *( ctr_base[i] + eRunStatus ) = 0x0206; // 0000 0010 0000 0110 rising and set window parameters // *( ctr_base[i] + eRunStatus ) = 0x0006; // 0000 0000 0000 0110 rising and window parameters are default *( ctr_base[i] + ePcount ) = 0x01; *( ctr_base[i] + eMaskWindow ) = 0; // *( ctr_base[i] + eSearchWindow ) = 2038; // *( ctr_base[i] + eMatchWindow ) = 2030; *( ctr_base[i] + eSearchWindow ) = TIME_RANGE + 8; // 0x25 + 8 = 37 + 8 = 45 *( ctr_base[i] + eMatchWindow ) = TIME_RANGE; // 0x25 = 37 }