AMT-VME

Atlas Muon TDC として開発されたチップを VMEのボードとして実装したものが、AMT-VMEです。

High rate 環境下で使用する場合の問題

AMT-VME ボードは、チャンネル単価が約5000円とこの手のモジュールとしては安価なものです。 そのため、うちの研究室でも多数購入して使用しています。

通常の使用ではあまり顕著ではありませんが、common stop モードの測定で高レート環境で使用すると、TDC が想定されない値になるという現象があります。 原因の理解と対策のため、AMT chip の制作者である新井氏相談後、ボードの制作会社である株式会社アムスクの協力により AMT-VME ボードを制御している DSP 及びCPLD のプログラムを入手できました。 また、DSPプログラムの開発環境およびフラッシュメモリにプログラムを書き込むソフト・ハードを一式借り受けることが出来ました。 実験データでのTDC分布及び、プログラムの解析の結果分かった事とDSPプログラムの書き換えによる対策を以下に記します。

内容

現象

NKS2実験での測定条件

我々は、NKS2実験でドリフトチェンバーの時間測定のために AMT-VME ボードを使用しています。 NKS2 実験は標識化実光子ビームを用いたハドロン物理の研究を行っており、ビームレートは標識化された光子(0.8-1.1 GeV の領域)に対するのカウンターのレートで 1~3 MHz になります。 実際は、標識化されていないものが約2, 3十倍 あり、標識化ビーム 1MHzでドリフトチェンバーでの 1 チャンネルあたりのシングル・レートが平均約10kHz、最大50kHz です。 この環境下で、一台のPCあたり12枚あるいは14枚のAMT-VME ボードを読み出しています。

TDC 分布

AMT-VME_TDC_distribution_s.png

測定するTDCのレンジは、Module Control parameter の Time range count という変数を VME 側から指定することで変更可能です。 VMEメモリと Module Control parameters の対応はマニュアルにも載っていますが、自分でまとめたものを以下のリンクにおいています。

なお、AMT-VME ボード付属の CD-ROM に複数のマニュアルが入っていますが、この文章で単にマニュアルと言った場合は、ファイル名: AMT-VME_English_manual.pdf, Rev.1.0 (2006/08/08) のものを指します。

Time range count は、12 bit の整数で、1カウント 25 ns の時間幅を持っています。 これは、AMT chip 内でのカウンターの時間幅がクロックでそろえてあるからで、40MHz クロックを使用していることによります。 NKS2 実験のシステムでは、チェンバーのシグナルが AMT-VME に入ってから、common stopが来るまで約 μs の遅れがありますので、Time range count は、 0x25 (= 37, 925 ns) のレンジに設定しています。 TDC の時間幅は、クロックを PLL で 1/32 にしたものを使用しています。 つまり、TDC 1 ch = 25/32 = 0.78125 ns の時間幅を持っていますので、TDC のレンジは 1200 ch 以下に収まると予想されます。

測定されたデータを見てみると、0x10000辺りから 0x1FFFF までと、0xF0000辺りから 0xFFFFFまでの間にもヒットがあります。 結論からいうと、これは common stop が入った後も AMT chip が測定を続けておりそのために出てくるマイナスの値です。

AMT_data_flow_s.png

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 以下の 領域二ヶ所に変な値が分布することになります。

イベント・マッチングと count offset, time window が common stop モードの測定でどのように働いているかは、以下のリンクを見て下さい。

Block_Diagram_of_the_AMT-3_s.png

Common stop のシグナルは、AMT3 に入ります。 同時に CPLD に入り内部でクロックと同期した後、各 AMT chip の trigger に入力されています。 以下、Trigger mode で AMT-VME ボードを使用しているとします。 AMT chip は、trigger にシグナルが入力されると、それまで 内部の Level 1 buffer に貯められていた hit 情報と、trigger matching を行い、条件に合った物だけが Read-out FIFO に送られます。

右に示したのは、AMT-3 User's Manual の p.6 にある、AMT chip のブロック・ダイアグラムです。 (大きな図は、こちらのリンクから) チップひとつ当たり 24 ch の入力がありますが、それぞれのチャンネルが 4 words のバッファをもっています。 その情報が、Level 1 buffer (256 words) に送られ、Trigger matching を行ったあと、64 words の Read-out Buffer に送られる流れを示しています。

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 で指定される値分だけ遅らせることが出来ます。 Common stop mode で使用する場合に、bounch_count_offset は、Time range count 分だけマイナス方向にずらしてあります。

