無からはじめる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になってるけど動く。よくわからないが固定ピンなので大丈夫なのかもしれない)。


(ここからしばらくFPGA関係無いです)

さて、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 番に対応してるらしい。

https://forums.xilinx.com/t5/Embedded-Linux/GPIO-issues-with-Linux-version-3-17-0-xilinx/td-p/560245/page/2

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がクソだ…というのは最初に書いたしいいか…