Avalon® Memory-Mapped Interfacesを理解する For beginners

# 概要

この記事はIntel®のFPGA(Field Programmable Gate Array)開発を始めたばかりの初心者の方、特に[Intel® Quartus® Prime Software](https://www.intel.com/content/www/us/en/products/details/fpga/development-tools/quartus-prime.html)で[Plarform Designer](https://www.intel.com/content/www/us/en/software/programmable/quartus-prime/qts-platform-designer.html)を触り始めたけど、IP(Intellectual property)のインターフェースがよくわからないという方向けに書かれた記事です。Avalon® Interfaceにはいくつか種類があるのですが([こちら](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/introduction-to-the-interface-specifications.html)を参照してください)、中でも使用頻度の高いAvalon® Memory-Mapped Interfacesについて紹介し、信号の検証に使用する[Avalon Verification IP Suite](https://www.intel.com/content/www/us/en/docs/programmable/683439/20-4/introduction-to-avalon-verification-ip-suite.html)についても説明したいと思います。特にAvalon® Verification IP Suiteについては[こちら](https://www.intel.com/content/www/us/en/docs/programmable/683439/20-4/avalon-mm-verilog-hdl-and-vhdl-testbenches.html)の**Avalon Verification IP Suite Design Files**をクリックするとテストベンチがダウンロードできるので、実際に動かします。なおテストベンチはIntel® Quartus® Prime Software Standard Editionがあれば動かせるので、実機は必要ありません。

※データのやりとりにおいては、Master⇔Slaveという関係がよく出てきます。この記事では「誰が信号を送っているのか」という説明においては主語をくどいほど明記します。

## Avalon® Interfaceとは?

Avalon® InterfaceとはIPのポート、つまりクロックやデータ等、信号の「出入り口」のことです。ただし出入り口と言ってもただ物理的な出入り口があるだけでなく、そこには様々なルールが存在します。
例えば空港を考えてみると、そこには物理的に乗り降りする搭乗ゲートがあるだけではなく、どの便がどのゲートに繋がっているか、何時何分に飛行機が出発or到着するか、など事前に様々な「ルール」が決められているはずです。
その決まり事に従わないと飛行機は空港を行き来することはできません。同じことはAvalon® Interfaceにも当てはまり、これは物理的な「出入口」を意味すると同時に、その出入口を利用するためのプロトコル(ルール)も定義されているのです。
Avalon® Interfaceにはどのようなプロトコルが存在するでしょうか。具体的には

- [Avalon® Clock and Reset Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/clock-and-reset-interfaces.html)
- [Avalon® Memory-Mapped Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/introduction-to-memory-mapped-interfaces.html)
- [Avalon® Interrupt Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/interrupt-interfaces.html)
- [Avalon® Streaming Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/streaming-interfaces.html)
- [Avalon® Streaming Credit Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/streaming-credit-interfaces.html)
- [Avalon® Conduit Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/conduit-interfaces.html)
- [Avalon® Tristate Conduit Interface](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/tristate-conduit-interface.html)

などがあります。今回は、中でも使用頻度の高い[Avalon® Memory-Mapped Interfaces](https://www.intel.com/content/www/us/en/docs/programmable/683091/20-1/introduction-to-memory-mapped-interfaces.html)について詳しく見てみましょう。

## Avalon® Memory-Mapped Interfacesとは?

Avalon® Memory-Mapped Interfacesは、先ほど述べたように物理的な出入口とプロトコル(ルール)の両方を指しています。主に以下のIPの出入り口として使用されます。

- Microprocessors
- Memories
- UARTs
- DMAs
- Timers

SDRAMのようなメモリについて考えてみるとわかりやすいのですが、Masterのreadやwrite信号に応じてデータを双方向にやり取りするためのプロトコルと言えるでしょう。
以下ではAvalon® Memory-Mapped Interfacesにおいてよく使われる信号をテーブルにまとめています。

<table>
    <tr>
        <th>Signal Role</th>
        <th>Width</th>
        <th>Direction</th>
        <th>Required</th>
        <th>Desctiption</th>
    </tr>
    <tr>
        <td>address</td>
        <td>1-64</td>
        <td>Master → Slave</td>
        <td>No</td>
        <td>データのアドレス指定に使用される信号です。当然のことですが、Masterがread信号をassert(信号をactiveにすること。deassertはその逆でinactiveにすること。)している場合、アドレスを指定しないとどのデータをreadしたいのかSlaveは判断できませんし、Masterがwrite信号をassertしている場合、アドレスを指定しないとどこにデータを書き込みたいのかSlaveは判断できません。ただし、Slave側で用意されているレジスターが1つしかない場合に限り、アドレス指定は不要です。</td>
    </tr>
    <tr>
        <td>byteenable</td>
        <td>2, 4, 8, 16, 32, 64, 128</td>
        <td>Master → Slave</td>
        <td>No</td>
        <td>readdata, writedataのうちどのバイトを読み書きしたいのかを指定するための信号です。例えば、32ビットデータに対してbyteenable=0b0001であれば下位8bitを読み書きし、byteenable=0b1000であれば上位8bitが読み書きされます。特にSlave側がバイト単位のアクセスに対応している場合はbyteenable信号を用いて送受信を行います。対応していない周辺機器を使用する場合は、マニュアルでアクセス方法を確認してください。</td>
    </tr>
    <tr>
        <td>read</td>
        <td>1</td>
        <td>Master → Slave</td>
        <td>No</td>
        <td>Masterがreadをassertすれば、SlaveはMasterがデータの読み込みをしたいと判断できます。また、writeのみを行いたい場合read信号は必要ありません。</td>
    </tr>
    <tr>
        <td>readdata</td>
        <td>2, 4, 8, 16, 32, 64, 128, 256, 512, 1024</td>
        <td>Slave → Master</td>
        <td>No</td>
        <td>Masterからのread信号を受け取った後、Slave → Masterに送信されるデータ。read信号を使用しない場合、readdata信号も必要ありません。</td>
    </tr>
    <tr>
        <td>response[1:0]</td>
        <td>2</td>
        <td>Slave → Master</td>
        <td>No</td>
        <td>Slaveが送信する受信ステータス信号。やり取りが正常に行われたかというステータスを知らせるために使用されます。</td>
    </tr>
    <tr>
        <td>write</td>
        <td>1</td>
        <td>Master → Slave</td>
        <td>No</td>
        <td>Masterがwriteをassertすれば、SlaveはMasterがデータを書き込みたいと判断できます。また、readのみを行いたい場合write信号は必要ありません。</td>
    </tr>
    <tr>
        <td>writedata</td>
        <td>2, 4, 8, 16, 32, 64, 128, 256, 512, 1024</td>
        <td>Master → Slave</td>
        <td>No</td>
        <td>Masterがwrite信号と同時に送信する、Slaveへ書き込むデータ。write信号を使用しない場合、writedata信号も必要ありません。</td>
    </tr>
</table>

## Avalon® Memory-Mapped Interfacesの信号パターン

以下では[マニュアル](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjcn4SO_fX7AhXcm9gFHbT3Ar8QFnoECBcQAQ&url=https%3A%2F%2Fwww.intel.com%2Fcontent%2Fdam%2Fwww%2Fprogrammable%2Fus%2Fen%2Fpdfs%2Fliterature%2Fmanual%2Fmnl_avalon_spec.pdf&usg=AOvVaw0KRH8z7jYf5e4cCs0C4vul)に記載されているいくつかの信号パターンについて見ていきましょう。各サイクル付近において信号がどういう状態なのか説明します。

### 3.5.1. Typical Read and Write Transfers

典型的なread, write信号のやり取りです。各信号をMasterとSlaveのどちらがassertしているのか意識して見てください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/931cadf2-1def-0ecd-7ff6-69f584700f2d.png)
画像引用元: [Avalon® Interface Specifications](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjcn4SO_fX7AhXcm9gFHbT3Ar8QFnoECBcQAQ&url=https%3A%2F%2Fwww.intel.com%2Fcontent%2Fdam%2Fwww%2Fprogrammable%2Fus%2Fen%2Fpdfs%2Fliterature%2Fmanual%2Fmnl_avalon_spec.pdf&usg=AOvVaw0KRH8z7jYf5e4cCs0C4vul) Figure 7. Read and Write Transfers with Waitrequest
1. address, byteenable, readがMasterによりassertされる。ただし、Slaveがwaitrequestをassertするので、Slave→Masterへのデータ送信は行われない。
2. Slaveがwaitrequestをassertしているので、データの送信は行われない。
3. Slaveがwaitrequestをdeassertし、Slave→Masterへデータの送信が行われる。
4. Master側でreaddataの受信が完了する。
5. readもwriteもdeassertされているため、データの送受信は行われない。
6. Master側はwritedataを送り続けているが、waitrequestがassertされているためSlave側はまだデータを受け取らない。
7. waitrequestがdeassertされているため、SlaveはMasterからのaddress, byteenable, write, writedataを受け取る。

※信号が灰色になっている部分は不定値です。
※信号はクロックの立ち上がりに対して少し遅れて出力されます。例えば1番目のクロックの立ち上がり付近に着目すると、Masterはaddress, byteenable, read信号をassertしますが、これらはクロックの立ち上がりから少し遅れてassertされていることがわかります。これは[D flip-flop](https://en.wikipedia.org/wiki/Flip-flop_(electronics)#D_flip-flop)から出力が得られるのに少し時間がかかるためです。

### 3.5.5.1. Write Bursts

Burstモードで書き込みを行う際の信号例です。ちなみにBurstモードとは連続してデータを送るモードのことです。最初にアドレスとburstcount(何個連続でデータを受信or送信するか)を指定すると、アドレスの位置からデータをburstcount個だけ受信or送信することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/733abe0e-b927-910a-3c55-a1943841ac2e.png)
画像引用元: [Avalon® Interface Specifications](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjcn4SO_fX7AhXcm9gFHbT3Ar8QFnoECBcQAQ&url=https%3A%2F%2Fwww.intel.com%2Fcontent%2Fdam%2Fwww%2Fprogrammable%2Fus%2Fen%2Fpdfs%2Fliterature%2Fmanual%2Fmnl_avalon_spec.pdf&usg=AOvVaw0KRH8z7jYf5e4cCs0C4vul) Figure 14. Write Burst with constantBurstBehavior Set to False for Master and Slave
1. address, beginbursttransfer, burstcount, write, writedataがMasterによりassertされる。ただし、Slaveがwaitrequestをassertするので、Slave→Masterへのデータ送信は行われない。
2. Slaveはwaitrequestをassertするので、Slaveはwritedataの受信を完了しない。
3. Slaveはwaitrequestをdeassertしているので、Slaveはデータ1を受信する。
4. Slaveはwaitrequestをdeassertしているので、Slaveはデータ2を受信する。
5. Masterはwriteをdeassertしているので、Slaveはwritedataを受信しない。
6. Slaveはwaitrequestをdeassertしているので、Slaveはデータ3を受信する。
7. Slaveはwaitrequestをassertするので、Slaveはwritedataを受信しない。
8. Slaveはwaitrequestをdeassertしているので、Slaveはデータ4を受信する。


### Avalon® Verification IP Suite Design Exampleを動かしてみよう

[Avalon® Verification IP Suite](https://www.intel.com/content/www/us/en/support/programmable/support-resources/design-examples/horizontal/exm-avalon-verification-ip.html)とはAvalon® Interfacesの信号を観察するためのシミュレーションライブラリです。以下の図にあるように、Test Moduleをユーザー側で定義し、どのようなシミュレーションを行うか指定できます。[Design Exampleのダウンロード](#Design-Exampleのダウンロード)で使用するDesign Exampleでは、SystemVerilogを使用してUser Test Benchが記述されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/aa7c4cfe-5390-3f25-3133-456a1342d992.png)
画像引用元: [Avalon® Verification IP Suite Design Example](https://www.intel.com/content/www/us/en/support/programmable/support-resources/design-examples/horizontal/exm-avalon-verification-ip.html) Figure 1. Verification testbench using Avalon Verification IP Suite.

#### 必要環境
Windows 10 21H2
Intel® Quartus® Prime Software Standard Edition

#### Design Exampleのダウンロード
[こちら](https://www.intel.com/content/www/us/en/support/programmable/support-resources/design-examples/horizontal/exm-avalon-verification-ip.html)の**ug_avalon_verification.zip**をクリックして、Design Exampleをダウンロードしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/142f3eaa-e2d4-851b-4574-eacdada1fbc4.png)

※<b>Avalon Verification IP Suite User Guide (PDF)</b>はマニュアルです。

ダウンロードが完了したらzipを解凍し、中に
- avlmm_1x1_verilog.zip
- avlmm_1x1_vhdl.zip
- avlmm_2x2_verilog.zip
- avlmm_2x2_vhdl.zip
- ug_avalon_verification.zip

が含まれることを確認してください。
今回使用するのは、**avlmm_1x1_verilog.zip** のみですので、こちらも解凍してください。
これで準備は完了です。

#### Intel® Quartus® Prime Softwareの操作

Intel® Quartus® Prime Softwareを開き、File>Openをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/9c66a89f-b508-2c21-3196-19aca4afa82f.png)

File Explorerが起動するので、avlmm_1x1_verilog/avlm_avls_1x1.qsysを選択してOpenをクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/e37c9825-2e06-92da-84d7-98937f30143e.png)

Platform Designerと以下のWindowが起動します。IPのバージョンに関するWarningが出ていますが、特に問題ないのでCloseをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/4813287f-4be4-3f4a-b30e-3dd9210db55d.png)

IPをupgradeしたことを知らせる以下のwindowも表示されますので、Closeをクリックして閉じてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/97f3eef6-dcc8-bf9b-84ee-ce601839011a.png)