NKS2実験では、Time range count は約 1 μs ですので、そこから matching_window の時間内に入ったヒットだけ L1 buffer から Read-out FIFO に送られます。 つまり、common stop から約 50 μs も後の方にタイム・ウインドウが開いており、common stop 後のヒット時刻を記録し続けることになります。 これが原因となり、非常に高レートの環境下ではマイナス時刻のヒットを大量に読み出さなければならず、イベントサイズの増加とそれ伴う DAQ 効率の低下が問題となりました。

対策

ボード制御プログラムの改造

AMT-VME ボード上では、DSPとCPLDの二種類のプログラム可能なチップがあります。DSPは入力とCommon Start/Stop との時間差の計算及びデータの整形と、AMT chip の制御パラメータ(CSRレジスタ等)の値の設定を行っています。 CPLDの方は、DSPからのシグナルをクロックに同期させたあとにAMT chip に送るものと、VME bus とデータをやりとりする為のものとの二つのチップがあります。

マイナスのTDCの値が出ないようにするために、以下の三つのことを考えました。 最終的に採用したのは三番目のものです。

  1. DSP プログラムの改造(1)
    • マイナスのTDCに値に相当するデータが出たら捨てるように if 分を足す。
    • 値は出なくなったが、AMT から出てくるデータ量は変わらないので読み出し時間の短縮にならない。
      • DSP で 1 hit 処理するのに約 5 μs かかる。
    • この方法は得にならないのでボツ。
  2. 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 のプログラムを変更して試すことが出来なく、この案は断念。
  3. DSP プログラムの改造(2)
    • DSP プログラムは、パラメータ設定モードと測定モードを交互に繰り返すが、最初一回だけパラメータ設定モード中で AMT chip の CSRレジスタの値を設定し chip に送っている。
    • Time window に関連するパラメータをVME 側から設定できるように DSP プログラムを変更。
    • Time window を調整することで、Trigger matching により AMT chip 内で要らないデータを捨てることが出来るので、DSP での処理時間が短縮される。
      • Trigger matching にかかる時間は、1 hit あたり、1 Clock (= 25 ns)。AMT chip 内で捨てる方が、DSP で捨てるよりも遙かに短い。

DSP用のプログラムは複数のファイルから構成されていますが、改造したのは filemain.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:    }

になります。 なお、各行の最初の数字と:は行番号を示していて、実際のコード(filemain.c)には書かれていません。

プログラム中の uiRunStatus という変数は、アムスク制作の User's Manual (user,s m.pdf) の22ページに記述のある RunStatus に対応します。 マニュアルの記述では、Bit0 - Bit7, Bit28 - Bit30 だけが使われています。 (注意! マニュアルには記述がありませんが、Bit8 にフラグが立つと、「連続測定モード」がテストできる用に実装されています。連続測定モードに関する説明は、ボード同封の CD-ROM にある Rev1,1CMeasurementDescription.pdf に記述があります。) オリジナルのプログラムでは使われていない 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)の p.30から"を参考にして下さい。)

Module Control Parameters 等の AMT-VMEボードに関連する変数とVMEアドレスの関係は、別のページにまとめてあります。

パラメータの設定方法

NKS2実験では、SBS Technologies (Bit3) 社製 PCI-VME アダプタ (Model 618)を用いてVMEからPCでデータを読み出しています。 デバイスドライバ及びVMEデバイスへアクセスするためのライブラリは、東北大学ニュートリノ科学研究センターの榎本三四郎氏の開発したvmedrvとvmeslibを使用しています。 ドライバとライブラリの関数の詳しい使用方法は以下のリンクを参考にして下さい。

AMT-VMEボードへのパラメータの設定方法は、ソフトにより異なりますので、上記以外のドライバ・ライブラリを使用している場合適宜そのドライバに応じて変更する必要があります。 以下に、NKS2実験で用いているDAQプログラムの一部を抜粋・省略したものを載せます。 AMT-VMEボードは5枚使用する場合の例で、それぞれのVMEメモリマップの先頭のアドレスは define で定義されている変数 AMT1, AMT2, ... AMT5 で指定されています。

// 変数定義等
#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  // バッファ一つ分のサイズ(バイト)
                                   //  0x3000 / NUM_PART の値を指定
#define NUM_PART           0x4     // number of patition in a buffer

#define TIME_RANGE         0x25    // 37 = 925 ns (TDC chでは 1184に相当)

VMEMAP* amt_ctr_map[30];    // VMEMAP は vmeslib で定義されている構造体 
VMEMAP* amt_dat_map[30];    // 

