この記事は高知工科大 Advent Calendar 2015の12日目の記事です。
本当はROSについて書きたかったけどやる気が起きないので、今やってることを書く。
CycloneⅤのLightweight HPS-to-FPGA BridgeにPythonでアクセスして読み書きする。
結論としてはテスト環境としては使えるかなという感じ。
#実行環境
使用しているボードはTerasicの DE1-SoCです。
BSPは公式のLinux Ubuntu Desktopを使っています。
Pythonのversionは2.7.3です
AlteraのSoCFPGAには便利なLightweight HPS-to-FPGA Bridgeというバスがあるのでそれを使います。
Lightweight HPS-to-FPGA Bridgeの詳しい資料はCyclone V Hard Processor System Technical Reference Manualとかを見てください。
マップされてる内容はCyclone V HPS Memory Mapに書いており、GPIOやUARTなどのペリフェラルのレジスタにもアクセスできるようです。
自作のipなんかは0xFF200000から0xFF3FFFFFまでの間にマップされます。(Qsys側からは0x0~0x1FFFFF)
今回は0xFF200000から0xFF200010までにipが繋がっている想定で説明します。
#/dev/mem をopen
とりあえず必要なモジュールをimportして /dev/mem を開きます。
import os
import mmap
fd = os.open("/dev/mem",os.O_RDWR | os.O_SYNC)
#mmapする
# 使用する領域(Byte)
reg_span = 0x200000
# Lightweight HPS-to-FPGA Bridge のオフセット
reg_base = 0xff200000
lw_h2f = mmap.mmap(fd ,reg_span ,mmap.MAP_SHARED,mmap.PROT_READ | mmap.PROT_WRITE,offset = reg_base)
これで Lightweight HPS-to-FPGA Bridge をmmapできます。
あとは、読み書きしたいアドレスまで移動して読み書きします。
#読み込み
lw_h2f.seek(0x0,os.SEEK_SET)
read_data1 = ord(lw_h2f.read_byte())
read_data2 = ord(lw_h2f.read_byte())
read_byte()は勝手にインクリメントされます。
インクリメントされる間隔はこの環境だと1byteでした。
mmap.read_byteは長さ1の文字列として読むので、数値として扱いたい場合は **ord()**で変換する必要があります。
#書き込み
lw_h2f.seek(0x0,os.SEEK_SET)
write_byte(chr(write_data1))
write_byte(chr(write_data2))
こちらも勝手にインクリメントされます。間隔は1byteでした。
読み込みと同じく、書き込みときは長さ1の文字列として書かねばならないので**chr()**で変換する必要があります。
#所感
Pythonはあまり書いたことがなかったが、難しくなかった。
FPGAのテスト環境としてはアリかなとは思った。
ただ、実効速度が致命的に遅いのでSDRAMをシェアして大量のデータ(画像とか)をやり取りするのには向いていない。
ペリフェラルのレジスタ的扱いするのが正解っぽい。