Platform Designer右下のGenerate HDL...をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/fcd97968-38e2-b782-1abb-24f6d3241d6a.png)

Generationのwindowが表示されるので、以下の画像のように設定し、Generateをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/1b00cbf0-3510-7f52-04db-40c2e25bf2f0.png)

Save System Completedのwindowが表示されるので、Closeをクリックして閉じてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/cc23fc58-b0de-2c49-2fa7-fd7771012249.png)

Generate Completedのwindowが表示されるので、Closeをクリックして閉じてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/17cd77eb-c300-5fdc-2c96-4519c05709e8.png)

Windowsのスタートメニューから、Questaを起動してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/f0b09d0b-4520-8337-d33b-7e7e24c5cec4.png)

以下がQuestaの起動画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/b2561112-bdef-b339-8e8d-e2b5d9a9e4c6.png)

Transcriptからavlmm_1x1_verilogの場所に移動し、
```
do run_simulation.tcl
```
を実行してください。以下の画像のように、avlmm_1x1_verilogの中にはrun_simulation.tclが含まれているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/8e3c6eff-5e8c-810d-67b9-da0c61b71ca8.png)

以下のようなシミュレーション結果が表示されることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/ddfb66c4-27ca-7113-efdf-528ddd773869.png)

キーボードのiでzoom inができ、oでzoom outができます。波形が捉えづらい場合は適当な大きさにズームして見るとよいです。
左側の灰色のpaneのavm_write信号とavm_read信号(水色の四角)に着目すると
1. masterがwrite信号をassert (no burst)
2. masterがread信号をassert (no burst)
3. masterがwrite信号をassert (burst)
4. masterがread信号をassert (burst)

