無からはじめるFPGAプログラミング(2)
1 : http://d.hatena.ne.jp/w_o/20160518#1463571239
さて、PS7を置いたら、Synthesizeをしよう。Synthesizeは、ボタンをポチーとするとできる。
Synthesizeすると、netlistができる。あんまりXilinx以外は知らないのだけど、Xilinx では、複雑な演算を、FPGA内にあるprimitiveで表現できるように変換した物体のことを、netlistと呼んでる気がする。
このへんの画面で、オブジェクトを右クリックして、Schematicを選ぶと、画像でnetlistが見られる。
とりあえず今は、「PS7を置け」というHDLを書いたので、そのとおりPS7が置いてあるはず。
これを、Generate Bitstreamすると、何もしないbitfileが完成する(project_dir/なんとか.runs/impl_1/design_1_wrapper.bit とかにある) 。cat bitfile > /dev/xdevcfg とかすると、何も起こらないことが確認できるはずだ(DDR3とかはn/cになってるけど動く。よくわからないが固定ピンなので大丈夫なのかもしれない)。
さて、Zynq には、GPIO が付いている。これは、ARMと同じように、固定機能として入っていて、FPGAが何もしないように設定されていても使える。GPIOというのは、まあ、ただの1bit入出力なのだけど(何の機能も無い1bitをGeneral Purposeと呼ぶ姿勢を見習っていきたい)、LEDやボタン等は、1bit取れればいいので、このGPIOを使ってアクセスすることが多い。
http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf#381
GPIO の使いかたは、このへんにある。が、別にこれを読まなくてもLinux なら以下のようにして使える。
$ sudo sh -c 'echo 913 > /sys/class/gpio/export' # 7番目のGPIOを見えるようにする $ ls /sys/class/gpio/gpio913/ active_low device/ direction edge power/ subsystem/ uevent value $ sudo sh -c 'echo out > /sys/class/gpio/gpio913/direction' # out 方向に設定 $ sudo sh -c 'echo 1 > /sys/class/gpio/gpio913/value' # Hi 出力 $ sudo sh -c 'echo 0 > /sys/class/gpio/gpio913/value' # Lo 出力
これをすると、Parallella ならLチカができるはずだ。Lチカできたので満足した(完)
終わりではない。
913が何かというと、Zynqはカーネルコンフィグで、GPIO1024個と指定されてるけど、実際は118個しかなくて、何故か後ろから番号詰められるので 1024-118 = 906 が GPIO0 番に対応してるらしい。
GPIO 7 番が、LEDに接続されているので、906+7 = 913番目が、LEDと対応するGPIOになる。なので、それをHiにしたりLoにしたりすると、Lチカができる。(ZedboardもLEDが7番に繋がってるので同じようにできると思う)
parallella-utils には、これを簡単に使うスクリプトが入っている https://github.com/parallella/parallella-utils/blob/master/gpio (というかこれ見て上の機能知った)
しかし、残念ながら、このピンは固定なので、ARMからLチカできても、FPGAからはLチカはできない。悲しいなぁ…
(ここまでFPGA関係ないです)
で、このGPIOだが、外部I/Oに54本、 FPGA側に64本出ていて、FPGAで出したbitをARMから読んだり、ARMから出したbitをFPGAから読んだりできるようになっている。
module design_1_wrapper () ; wire [63:0] gpio_out; wire [63:0] gpio_in; assign gpio_in[0] = gpio_out[1]; PS7 ps7 ( .EMIOGPIOO (gpio_out), .EMIOGPIOI (gpio_in) ); endmodule
昨日書いた、design_1_wrapper.v をこんな感じに変更する。ps7 の EMIOGPIOO と、EMIOGPIOI を引き出して、そのうちの、EMIOGPIOO[1] と、EMIOGPIOI[0] を接続する。これでsynthesize,implementation,Generate Bitstream して、できたbitfileを、/dev/xdevcfgに書く。
EMIOGPIO[0] は、GPIO54 と対応している。EMIOGPIO[0] を in に、EMIOGPIO[1] を out に設定して、EMIOGPIO[1] を 0 にしたり、1にしたりすると、あわせて EMIOGPIO[0] が 0 になったり 1 になったりするのが確認できるはず。
$ # (上のparallella-utils に入ってるgpioスクリプトを使ってます) $ ./gpio ex 960 961 # EMIOGPIO[0] = GPIO54 = 906+54 = 960 Exporting 960 Exporting 961 $ ./gpio in 960 # EMIOGPIO[0] は in $ ./gpio out 961 # EMIOGPIO[1] は out $ ./gpio 0 961 # EMIOGPIO[1] に Lo $ ./gpio ls 960 # EMIOGPIO[0] が Lo gpio960: in 0 $ ./gpio 1 961 # EMIOGPIO[1] に Hi $ ./gpio ls 960 # EMIOGPIO[0] が Hi gpio960: in 1
これで、1bitデバッグが可能になったはず。
netlist を見ると、がんばって EMIOGPIOO と EMIOGPIOI を接続しているのがわかるはず。
配置後の配線を見ても、すっごいがんばって EMIOGPIOO と EMIOGPIOI を接続しているのがわかるね…
(飽きてきたので続かないかも)
書きたかった一覧
- IBUF, OBUF
- クロック
- CLB
- AXI
なんか、HDLだけじゃなくて、primitiveの使いかたも覚えないといけないよねー的な話を書きたかった。あとTclがクソだ…というのは最初に書いたしいいか…