コンテンツにスキップ

Synchronizer

Name In/Out Width Description
CLK In 1 メインクロック
SYNC_SETTINGS In -
├─ UPDATE In 1 同期フラグ
├─ ECAT_SYNC_TIME In 64 同期 EtherCAT 時刻
└─ ECAT_SYNC_CYCLE In 32 Sync0 の発火周期 (SYS_TIME 単位)
ECAT_SYNC In 1 EtherCAT Sync0 信号
SYS_TIME Out 57 システム時刻
SYNC Out 1 Sync0 検出フラグ
SKIP_ONE_ASSERT Out 1 1 飛ばしアサート
SYNC_TIME_DIFF Out 14 補正残量 (符号あり)

Synchronizer はすべてのデバイスで同期した時刻 SYS_TIME を生成するモジュールである. 超音波出力, Modulation, Emission 等はすべてこの SYS_TIME を時刻の基準にしている. したがって, それらも必然的にすべてのデバイスで同期する.

このモジュールの動作を理解するためには, 以下の事柄を理解しておく必要がある.

  • EtherCAT のシステム時刻は 単位の データであり, これはすべての EtherCAT スレーブで同期している.
    • なお, 時刻基準は 2000 年 1 月 1 日である. 単位の なので約 600 年しか使えないが, 事実上問題ない.
  • FPGA からは EtherCAT スレーブ (CPU ボード) のレジスタに書き込まれているシステム時刻に直接アクセスできない.
  • EtherCAT スレーブは一定の周期で Sync0 信号 (ECAT_SYNC) をアサートできる. この信号の発火はシステム時刻を参照しているので, すべてのデバイスで同期している.
  • Sync0 信号が発火する周期は の整数倍である.
  • この周期はマスタが ESC の DC レジスタ 0x09A0 に設定する. CPU ファームウェアはこれを読み出し, SYS_TIME の単位に変換して ECAT_SYNC_CYCLE として FPGA に渡す (詳細は CPU ファームウェア を参照).

なお, SYS_TIME は EtherCAT のシステム時刻に同期しているが, その単位は で, となっている.

SYS_TIME の初回の時刻同期は CPU ファームウェアと協調して, 以下の手順で行われる.

  1. CPU: 次の Sync0 信号が発火するシステム時刻 ECAT_SYNC_TIME を読み出し, FPGA 内の BRAM に書き込む.
    • ただしこの時, 現在時刻が ECAT_SYNC_TIME に近すぎる場合は, いったん待機する. これにより, 次の UPDATE フラグの書き込み/読み出しが ECAT_SYNC_TIME より前に行われることを保証する.
  2. CPU: UPDATE フラグを FPGA 内の BRAM に書き込む.
  3. FPGA: 以下の計算により, 時刻単位を変換しておく.
  4. FPGA: UPDATE フラグがアサートされている, かつ, ECAT_SYNC がアサートされたタイミングで, 単位変換済みの ECAT_SYNC_TIMESYS_TIME にセットする.

以上により, FPGA 内部の SYS_TIME の時刻が EtherCAT のシステム時刻に同期する. 単位変換は ec_time_to_sys_time サブモジュールが行う.

あとは, SYS_TIME をメインクロックでカウントアップすればいい. しかし, 実際には FPGA のクロックを生成する水晶振動子には個体差があるため, SYS_TIME は徐々にずれていってしまう. 定期的に上記と同様のことを行って補正してもいいが, それは大変なので, Sync0 信号が周期的かつ同期的に発火するという性質を用いた別の補正方法を採用している.

Sync0 信号が発火した際, SYS_TIME は前回 Sync0 信号が発火したときの値に, Sync0 の発火周期を足した値になっているはずである. この周期は ECAT_SYNC_CYCLE として CPU から与えられているので, Sync0 が発火するたびに次に期待される時刻を

と更新すればよい. Sync0 信号が発火した際に, この本来あるべき値と実際の SYS_TIME の差を取れば, 補正すべき量が求まる.

SYS_TIME の補正は, SYS_TIME が基準より進んでいる場合 (即ち, 水晶振動子の周波数が基準より高い場合) は SYS_TIME のインクリメントを止め, SYS_TIME が遅れている場合 (即ち, 水晶振動子の周波数が基準より低い場合) は SYS_TIME することにより実行する. そのため, SYS_TIME は逆戻りすることはないが, 一つ飛ばしでカウントアップされる可能性がある. 一つ飛ばしが発生した際は SKIP_ONE_ASSERT をアサートする.

補正の残量は SYNC_TIME_DIFF として出力され, デバッグ用に GPIO Output から観測できる.

補正を Sync0 信号の発火直後に集中して行うと, Sync0 の発火周期に由来する周期的なノイズが生じる. Sync0 の発火周期を とすると, 補正の集中により生じるノイズの周波数は である. 特によく使われる あたりの周波数はヒトの聴覚が比較的敏感な周波数であるため, 補正タイミングを疑似乱数を用いて分散している.

(とはいえ実際にはこのノイズはほとんど聞こえない)