のように、赤い4つの四角のパートで分けられることがわかります。

Avalon® memory-mapped interfaceが[3.5.1. Typical Read and Write Transfers](#351-Typical-Read-and-Write-Transfers)や[3.5.5.1. Write Bursts](#3.5.5.1.-Write-Bursts)で説明したような動作をしているか、シミュレーション結果をよく観察してみましょう。以下では、4つの赤いブロックの各パートについて解説します。

### masterがwrite信号をassert (no burst) 開始位置=1.45ns
最初に`avm_write`がno burstでassertされるタイミングを見てみましょう。
<!-- 毎回同じか確認したい、データも含めて -->

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/543ff6a3-9c06-0762-bf48-00dee4091e5b.png)

- cycle0: Masterはavm_address, avm_burstcount, avm_write, avm_writedata, avm_byteenableをassertします。MasterはSlaveがwritedataを受信することを期待します。少し遅れて(これはMasterが上記の信号をSlaveに送信するのと、Slaveから信号が出てくるのに遅延が生じるからです)Slaveがwaitrequestをassertします。
- cycle1: waitrequestがassertされているので、SlaveはMasterからのデータを受信完了しません。
- cycle2: ここでSlaveがwaitrequestをdeassertします。その他信号は一定です。
- cycle3: waitrequestはdeassertされているので、ようやくSlaveはMasterからのデータを受信します。

