VME プロトコル
プリスケーラーロジックを実装して遊んでいると、いちいちコンパイルし直さずにパラメータを変更したいと思うようになると思います。 その要求を VME を用いて実現します。 書き込みなどの制御信号は CPLD で判定しているので、気になる人は CPLD の Verilog コードと VME インターフェースの説明をよんでください。 VME バス規格自体の詳しい説明は避けます。 いくつかの FPGA 制御信号とアドレス・データに絞って考えることにします。
Read タイミング
VME からしたら通信を行っている相手が FPGA ということは知りようがありません。
FPGA/CPLD も含めて、一般にメモリに対する書き込みのタイミングを下図に示します。
この例では 0x1234 というアドレスから読みだしたデータが 0xabcd であったことを意味しています。
以下で具体的に説明します。
最初に読み出したいアドレス (ここでは 0x1234) を VME から制御します。 そのアドレスのデータを読み出すために CPLD から制御信号を操作していきます。 まず Chip Enable をアサート(有効に)します。 VME バス上に複数の FPGA がのっていることも多くあります。 それらの FPGA が同時に反応してしまうと、バス内で信号の衝突が起きます。 それを防ぐために、どのチップとやりとりをするのか選択するのが CE の主な役割です。
Chip Enable がアサートされた状態になると、次に Output Enable をアサートします。 Read/Write のどっちの操作を行うのかを指定するために Output Enable/Write Enable があります。 今は Read をしたいので、 Output Enable をアサートしましょう。 これらの操作を行うことで、読みたいアドレスに対応するレジスタ(値を保持する箱)に入っているデータを読み出せます。 読み出しが終われば、CPLD から配られる CE, OE を元に戻すことを忘れないようにしましょう。
ここと次の Write タイミングで説明するのは一般のメモリに対して成り立つことです。 ピンの名前が違ったり、より高度な操作を行うために追加の信号が必要だったりすることがありますが、基本を理解しておくことが重要です。
Write タイミング
Write も、似たようなものです。同じようにタイミングチャートを載せます。
さきほどの説明でだいたい同じように理解できますよね。
チップを選択し、 Write Enable 状態にします。
その上で、書き込みたいアドレスに対してデータを書き込みます。
繰り返し言っておきますが、FPGA に対して読み書き操作を行う説明ですが、この説明は多くのメモリに共通する内容です。 見慣れない種類のメモリ ( SPI, BPI, … ) で合ったとしても、この基本は変わりません。 チップの説明書(データシート)から細かい変更点を読み取るだけで、対応が可能です。
VME を用いた読み書き
さて、では実際に VME から読み書きしていきましょう。 VME のコントローラとしては本当に実験で使用する時は Single Board Computer を使用するかもしれませんが、実験室などでテストを行う際には SBS 社の Bit3 を使用することが多いようです。 Bit3 を使用するためのドライバーについては vmedrv を使用していること前提で話を進めていきます。
特定のボードを操作するには専用のソフトウェアを書いたりするのですが、ここでは vmedrv に付属している vmeget/vmeput を使用して読み書きしてみましょう。 私が管理している PC であれば vmedrv はここにあります。
$ cd /local/vmedrv
この下に version ごとに directory を作っておくようにしています。
まずは、ある 0x12345678 というアドレスの値を読んでみましょう。
$ cd /local/vmedrv/ver121 $ ./vmeget /dev/vmedrv32d32 0x12345678
というようにします。 今回の場合 アドレス 32 bit、データ 32 bit のボードにアクセスするつもりで vmedrv(a)32d32 というデバイスを選択しています。 その次に続く引数が読みに行くアドレスです。 簡単ですね。
同じように 0x12345678 に対して 0xabcdabcd という値を書き込むには次のようにします。
$ ./vmeput /dev/vmedrv32d32 0x12345678 0xabcdabcd
今は説明のために適当なアドレスを指定していますが、これを実際に読み書きしたいアドレスに置き換えれば実際に操作することができます。
PT6 の VME 操作
では、実際に先ほど作った Prescaler ロジックのファクターを VME から操作してみましょう。
先ほどのファームウェアでは Prescaler ロジック一つでしたが、そこに VME Read/Write 操作を司る VMEEncoder モジュールというのを追加してみましょう。 追加後のブロック図は次のような感じです。
VMEEncoder モジュールを追加し、VMEEncoder モジュールと Prescaler ロジックとの間で fact という値を受渡しています。 こうすることで、いちいち bitfile を作り直す必要がなくなり、VME から ( 実際に操作するのは PC ) Prescale factor を変更することが可能です。 ここでは VME から操作するのは 1 つの値だけですが、通常複数(数十、数百)の値を設定出来るようなデザインが普通です。
必要なコードはここにあります。svn url もしくは svn からとってくるには
svn co svn+ssh://$USERNAME@svn.cern.ch/reps/atlas-tkunigo/tkunigo/software/testbench/Bit3/pt6/FPGA/PT6_VMEEncoder
です。
コードの基本的な見方は最初に詳しく説明したので、今は省略します。(あまりにも分からないようなら、後に追記します。) VMEEncoder モジュールでは、上で示したタイミングチャートに合わせて、VME のアドレスを見て、 Prescale factor レジスターの値の読み書きを行っています。
出来上がる bitfile を FPGA に書き込み、その後実際に fact を読み書きしてみましょう。 どこのアドレスに書き込めばいいのかを知るには PT6 のアドレス空間を知る必要があります。 下にアドレス空間の表を書いておきます。
アドレス | 31 - 20 | 19,18 | 17 - 11 | 10 | 9 - 2 | 1, 0 |
---|---|---|---|---|---|---|
FPGA | ボードアドレス | 00 | not used | 1 | offset | Byte access |
CPLD | ボードアドレス | 00 | not used | 0 | offset | Byte access |
* 実際に FPGA にやってくる ( VMEEncoder でしている )アドレスは offset 部分です。
- ボードアドレスは、同じクレート内でアドレスが被らないようにボード上の DIP SW で指定しています。
ボードアドレスを 0x0f1 だとした時、VMEEncoder モジュール内で Prescale factor に対して定めているアドレス 0xf0 にアクセスするためには 0x0f1007c0 というアドレスにアクセスすればよいことが分かります。 本当かどうか vmeget で確かめてみましょう。 正しく読めれば、初期値の 10 ( = 0xa ) が返ってきます。 その後、好きな値に書き換えて遊んでみてください。
ここまで出来れば、結構色んなことが出来るようになります。 値を自由自在に書き換えられれば、色んなボードの設定を変更することが可能です。