Ryuz's tech blog

FPGAなどの技術ブログ

フルロジックEther通信とボード間時計合わせ

はじめに

以前、ZynqMPでリアルタイムOSをFPGA化してみた というRTOSのスケジューリング部分をフルロジックで実装してみましたという記事を書きました。

今度は、それを複数ボード拡張することを目論んで、RTOSらしくリアルタイム保証や時計合わせを行うべく WAVESHAREのLAN8720 の互換のボードを買いあさって ZYBO に繋げて遊んでおります。いろいろと Twitter に呟いていますが、情報が拡散してきたので一度ブログにまとめておきます。

KV260 でやりたっかたのですがPMODが足りないので、暫定で 久々の ZYBO です。幸い2枚持ってましたし。

最終的な狙いどころとして、今度は通信部分もフルロジックで実装することで、

  • HPCみたいに各ノード間でマルチホップなメッセージ交換して MPI みたいなことできるようにしたい
  • HPCみたいに別ノードのメモリ空間に相互乗り入れさせたい(ccNUMA的な?)
  • RTOSらしく時間保証したい/ノード間で時計を揃えたい
  • EtherCAT みたいなリアルタイムの通信もしたい

そもそもリアルタイム保証出来ていたら計算も同期計算できるので、非同期システムと違ってハンドシェーク処理が不要になるのではないか? というのもあります。

  1. 各ボードで同じ時間にタスクが起床される
  2. 各ボードで最悪実行時間を保証した処理が終わる
  3. 時間保証されたタイムスロットで計算結果交換

という流れが容易にできそうな気がします。

これはノード間の通信遅延以下の精度で時計が揃えば基本的に成立するはずです。

加えて、プログラマブルロジック(FPGA)らしく、外部のセンサーやアクチュエータなど、入出力デバイスとのやり取りのタイミングもボード間で揃えることができるはずです。

Twitter で冗談で書いたが、ナノ秒オーダーの精度が出てくれば、LiDAR 等のように光の遅延で自己位置推定などができる可能性さえもあるかもしれません。

余談ですが、同期/非同期については、例えばロジック設計であればこの違いは明確で、同期処理では全員が処理をクロック立ち上がりに揃えることでハンドシェークが不要です。

もう少し大きな粒度のプロトコルになってくると、例えばTCP通信などは、データが届いたか? 次のデータを送って良いか? などをお互いでハンドシェークしながら通信しています。 計算タイミングの点では HPC でのクラスタ演算がスループットを出す為に演算のタイミングをある程度揃えていたはずです、一方でエッジでは、例えばROSなんかは各ノードが自分のタイミングで計算して publish できますので、非同期メッセージ通信の代表格の一つかもしれません。リアルタイムに近いエッジ分野のROSが非同期式で、スループットさえ出ればよいHPCが同期式というのもなんだか不思議な感じです。

構想

とりあえず、後半のリアルタイム保証の枠組みを先にしっかり整えた方がよさそうなのでそこから始めました。

基本的にはリング接続か直線的な接続を考えています。 リングを前提にしたいのですが KV260 が PMOD 一個しかないので仕方がないので、両対応で実装を進めています。

イデアとしては基本的には、毎周期のタイムスロット内で必ず行うリアルタイム通信と、一定頻度で入れる時計合わせ通信、残帯域でのノンリアルタイム通信用を考えています。

非リアルタイムスロットは、ある程度の頻度で時計合わせプロトコルが奪うので、時間保証されない感じになります。

タイムスロットの考え方

接続方法としては、リングと直線の2種で、それぞれリアルタイムスロットではダイレクトにパケットを一周させ(詳細仕様しりませんが EtherCAT と同じ?)ようなことをして、ノンリアルタイムスロットでは宛先付きのパケットをお隣同士で交換しながらマルチホップな通信を考えています(経路が空いていればダイレクトに送っても良い)。

接続形態

時計合わせは、基本的に往復の伝搬時間を測ってその半分を補正してやればよいはずです。

ちなみにこの辺のアイデアはすでに世の中にあるようで、 TSN(Time-Sensitive Networking) とか PTP(Precision Time Protocol) とかがそうであるようです。

そしてノード同士を接続する規格とかは CCIX とか CXL とか、これまたいっぱいあるわけですが、これらもまたリアルタイム系の規格とは別物です。

例によっていろいろと車輪の発明なのですが、これらのオープンでない規格をわざわざ調べる元気もないですし、やりたいことが全部やれないと意味が無いので、独自仕様で進めます。

今回単にFPGA同士を繋ぐ、ある程度安くて高速な回線が欲しかっただけなので、Ether が便利だったという以上でも以下でもないですし、他のシステムと繋がない限りは特になにかの標準に準拠する必要もないのかなと思います。

時計合わせとリアルタイム通信まで作ってみた

という事で、ノード間の時計合わせと、リアルタイム通信まで作ってみました。

youtu.be

時計が揃っているので、パルス幅情報をリアルタイムパケットで交換して、同じ時刻でパルスを出せば、同じ時刻に同じ幅の、つまり同じ形の波形が2つのボードから出るわけです。

Ethert のボード間通信は測ってみると 0.5us (上のお城の 2.5目盛分)ぐらいあるにもかかわらず、ちゃんと通信遅延はキャンセルして時刻が揃っています。

ぱっと見た感じ、数十ns程度の誤差範囲には収まっていそうです。 ボード間通信遅延より十分短い誤差量で時計合わせが出来ました。

おわりに

RTOSや通信をナノ秒単位の制御ができるRTLでのフルロジックで書いてしまい、高度な浮動小数点演算などはRPU(Cortex-R5) などでシンプルに書くというのは悪くないアプローチな気がしています。

この手のサイクル単位を扱うものは HLS(高位合成言語) よりも RTL 言語が向いていると思いますので、RTL学習の動機づけとなる題材としては悪くないのではないかと思いました。