// Module Control Parameters の ctr_base[]に対するポインタのオフセット
// ここでは、long で定義されていますが、int でかまわない
// ctr_base[] の型が int なので、0x01 のオフセットは 4 byte に対応する
const long ePcount        = 0x00;
const long eRunStatus     = 0x01;  // Run Status
const long eTimeRange     = 0x02;  // TDCの最大値の設定
const long eModuleID      = 0x03;  // モジュールID
const long eCHenable1     = 0x04;  // チャンネルマスク
const long eCHenable2     = 0x05;  // チャンネルマスク
const long eNumPartition  = 0x06;  // 複数バッファで使用する時の分割数
const long eIcount        = 0x07;  //
const long eMaskWindow    = 0x08;  // 新たに設定, mask_window の設定
const long eSearchWindow  = 0x09;  // 新たに設定, search_window の設定
const long eMatchWindow   = 0x0a;  // 新たに設定, match_window の設定
const long eEchoPoint     = 0x38;  //
const long eAMTStatus     = 0x39;  // 
const long eScount        = 0x3a;  // 


// 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]);
}

上記のプログラムにより、VME メモリ上の 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; // Time range count: 0x25 = 37
  *( ctr_base[i] + eModuleID )  = AMTIDList[i];
  *( ctr_base[i] + eCHenable1 ) = 0xffffffff; // ch. 0-31, 全てのチャンネルを読む
  *( ctr_base[i] + eCHenable2 ) = 0xffffffff; // ch.32-63, 全てのチャンネルを読む
  *( ctr_base[i] + eNumPartition ) = NUM_PART;

// Time windows are default values
//long run_status = 0x0006;  // 0000 0000 0000 0110    rising
//long run_status = 0x000e;  // 0000 0000 0000 1110    rising and falling

// Time windows will be changed
  long run_status = 0x0206;  // 0000 0010 0000 0110    rising
//long run_status = 0x020e;  // 0000 0010 0000 1110    rising and falling
//                                     || |||| |||
//                                     || |||| ||+---- 1 = measurement start
//                                     || |||| |+----- 1 = common stop mode
//                                     || |||| |
//                                     || |||+-+------ 00 = Rising, 01 = Falling
//                                     || ||| 
//                                     || |++--------- 00 = Don't subtract offset 
//                                     || +----------- 0 = Trigger measurement 
//                                     |+------------- 0 = Not continuance mode
//                                     +-------------- 1 = Set window parameter

  *( ctr_base[i] + eRunStatus ) = run_status;

  *( ctr_base[i] + ePcount )       = 0x01;

  *( ctr_base[i] + eMaskWindow   ) = 0;                // mask_window = 0
  *( ctr_base[i] + eSearchWindow ) = TIME_RANGE + 8;   // search_window = 45
  *( ctr_base[i] + eMatchWindow  ) = TIME_RANGE;       // match_window = 37
}
// Run Status bit information (original)
// 31  |30-28|27-8|      7 |    6-5 |            4-3 |         2 |   1 | 0
//-----+-----+----+--------+--------+----------------+-----------|-----|------
// not |width|not |0:Trig  |subtract|edge detection  |0:com start|start|not
// used|     |used|1:Normal|offset  |0:rising        |1:    stop |meas.|used
//     |     |    |        |        |1:rising&falling|           |     | 
//     |     |    |        |        |2:falling       |           |     |
//     |     |    |        |        |3:rising&width  |           |     |

Run Status の 各 bit の意味については、「スプレッド・シート AMT-VME data format and parameters の Run Status 」を参考にして下さい。

この中で、Common Stop モードでの 測定領域に関するパラメータを設定しているのは、

  *( ctr_base[i] + eTimeRange ) = TIME_RANGE;          // 0x25 = 37

  *( ctr_base[i] + eMaskWindow   ) = 0;                // mask_window = 0
  *( ctr_base[i] + eSearchWindow ) = TIME_RANGE + 8;   // search_window = 45
  *( ctr_base[i] + eMatchWindow  ) = TIME_RANGE;       // match_window = 37
 

の四行です。 なお、Time Window に関するパラメータの元々の値は、DSPプログラム内部で

 mask_window = 0
 search_window = 2038
 match_window = 2030

に設定されています。

TIME_RANGE は、1 count = 25 ns の幅を持つ(クロックの幅と同じ)パラメータです。 このパラメータは、AMT chip のCSR4(reject_count_offset)と CSR6 (bunch_count_offset)に対して

CSR4 (reject_count_offset) = 0xFFF - (0x08 + TIME_RANGE)
CSR6 (bunch_count_offset) = 0xFFF - (0x04 + TIME_RANGE)

の値になるようにDSPプログラム内で設定されています。 AMT chip のマニュアルにある例では、この二つのオフセットはポジティブの値に設定されています。 これは、trigger timing が AMT chip へのヒット入力よりも先に入ることが想定されているから(コライダーの bunch crossing time など)です。

