====== NIM プリスケーラ ====== 周波数 X Hz の入力信号を整数分の 1 倍した X/M Hz の出力信号を作る回路のことをプリスケーラと呼びます。 ここでは、ファームウェアにプリスケーラ回路を実装して、NIM 入力信号から整数分の 1 倍周期の出力信号を作ります。 下の図はインプットを黄色として、その 1/10 のアウトプットを水色で示したものです。 \\ {{testbench:hakei_prescaler.png?600}} ===== コード ===== 必要なコードはここにあります。[[https://svnweb.cern.ch/cern/wsvn/atlas-tkunigo/tkunigo/software/testbench/Bit3/pt6/FPGA/PT6_NIMPrescaler/?|svn url]] もしくは svn からとってくるには svn co svn+ssh://$USERNAME@svn.cern.ch/reps/atlas-tkunigo/tkunigo/software/testbench/Bit3/pt6/FPGA/PT6_NIMPrescaler 北棟160にある Windows では右クリックから SvnCheckout を選び、 URL of respository のところに、上の svn+ssh;~~ 以降を入れるとファイルを取って来れます。 ここに含まれるファイルの拡張子の意味は * *.v \\ Verilog-HDL のコード * *.ucf \\ User Constraints File ユーザー制約ファイル。FPGA のピンに名前をつけたり、クロックやタイミングについて記述する。 * *.xise \\ Xilinx ISE のプロジェクトファイル。編集・コンパイルをする時はここから始める。 * *.bit \\ 実際に FPGA に書き込むビットストリーム。( bit file ) となっています。 具体的に以下で見ていきましょう。 ==== ucf ファイル ==== FPGA は名前にも入っているように Ball Grid Aray で2次元にピンが配置されています。 X 軸に数字 (1, 2, 3, ...)、Y 軸にアルファベット (A, B, C, ...) を割り振ることで2次元に配置されたピンを識別しています。 例えば一番左上のピンが A1 で、その1つ右のピンは A2, その1つ下は B1 といった具合です。(番号の振り方は FPGA の種類によって違うかもしれません) それぞれのピンにどういった線が繋がっているかは回路図を見ることでわかりますが、その全てを覚えておくなんてことは出来ないのでピンに名前をつけて扱います。 実際の ucf ファイルを見てみると NET "ALL_RESET_B" LOC = G20 | IOSTANDARD = LVCMOS33; という記述があります。 この1行では G20 というピンにはリセット信号が繋がっているので ALL_RESET_B という名前をつけています。 また、接続されている信号準位が LVCMOS33 という準位であることも書いてあります。 この ucf ファイルを読み込むことで、今後 ALL_RESET_B と書けば、ISE は FPGA の G20 ピンだと理解します。 今回使用する Spartan6 FPGA は ISE というデザインツールによって処理します。 ISE ではユーザー制約をここで説明した ucf ファイルで記述します。 Xilinx の最新シリーズにあたる 7 シリーズからは Vivado というデザインツールに移行しており、この Vivado ではユーザー制約は xdc という形式に移行しています。 記述方法は異なりますが、基本的には同じような内容を記述するものです。 ==== Verilog-HDL コード ==== Verilog-HDL ではモジュールを処理単位としてロジックを構築します。 なので、各モジュールを一つのブロックだと思うことでブロック図を簡単に書くことが出来ます。 今回のロジックは main モジュールで Prescaler モジュールを一つ読み出す (インスタンスを作る) という簡単なものです。 以下にブロック図を示します。\\ {{testbench:block_prescaler.png?600}} \\ main モジュールは FPGA_GCLK, ALL_RESET_B をインプット (赤) として、Prescaler モジュールを呼び出します。 この際パラメータ (灰) として fact という値も与えています。 これらのインプットを元に Prescaler モジュールは処理を行い、EXT_DATA をアウトプット (青) します。 Prescaler モジュールの中身を見てみましょう。 実際に処理を行っているのはこの部分です。 always @(posedge INPUT or negedge RESET) begin if (!RESET) begin counter <= 4'b0; end else begin counter <= counter + 4'b1; if( counter == FACTOR ) begin OUTPUT <= 1'b1; counter <= 4'b0; end else begin OUTPUT <= 1'b0; end end end INPUT の立ち上がり、または RESET の立ち下がり ( 通常の信号は 1 が ON, 0 が OFF と理解しますが、この RESET 信号は activ low、つまり 0 が ON、1 が OFF の信号です ) になれば次の処理を行う。 * RESETが 0 \\ counter に対して 0 を代入する。 * それ以外 \\ counter に + 1 して、次の判定をする。 * counter が FACTOR と一致 \\ OUTPUT を 1 にして、counter を 0 に初期化。 * それ以外 \\ OUTPUT を 0 にする。 今回は1つのモジュールだけで処理を行っていますが、通常のロジックは複数のモジュールで実装されています。 最初はとっつきにくく見えますが、ですがブロック図を書いてみて、それぞれのモジュールを読み取ればどんな処理かは理解可能です。 ==== ISE でのコンパイル ==== 最後に ISE でコンパイルして、bit file を作ってみましょう。 xise ファイルから ISE を開くと次のような画面になります。 \\ {{testbench:ise.png?600}} \\ コードを編集をするには左上の窓からファイルを選択して、右の窓で編集します。 そして、編集が出来れば左下の窓から Generate Programming File を選択します。 コードに Error が含まれていなければ bit file が作れます。 実際には Synthesize -> Implementation という2つのステップを踏んでから bit file 生成の処理が行われます。それぞれのステップで Warning, Error が表示されるので、表示された場合はコードを見直しましょう ==== ファームウェアのダウンロード ==== ファームウェアをダウンロードします。 ダウンロード方法にはいくつかありますが、ここでは JTAG ケーブルを使用した方法を用います。 下に示した JTAG ケーブルを用いて、PC の USB ポートと FPGA の JTAG コネクターを接続します。 \\ {{testbench:jtag_usb.jpg?600}} \\ その後、ISE iMPACT を開きます。 表示されるままに Initialize Chain という操作を行うと、下図のような画面になります。 左下の窓、もしくは右クリックから Program という操作を実行するとファームウェアがダウンロードされます。 \\ {{testbench:iMPACT.png?600}} ===== CPLD ===== CPLDもFPGAと同じ再書き込み可能な集積回路ですが、FPGAほど集積度は高くありません。 その代わり、FPGAが揮発性(電源を切ると内部の情報が失われる)デバイスであるのに対し、CPLDは不揮発性であるため、内部の情報を保持することができます。 PT6のボードにはFPGAとCPLDが両方搭載されているため、CPLDに対してもデータを書き込む必要があります。 必要なコードはここにあります。[[https://svnweb.cern.ch/cern/wsvn/atlas-tkunigo/tkunigo/software/testbench/Bit3/pt6/CPLD/modified/?|svn url]] もしくは svn からとってくるには svn co svn+ssh://$USERNAME@svn.cern.ch/reps/atlas-tkunigo/tkunigo/software/testbench/Bit3/pt6/CPLD/modified CPLD FPGAの場合と同じように、PT6_CPLD を ISE で開いてコンパイルし、書き込み可能なファイルを作ります。(今回は .jed ファイル) PC の USB ポートと CPLD の JTAG コネクターを接続し、ISE iMPACT を開いてさっき作ったファイルを選んで Program をしてください。 これでCPLDにも必要なデータが書き込まれ、入力した NIM 信号に対して 1/10 のアウトプットが見られるはずです。 ===== 練習 ===== 今までの説明と Verilog-HDL の解説サイトなどを利用すれば NIM インプットに対して任意の処理をかけて、NIM アウトプットを作れます。 コードを編集して遊んでみましょう。 ( e.g. x MHz のクロックをインプットにして、x/2, x/3 MHz のクロックを作るロジックとか )