### masterがread信号をassert (no burst) 開始位置=2.35ns

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/381d3bd4-493e-bb75-c827-bac62fcd33ed.png)

- cycle0: Masterはavm_address, avm_burstcount, avm_write, avm_writedata, avm_byteenableをassertします。MasterはSlaveがwritedataを受信することを期待します。
- cycle1: Slaveはwaitrequestをassertしていないので、SlaveはMasterからのデータを受信します。
- cycle2: Masterはavm_address, avm_burstcount, avm_write, avm_writedata, avm_byteenableをassertします。MasterはSlaveがwritedataを受信することを期待します。
- cycle3: Slaveはwaitrequestをassertしていないので、SlaveはMasterからのデータを受信します。同時に、Masterは次のデータを送信するために、新しいaddressとwritedataをassertします。
- cycle4: Slaveはwaitrequestをassertしていないので、SlaveはMasterからのデータを受信します。

### masterがwrite信号をassert (burst) 開始位置=7.25ns

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/4837959c-fd67-9e40-0734-cf5dfd08bc51.png)

- cycle0: Masterはavm_address, avm_burstcount, avm_read, avm_byteenableをassertします。MasterはSlaveがreaddataを送信することを期待します。また、少し遅れてSlaveがwaitrequestをassertします。
- cycle1: waitrequestがassertされているので、SlaveはMasterからのデータを受信完了しません。
- cycle2: waitrequestがassertされているので、SlaveはMasterからのデータを受信完了しません。Slaveはwaitrequestをdeassertします。
- cycle3: waitrequestがdeassertされているので、SlaveはMasterからavm_address, avm_burstcount, avm_read, avm_byteenableを受信します。
- cycle4: MasterもSlaveも何も信号を出していません。
- cycle5: cycle0にてMasterがSlaveに要求したデータがMasterに届きます。