AMT-VME ボードの common stop mode の場合は、common stop のシグナルがCPLD上でクロックに同期されたあと、AMT chip に trigger signalとして入力されます。 Event matching を行う trigger がヒットより後に来ますので、マイナスの方向にオフセットを指定する必要があります。 そのため、12bit のマイナスになるように 0xFFF から TIME_RANGE の値を引いてあります。 また、それぞれ 0x08, 0x04 の さらなるオフセットがあります。 安全のため少しずらしてあるのではと想像しますが、元々の開発者がすでにアムスクを退社しているので本当の理由は分かりません。

AMT-VME ボード上での動作としては、TIME_RANGE よりも過去の時間のヒットについては、event matching をする際(trigger singalが入った後)に AMT chip 内の Level 1 (L1) buffer から 捨てられます。 つまり、この値より過去のヒットはデータとして出てきません。

mask_window は、time window に関係するパラメータなので、変更可能にしています。 元々の初期値はゼロなので、私が使用する際はゼロに設定しています。

Trigger signal がAMTに入った時点から、search_window に入っているヒットに対し、match_window 以内あるヒットだけが、L1 buffer から Read-out FIFO に送られます。 この条件に充たさないヒットは捨てられることになり、common top より後に入力に入ったヒットが L1 buffer に入っていても、Read-out FIFO に送られません。

ビームテストの結果

2010年4月26-28日に、東北大学電子光理学研究センター(旧核理研)で実際のNKS2セットアップで標識化実光子ビーム(Eγ = 0.8 - 1.2 GeV)を使用してテストを行いました。 本実験のセットアップで time window のパラメータを変えた場合、どのくらい読み出し時間のロスが減りDAQ効率が上がるかを確かめることが目的です。

パラメータは、TIME_RANGE = 0x25 = 37 に固定し

  • オリジナル
    • mask_window = 0
    • search_window = 2038
    • match_window = 2030
  • Plan A
    • mask_window = 0
    • search_window = 2038
    • match_window = TIME_RANGE
  • Plan B
    • mask_window = 0
    • search_window = TIME_RANGE + 8
    • match_window = TIME_RANGE

の三種類の組み合わせをテストしました。 Plan A は search_window はオリジナルのものと同じだが、match_window を測定したい TDC チャンネルの領域にしたもの。 つまり、マイナスの値が出ないようにしたものです。 Plan B は、search_window も狭くしたものですが、オリジナルのものが search_window を match_window より8カウント大きく取ってあるので、同様に8カウント大きくしたものです。

Trigger が AMT chip に入ったときに、search_window に入ってはないがそれより後ろに有るデータは L1 buffer に残るはずです。 それらは、次の trigger が入ったときには event rejection によって捨てられると考えられます。 Plan A と Plan B の違いは、search_window より後にあったヒットデータを、今の trigger matchingで捨てるか次の trigger matching で捨てるかの違いになります。

各パラメータの組み合わせに対して、加速器の(電子の)ビームカレントを変えたものを三つデータを取っています。 加速のビームカレントが完全に安定しているわけではないので、各データ内でも光子ビームレートに変動があります。 下に、結果の図を示しました。

daq_efficiency.png

最初の四つの図は、Trigger Accepted(1行目), DAQ efficiency(2行目) を、光子ビームレート(左側)とTrigger Requested(右側)のレートでプロットしたものです。 (なお、光子ビームレートは、標識化出来ている光子についてのものです。) 左下の図はビームレートに対する Trigger Requested のレートで、これは AMT-VMEのパラメータとは関係なく同じ曲線状に乗るものです。

図中オープン・シンボル(黒)で書かれたものが、time window のパラメータを何も変えなかった場合。 赤と青がtime windowを変えたものです。 DAQ効率が向上していることが、見て取れます。

event size と TDC 分布がどのように変わったかについては、解析結果のレポートのプレゼンテーション を見て下さい。


添付ファイル: fileNKS2_DAQ_sequence.pdf 654件 [詳細] fileNKS2_DAQ_sequence.odg 668件 [詳細] fileBlock_Diagram_of_the_AMT-3_s.png 578件 [詳細] fileBlock_Diagram_of_the_AMT-3.png 454件 [詳細] fileAMT-VME_TDC_distribution_s.png 552件 [詳細] fileAMT_data_flow_s.png 583件 [詳細] fileAMT_data_flow.png 377件 [詳細] filedaq_efficiency.png 567件 [詳細] filemain.c 1014件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-03-13 (水) 00:36:23 (125d)