Synchronizer
This content is not available in your language yet.
| 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 年しか使えないが, 事実上問題ない.
- なお, 時刻基準は 2000 年 1 月 1 日である.
- 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 ファームウェアと協調して, 以下の手順で行われる.
- CPU: 次の Sync0 信号が発火するシステム時刻
ECAT_SYNC_TIMEを読み出し, FPGA 内の BRAM に書き込む.- ただしこの時, 現在時刻が
ECAT_SYNC_TIMEに近すぎる場合は, いったん待機する. これにより, 次のUPDATEフラグの書き込み/読み出しがECAT_SYNC_TIMEより前に行われることを保証する.
- ただしこの時, 現在時刻が
- CPU:
UPDATEフラグを FPGA 内の BRAM に書き込む. - FPGA: 以下の計算により, 時刻単位を変換しておく.
- FPGA:
UPDATEフラグがアサートされている, かつ,ECAT_SYNCがアサートされたタイミングで, 単位変換済みのECAT_SYNC_TIMEをSYS_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 から観測できる.
補正タイミングの分散
Section titled “補正タイミングの分散”補正を Sync0 信号の発火直後に集中して行うと, Sync0 の発火周期に由来する周期的なノイズが生じる.
Sync0 の発火周期を
(とはいえ実際にはこのノイズはほとんど聞こえない)