2021-12-02 AXI4-Stream Verification IPをMasterとして使う


### 動作環境

- Windows 10 Pro (21H1)
- Vivado 2019.1

### 関連

- 2021-12-02 AXI Verification IPを使う (AXI4LITE)
    - https://qiita.com/7of9/items/8c846c41a6337420d5c8
- PG277 AXI4-Stream Verification IP v1.0
    - https://japan.xilinx.com/support/documentation/ip_documentation/axi4stream_vip/v1_0/j_pg277-axi4stream-vip.pdf
   
### 手順の概要

1. Vivadoでプロジェクトを新規作成
1. Block Designを「sys」という名前で作成する
1. Tools > Create and Package New IP ... > Create a new AXI4 peripheral
    - InterfaceをStreamに変更
1. myip_0をBlock Designに追加する
1. AXI4-Stream Verification IPを追加する
    - INTERFACE MODEをMASTERに変更
    - TDATA WIDTH(BYTES)を4に変更
        - IPに合わせてこうした
    - 名前はaxi_vip_0にしている (System Verilogの記述に合わせて)
        - `agent = new("master vip agent", dut.sys_i.axi_vip_0.inst.IF);`だけが関係する？
1. aclk, aresetnのピンをMake Externalする (名前をこのようにする)
1. axi_vip_0とmyip_0を接続する
1. Create HDL Wrapperをする
1. Simulation Sourcesにtb.svを作成する
1. Run Simulationをする
1. 見たいピンを波形に足す
    1. m_axi_wlast, m_axi_wvalid, m_axi_wready, m_axi_wdata[31:0]
    1. s00_axi_wdata[31:0], s00_axi_rready, s00_axi_rvalid

<img width="1488" alt="image.png (54.7 kB)" src="https://img.esa.io/uploads/production/attachments/6206/2021/12/02/21741/062bc79a-0fc5-4365-8af4-ab690531ab9f.png">


### Block Design

<img width="690" alt="image.png (25.0 kB)" src="https://img.esa.io/uploads/production/attachments/6206/2021/12/02/21741/a307454f-7c3c-4cbb-b7df-865b26bbd315.png">


### テストベンチ (System Verilog)

https://qiita.com/tethys_seesaa/items/9d4c00212d9ea79b1497
の実装をベースとしてAXI4Streamに書き換えした。

```tb.sv
`timescale 1ns/1ps
//import axi_vip_v1_0_1_pkg::*;
//import axi_vip_pkg::*;
import axi4stream_vip_pkg::*;
//import sys_axi_vip_0_0_pkg::*;
import sys_axi4stream_vip_0_0_pkg::*;

module tb();

    localparam int LP_CLK_PERI = 100;
    localparam int LP_RST_PERI = 777;

    // DUT instance
    logic aresetn, aclk;
    sys_wrapper dut(.*);

    task rst_gen();
        aresetn = '0;
        #(LP_RST_PERI);
        aresetn = '1;
    endtask

    task clk_gen();
        aclk = '0;
        forever #(LP_CLK_PERI/2) aclk = ~aclk;
    endtask

    task clk_dly(int n);
        repeat(n) @(posedge aclk);
    endtask

    // VIP decreation
//    sys_axi_vip_0_0_mst_t   agent;
    sys_axi4stream_vip_0_0_mst_t agent;

    task init_agent();
        agent = new("master vip agent", dut.sys_i.axi_vip_0.inst.IF);
        agent.start_master();
    endtask

    // Transaction method
    task wr_tran();
        // for axi
        //axi_transaction  wr_transaction;
        //wr_transaction   = agent.wr_driver.create_transaction( "write transaction with randomization");
        //WR_TRANSACTION_FAIL: assert(wr_transaction.randomize());
        //agent.wr_driver.send(wr_transaction);

        // for axi4stream
        axi4stream_transaction wr_transaction;
        wr_transaction = agent.driver.create_transaction("write transaction"); // wr_driver=>driver
        WR_TRANSACTION_FAIL: assert(wr_transaction.randomize());
        agent.driver.send(wr_transaction); // wr_driver=>driver
    endtask

    task rd_tran();
        // for axi
        //axi_transaction  rd_transaction;
        //rd_transaction   = agent.rd_driver.create_transaction("read transaction with randomization");
        //RD_TRANSACTION_FAIL_1a:assert(rd_transaction.randomize());
        //agent.rd_driver.send(rd_transaction);
        
        // for axi4stream
        axi4stream_transaction  rd_transaction;
        rd_transaction   = agent.driver.create_transaction("read transaction with randomization"); // rd_driver=>driver
        RD_TRANSACTION_FAIL_1a:assert(rd_transaction.randomize());
        agent.driver.send(rd_transaction); // rd_driver=>driver
    endtask

    // Testscenario
    initial begin

        fork
            init_agent();
            clk_gen();
            rst_gen();
        join_none

        clk_dly(100);

        wr_tran();

        clk_dly(100);

        //rd_tran();
        wr_tran();

        clk_dly(100);
        $finish(2);
    end
endmodule
```

- Streamなので、wr_tran()とrd_tran()を対にはせずにwr_tran()だけに
- wr_tran()をもう一回実施
- axiからaxi4stream変更時に「wr_driver」「rd_driver」はともに「driver」に変わったようだ

### Run Simulation

波形を見る時は「Zoom Fit」を実行して全体表示してから見たい部分を見る。

以下の例では一部を拡大したもの。
m_axis_tdataの値がそのままs00_axis_tdataに入っている。
tvalid=1, tready=1のときが有効なデータ (参考: 後述のFPGAの部屋さんの記載)。
<img width="1564" alt="image.png (28.9 kB)" src="https://img.esa.io/uploads/production/attachments/6206/2021/12/02/21741/aec41789-48e9-423d-a266-7eaf634c6ad6.png">

wr_tran()を5回実施した例。m_axis_tvalidが5回1になっている。
<img width="1556" alt="image.png (29.5 kB)" src="https://img.esa.io/uploads/production/attachments/6206/2021/12/02/21741/a604ad61-6cf5-4739-9522-eb7e4d4859c2.png">


### 関連

- AXI4-Stream のお勉強 @ FPGAの部屋さん
    - https://marsee101.blog.fc2.com/blog-entry-2454.html
    - 信号の説明が書かれている
    - 必須とオプションの記載、など
- [AXI4-Stream を試す](https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E9%9B%BB%E6%B0%97%E5%9B%9E%E8%B7%AF%2FHDL%2FVivado%E3%81%A7AXI%E3%83%90%E3%82%B9%E3%82%92%E5%88%A9%E7%94%A8#maf47dc5
) by 筑波大学 武内修様
    - AXI4 StreamのMaster IPなので、これと接続するのはAXI4-Stream VIP (Slave)になる？