VALID 信号と READY 信号によるハンドシェイクの注意点

# はじめに


FPGA/ASICなどの論理回路では、モジュール間で各種情報を転送する方法として VALID 信号と READY 信号によるハンドシェイクがよくつかわれます。有名なところでは ARM 社が規定した標準バスプロトコル仕様の AXI4 / AXI4-Stream があります。また、データーフローやパイプラインの各ステージのデータの受け渡しにも使われることがあります。


![Fig.1 VALID 信号と READY 信号によるモジュール間転送](https://qiita-image-store.s3.amazonaws.com/0/24981/cbb33084-aea2-42ab-7b27-f41bb163a2d2.jpeg  "Fig.1 VALID 信号と READY 信号によるモジュール間転送")
Fig.1 VALID 信号と READY 信号によるモジュール間転送

<br />

この記事では VALID 信号と READY 信号によるハンドシェイク方法に関して、基本的な説明と、実は似てるようで微妙に異なるため取り扱いに注意が必要な３種類のプロトコルに関して説明します。




# VALID信号とREADY信号によるハンドシェイク



## VALID 信号と READY 信号によるハンドシェイクの基本規則


* 出力側は転送したい情報とともにVALID信号 をHigh レベルにします。
* 入力側は受け入れ可能ならば READY 信号を High レベルにします。
* VALID 信号と READY 信号が共に High レベルになった時、情報の転送が完了します。
* ~~出力側は一旦 VALID 信号を High レベルにしたら、情報の転送が完了するまで VALID 信号を Low レベルにしてはいけません。~~(削除、補足参照)
* ~~出力側は一旦 VALID 信号を High レベルにしたら、情報の転送が完了するまで情報の値を変更してはいけません。~~(削除、補足参照)
* ~~入力側は一旦 READY 信号を High レベルにしたら、情報の転送が完了するまで READY 信号を Low レベルにしてはいけません。~~(削除、補足参照)


![Fig.2 VALID 信号と READY 信号によるハンドシェイク](https://qiita-image-store.s3.amazonaws.com/0/24981/46009275-1a47-e87b-c725-ce12d8386c48.jpeg "Fig.2 VALID 信号と READY 信号によるハンドシェイク")

Fig.2 VALID 信号と READY 信号によるハンドシェイク

<br />




## VALID 信号と READY 信号の依存関係に関する追加規則


一般的には上記の規則以外に下記のような VALID 信号と READY 信号の依存関係に関する規則が追加されます。この追加規則は３種類あります。この記事では便宜上  VALID-and-READY、VALID-then-READY、 READY-then-VALID としますが、これは筆者が勝手に作った言葉で、ほかに良い言葉があるかもしれません。もし知っている方がいらっしゃればコメントください。




### ・VALID-and-READY プロトコル

* 出力側は VALID 信号を High レベルにするために READY 信号が High レベルになるのを待ってはなりません。
* 入力側は READY 信号を High レベルにするために VALID 信号が High レベルになるのを待ってはなりません。

このプロトコルはモジュールの設計がけっこう難しくなります。しかしこのプロトコルでモジュールを作っておくと、次の２種類のプロトコルを持つモジュールにも接続できるので便利です。


### ・VALID-then-READY プロトコル

* 出力側は VALID 信号を High レベルにするために READY 信号が High レベルになるのを待ってはなりません。
* 入力側は READY 信号を High レベルにするために VALID 信号が High レベルになるのを待ってもかまいません。

このプロトコルは AXI4 や AXI4-Stream で採用されています。特に多対1で調停用の信号を別途用意する必要がなくなるので、インターコネクトに向いています。


### ・READY-then-VALID プロトコル

* 出力側は VALID 信号を High レベルにするために READY 信号が High レベルになるのを待ってもかまいません。
* 入力側は READY 信号を High レベルにするために VALID 信号が High レベルになるのを待ってはなりません。

このプロトコルは Altera 社の Avalon-ST で採用されています。


# VALID 信号と READY 信号の依存関係に関する注意点


前節でVALID 信号と READY 信号の依存関係の違いによる３種類のプロトコルの説明をしましたが、このように３種類の異なる規則を定める必要があるのかというと、定めていないと問題があるからです。ここでは起こりうる問題の説明をします。

また、「出力側は VALID 信号を High レベルにするために READY 信号が High レベルになるのを待ってもかまわないし、また、入力側は READY 信号を High レベルにするために VALID 信号が High レベルになるのを待ってもかまわない。」という規則が成り立たない理由でもあります。


## 依存関係で問題が発生する可能性のある組み合わせ


次のような組み合わせの場合、問題が発生する可能性があります。

* 出力側が READY-then-VALID プロトコル(VALID 信号を High レベルにするために READY 信号が High レベルになるのを待ってもかまわない)に基づいている。
* 入力側が VALID-then-READY プロトコル(READY 信号を High レベルにするために VALID 信号が High レベルになるのを待ってもかまわない)に基づいている。


## デッドロック問題


* 出力側が READY-then-VALID プロトコルに基づいている場合、通常は VALID 信号を Low レベルに保ちつつ READY 信号が High レベルになってから VALID 信号を High レベルにするように設計されていることがあります。
* 入力側が VALID-then-READY プロトコルに基づいている場合、通常は READY 信号を Low レベルに保ちつつ VALID 信号が High レベルになってから READY 信号を High レベルにするように設計されていることがあります。



上記のような出力側と入力側の組み合わせの場合、出力側も入力側も自分からは High レベルにすることなく相手からの 信号が High レベルになるのをひたすら待ち続ける状態(いわゆるデッドロック状態)になります。




## コンビネーションループ問題


* 出力側が READY-then-VALID プロトコルに基づいている場合、出力側がミーリマシンで構成されていて READY 信号がレジスタを通さずに VALID 信号の生成に使われている場合があります。
* 入力側が VALID-then-READY プロトコルに基づいている場合、入力側がミーリマシンで構成されていて VALID 信号がレジスタを通さずに READY 信号の生成に使われている場合があります。



上記のような出力側と入力側の組み合わせの場合、次の図のようにコンビネーションループが発生します。コンビネーションループは論理合成出来ないだけでなく、シミュレーション時に無限ループに陥ることがあります。



![Fig.3 VALID 信号と READY 信号のコンビネーションループ](https://qiita-image-store.s3.amazonaws.com/0/24981/ad0b2fa3-2635-6169-663b-0596d99dd2b3.jpeg "Fig.3 VALID 信号と READY 信号のコンビネーションループ")

Fig.3 VALID 信号と READY 信号のコンビネーションループ

<br />




# まとめ


VALID 信号と READY 信号によるハンドシェイクには、ここで紹介したように、実は微妙に異なるプロトコルがあります。そしてこのプロトコルの違いに気が付かずに安易に違うモジュールを接続すると問題が発生する場合があります。

実は恥ずかしい話ですが、筆者はVALID-then-READY プロトコルの AXI4-Stream 入力モジュールに READY-then-VALID プロトコルの Avalon-ST 出力モジュールを何も考えずにそのまま接続して大失敗した経験があります。

また、モジュールを設計している最中に、いつのまにか VALID-then-READY プロトコルと READY-then-VALID プロトコルを混在させてしまったこともあります。

自分が設計しているモジュールがどのプロトコルに基づいて設計しているのか、相手のモジュールがどのプロトコルに基づいているのかを常に意識しておくことが重要です。


# 補足


当初の記事では、「VALID 信号と READY 信号によるハンドシェイクの基本規則」に次の３つの規則を含めていました。



* 出力側は一旦 VALID 信号を High レベルにしたら、情報の転送が完了するまで VALID 信号を Low レベルにしてはいけません。
* 出力側は一旦 VALID 信号を High レベルにしたら、情報の転送が完了するまで情報の値を変更してはいけません。
* 入力側は一旦 READY 信号を High レベルにしたら、情報の転送が完了するまで READY 信号を Low レベルにしてはいけません。



しかし、必ずしも常にこれらの規則が適応されるわけでは無いようです。



例えばコメントで kino2718 さんが指摘されたように、AXI4や AXI4-Stream には「入力側が READY 信号を High にしている時、出力側が VALID 信号を High にする前ならば、 入力側はREADY 信号を Low にしても構わない」という規則がありました。(筆者は恥ずかしながら、この規則を失念していました。)

他にも READY-then-VALID プロトコルならば「出力側がVALID 信号を High にしている時、入力側が READY 信号を High にする前ならば、出力側が VALID 信号を Low にしても構わない」という規則も有り得ます。

また、「出力側は VALID 信号を High レベルにしている間に情報の値を変更しても構わない」という規則も有り得るでしょう。


これらの３つの規則は、今回の「VALID 信号と READY 信号によるハンドシェイクの注意点」の説明にはあまり関連が無いため、本記事から削除するとともに、参考としてこちらの補足に載せました。