### masterがread信号をassert (burst) 開始位置=32.85ns

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944815/182badb8-c3f8-950d-501d-26edd4607262.png)

急に見るべきcycleが増えましたが、辛抱して以下のフローを確認してください。

- cycle0: Masterはavm_address, avm_burstcount, avm_read, avm_byteenableをassertします。MasterはSlaveがreaddataを送信することを期待します。<b>burstcount=3であることに着目してください。</b>また、少し遅れてSlaveがwaitrequestをassertします。
- cycle1: waitrequestがassertされているので、SlaveはMasterからのデータを受信完了しません。Slaveはwaitrequestをdeassertします。
- cycle2: waitrequestがdeassertされているので、SlaveはMasterからavm_address, avm_burstcount, avm_read, avm_byteenableを受信します。
- cycle3: Masterはavm_address, avm_burstcount, avm_read, avm_byteenableをassertします。MasterはSlaveがreaddataを送信することを期待します。少し遅れてSlaveがwaitrequestをassertします。cycle0にてMasterがSlaveに要求したデータ1がMasterに届きます。
- cycle4: waitrequestがdeassertされているので、SlaveはMasterからavm_address, avm_burstcount, avm_read, avm_byteenableを受信します。
- cycle5: MasterもSlaveも何も信号を出していません。
- cycle6: cycle0にてMasterがSlaveに要求したデータ2がMasterに届きます。
- cycle7: MasterもSlaveも何も信号を出していません。
- cycle8: MasterもSlaveも何も信号を出していません。
- cycle9: MasterもSlaveも何も信号を出していません。
- cycle10: Masterはavm_address, avm_burstcount, avm_read, avm_byteenableをassertします。MasterはSlaveがreaddataを送信することを期待します。また、cycle0にてMasterがSlaveに要求したデータ3がMasterに届きます。これにより、cycle0にてMasterがSlaveに要求したデータが全てSlaveからMasterに送信されたことになります。



## まとめ

さて、いかがだったでしょうか。シミュレーション結果から、Avalon® memory-mapped interfaceの動作が理解できたのではないかなと思います。
忙しいAさんと、忙しいBさんがコミュニケーションを取るためにはルール(プロトコル)が必要ということですね。IPにも同じことが当てはまり、コミュニケーションはルール化され、忙しい時には「ちょっと後にして」という信号(waitrequest)を出したり、メッセージを受け取りたい(read)のか送りたい(write)のか、などルールを理解することはとっても大事ということです。

## Notices & Disclaimers

Intel technologies may require enabled hardware, software or service activation.
© Intel Corporation. Intel, the Intel logo, and other Intel marks are trademarks of Intel Corporation or its subsidiaries. Other names and brands may be claimed as the property of others.
https://edc.intel.com/content/www/us/en/products/performance/benchmarks/overview/