メモ置き場

メモ置き場です.開発したものや調べたことについて書きます.

[tex: ]

ZynqとWebsocketでリアルタイムデータ処理システムを構築

ZynqとWebsocketを使って,FPGA上のデータをウェブブラウザからリアルタイムに見られるようなシステムを作った.

youtu.be

この記事では全体の概要だけ説明して,細かい実装については別の記事にしていこうと思う.

全体図

こんな感じになっている.
f:id:okchan08:20190509215924p:plain

PL部分で生成したデータをDDRへ転送し,PSからデータを読み出しWebcosketとしてデータを送信する.送信されたデータはクライアントでグラフに描写している.

FPGAでの処理

FPGAでは,AXI4-Streamで出力されるデータをDMA転送している.FIFOとAXI DataMoverを使ってDMA転送を実現している.上記動画では,カウントアップデータを送信している.
初めは1→2→3→…と増え,その後1→3→5→…,1→4→7→…のように増分が1ずつ増えるようなカウンタになっている.グラフでは描写のたびにデータの傾きが変わっていることがわかる.

DMA転送に使っているAXI DataMoverのマニュアルはこちらから*1.AXI4-Stream形式でデータを出力できるIPを繋ぐことで様々な処理の結果をブラウザ上で見られるようになっている.現状デザインでは,常にDMAが発行されているわけではなく,PSからの制御によってトランザクションを開始している.DMA制御はAXI4-Liteで行う.FPGAからこの制御信号を発行する機能を取り付ければ,自動でDMAが行われているデザインに変更できると思う.

Linuxでの処理

PSではUbuntu Linuxが動いている.Linux上では

  • DMAの開始とデータの取り込み
  • DMAデータの送信を行うwebsocketサーバ
  • HTTPサーバ

の処理を行なっている.

DMA制御は,AXI4-Liteのアドレスに適切なコマンドを送信することで行う.DMAされたデータはDDR上に一時保存されるため,PSのプログラムからアクセスして読み出すことができる.データ読み出しのためのデバイスドライバは作成しておらず.直接/dev/memから物理アドレスにアクセスすることでデータ読み出しを行う.

読みだしたデータはWebsocketでクライアントにバイナリデータとして送信される.Websocketサーバにはlibwebsocketsを用いC言語で実装した.libwebsocketsのドキュメントはここ.
libwebsockets.org lightweight and flexible C networking library

lws_writeという関数が用意されていて,これを使うことで通信が確立した相手にデータを送ることができる.


HTTPサーバにはApacheを使っている.Apacheでは/var/www/html/にあるhtmlファイルをブラウザに送信する.このディレクトリをドキュメントルートと呼ぶらしい.ドキュメントルート直下にlibwebsocketsというディレクトリを作成し,グラフ表示を行うhtmlファイルとjavascriptファイルを配置してある.

ブラウザ上での処理

ブラウザから"ZynqのIPアドレス" + /libwebsockets にアクセスすると,準備したhtmlファイルが読み込まれ,ブラウザにグラフが表示される.ファイルは上で述べたようにZynqの/var/www/html/libwebsocketsディレクトリに配置してある.htmlのファイル名をindex.htmlにしておくと,ブラウザでディレクトリにアクセスした場合自動でhtmlファイルを読みだしてくれる.

ブラウザではjavascriptを使って,websocketのデータ受信とグラフの描写を行っている.グラフ描写にはChart.jsを使っている.
JavascriptのWebsocketでは,Websocketサーバーからデータを受信したときに実行する関数を次のように設定できる.

var ws = new WebSocket("ws://" + DEFAULT_DOMAIN + ":" + DEFAULT_PORT, "example-protocol");
ws.onmessage = function(e){ // eはwebsocketから送られてきたデータ
    // do something
}

onmessageで,受信データのデコードとグラフの描写を行なっている.

注意すべき点

上の動画のグラフは,FPGA上で生成されたデータを「余すところなく全て」表示しているわけではない.グラフの描写およびDMAで転送されたデータの取得は50msecごとに行なっている.また,DMA転送の開始はPS側から制御しており,PL側ではPSからの信号(AXI4-Liteで受け取る)に応じてDMAを開始している.あくまでもPSの処理に同期したDMA→Websocket通信→グラフ描写であり,FPGAのデータを本当にリアルタイムでモニターしているわけではない.

このためには,FPGA上でデータをDMA転送するシグナルを発行し,割り込みによってPSからデータを取得しグラフの描写を行う,といったトリガーのような仕組みを作る必要がある.
ちなみにこの場合でも,FPGA上で生成される全てのデータをグラフに描写するというのは非現実的だと思う.FPGAのデータは100MHzくらいで生成される一方で,ネットワークでデータを送信しブラウザで描写するにはミリ秒オーダーでの処理が必要だからである.