LoginSignup
18
8

More than 5 years have passed since last update.

ZYBO (Zynq) 初心者ガイド (6) 自作IPでLチカ

Last updated at Posted at 2018-01-08

この記事の内容を4分で見る ( https://www.youtube.com/watch?v=JoQePlMliyk )

環境

  • 開発用PC: Windows 10 64-bit
    • Vivado 2017.4 WebPACKライセンス
    • Xilinx SDK 2017.4
  • ターゲットボード: ZYBO (Z7-20)

Windows環境は1回目を参照。

自作IPでLチカ

GPIOの OUT だけの機能を持ったIPを作ります。この自作IPをPS側のCPUから制御してLEDをチカチカさせます。前回の最後に、LED点灯するモジュール(blink)をIP Integratorから呼んでみました。しかし、厳密にはこれはあくまで「モジュール」であって「IP」ではないようです。IPを作るためには、ちゃんとパッケージ化する必要があります。まずはそれをやります。

今回も、最初からVivadoプロジェクトを作ります。ボードにZyboを指定した空のプロジェクトを用意済みとして、話を進めます。

自作IPを作る (Vivado)

自作IPの仕様

今回のIPはPSから制御できるようにします。PSとPLでデータをやり取りするときには、AXIバスを使います。CPUはAXI経由でIP内部のレジスタに値をR/Wします。IPはこのレジスタの値を使って動作します。今回は、レジスタ値の下位4ビットを反転して出力するようにします。
(このIP単体にとっては、この4bit出力はただの信号線です。なので、「LED」とかは付けないことにします。どこに接続するかは、このIPを使用するIP Integratorで決めます。(という考えはソフト屋さん的な考えなのかな。。。))

  • 名前: myip
  • PSとのインターフェース: AXI4-Lite Slave
  • レジスタ: 32-bit x 4 (実際に使用するのは1個だけだが、デフォルト設定のまま使うため)
  • 出力: 4-bitの信号線 (後でLEDに接続される)

自作IPのひな形を作る

空のVivadoプロジェクトを開いたら、まずはメニューバー -> Tools -> Create and Package New IPをクリックします。何をやるか聞かれるので、「Create AXI4 Peripheral」を選びます。OKを押すと、IP名などを設定する画面になります。基本はデフォルトのままで良いですが、僕は保存先だけ変更しました。デフォルトだと、1つ上のフォルダに作られてしまいます。今回作るIPはこのプロジェクトでのみ使うので、「../」を削除しました。

01.jpg
02.jpg

続いて、インターフェースを編集できますが、ここもひとまずはデフォルトのままにします。デフォルトでは、AXI4-Lite Slaveで、32-bit x 4個のレジスタが用意されます。OKを押して、次の画面もAdd IP to the repositoryのままでFinishします。(4-bitの出力は、後でコード上で追加します)

03.jpg

自作IPを編集する

Flow Navigator -> PROJECT MANAGER -> IP Catalogをクリックして、IP Catalogを確認すると、User Repositoryの下に「myip_v1.0」が出来ています。先ほど全てデフォルト設定で作成したので、これから編集します。右クリックして「Edit in IP Packager」を選びます。これで、このIPを編集する新しい一時的なプロジェクトを開きます。そのプロジェクトの保存先を聞かれますが、デフォルトのままOKします。

04.jpg

自作IP(myip)を編集するための、新しいVivadoウィンドウが開かれます。ソースコードは2つあり、myip_v1_0_S00_AXI.vが実体で、myip_v1_0.vはラッパー的な感じです。

05.jpg

今回は出力として、4-bitのMY_OUTを追加します。これに、4個のうち最初のレジスタの下位4-bitを反転して割り当ててみます。レジスタ名はslv_reg0のようです。(この記事では簡単のために、例としてこのようなシンプルなロジックにしました。実際のプロジェクトではもっと複雑なロジックになると思います。)
myip_v1_0_S00_AXI.vを開くと、既にかなりのコードが実装されています。これは、AXIインターフェースでレジスタに読み書きするコードになります。「Users to add ...」というところに、コードを追加していきます。追加は2行だけで、ポート定義と、ロジック記述だけです。

myip_v1_0_S00_AXI.vの一部
    module myip_v1_0_S00_AXI #
    省略
    (
        // Users to add ports here
        output [3:0] MY_OUT,
        // User ports ends
        // Do not modify the ports beyond this line

        省略
    );

    省略

    // Add user logic here
    assign MY_OUT = ~slv_reg0[3:0];
    // User logic ends

    endmodule

myip_v1_0.vにも同様に追加します。MY_OUTを接続するコードを追加するだけです。

myip_v1_0.vの一部
    module myip_v1_0 #
    省略
    (
        // Users to add ports here
        output [3:0] MY_OUT,
        // User ports ends
        省略
    );
// Instantiation of Axi Bus Interface S00_AXI
    myip_v1_0_S00_AXI # ( 
        省略
    ) myip_v1_0_S00_AXI_inst (
        .MY_OUT(MY_OUT),
        省略
    );
    endmodule

コードの編集が終わったら、IPを再作成します。Package IPタブで全てのPackaging Stepsが編集マークからチェックマークになるように、更新します。各Stepの所で「Merge changes...」をクリックすればOKです。最後に、Review and Packageを選び、Re-Package IPをクリックします。成功したら、IP編集用のプロジェクトは閉じられます。

05_5.jpg
06.jpg

自作IPを使う (Vivado)

PSと、作成したIP(myip)を搭載したハードウェアを作ります。元のVivadoプロジェクト上で、Flow Navigator -> IP INTEGRATOR -> Create Block Designで新しいブロックデザインを作ります。作成されたブロックデザインのDiagramビュー上でPSを追加して、Run Block Automationします。ここまでは、2回目、3回目の内容と同じです。同様の手順で、作成したmyipも追加します。Add IPで表示されるIP一覧にmyipが追加されています。配置後、Run Connection Automationで自動接続してもらいます。設定は全てデフォルトでOKです。

07.jpg

myipが配置されたら、MY_OUTの出力ポートを用意します。myipのMY_OUT端子付近で右クリックしてMake Externalを選びます。すると、MY_OUT_0ポートが作られます。

08.jpg

必要部品の配置が出来たので、このブロックデザインをトップモジュールとして使います。ここから先は前回と同様です。Sourcesのdesign_1の所で右クリック -> Generate Output Productsと Create HDL Wrapperします。その後、MY_OUT_0ポートをLEDの接続されているピンに割り当てます。これも前回と同様に、Flow Navigator -> RTL ANALYSIS -> Open Elaborated Designしてから、以下のようにピン設定をして、適当な名前で制約ファイルを保存します。

09.jpg

最後に、Generate Bitstreamでビットストリームファイルを作り、Export Hardwareして、Launch SDKします。

ノート: 後で再びIPを編集する場合

自作IPを既にブロックデザイン上で配置した後に、自作IPを編集した場合は、更新作業が必要になります。自作IPの編集を終えて、元のVivadoプロジェクトに戻ると、以下のようにメッセージが上部に表示されるので、「Report IP Status」をクリックします。

10.jpg
11.jpg

すると、画面下部にIP Statusが表示されます。変更のあったmyipがチェックされていることを確認して、「Upgrade Selected」をクリックします。その後、必要であればデザインを変更し、Generate Output Products、Create HDL Wrapper、ビットストリーム作成をすることで更新完了です。

自作IPを呼び出してLチカするソフトを書く (SDK)

起動したSDK上で、適当なプロジェクトを作ります。ここでは名前をblinkとします。
まず最初に、自動生成されたblink_bspプロジェクトを確認します。xparameters.hを見ると、#define XPAR_MYIP_0_S00_AXI_BASEADDR 0x43C00000が定義されています。これが、自作IP内のレジスタのアドレスになります。各レジスタアドレスは、以下のようになります。

  • slv_reg0: 0x43C00000
  • slv_reg1: 0x43C00004
  • slv_reg2: 0x43C00008
  • slv_reg3: 0x43C0000C

今回は、0x43C00000にアクセスすることでLED制御できます。いつも通り、0x43C00000をポインタ化してアクセスしてもいいのですが、アクセス関数も自動生成されています。libsrc/myip_v1_0/src/myip.hを見ると、MYIP_mWriteReg()関数が用意されています。また、オフセットもマクロ化されて用意されているのでそれを使います。これらを使い、以下のように実装します。

helloworld.c
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "sleep.h"
#include "xparameters.h"
#include "myip.h"

int main()
{
    init_platform();

    print("Hello World\n\r");

    while(1) {
        MYIP_mWriteReg(XPAR_MYIP_0_S00_AXI_BASEADDR, MYIP_S00_AXI_SLV_REG0_OFFSET, 0x00);
        sleep(1);
        MYIP_mWriteReg(XPAR_MYIP_0_S00_AXI_BASEADDR, MYIP_S00_AXI_SLV_REG0_OFFSET, 0x0F);
        sleep(1);
    }

    cleanup_platform();
    return 0;
}

ビルド後、まずはXilinx -> Program FPGAでビットストリームファイルを書き込みます。確認してほしいのは、この時点でLEDが点灯することです。理由は、myipではレジスタ値の反転を出力しているため、初期値(0)の反転でHigh出力になっているためです。その後、ビルドしたプログラムをRunします。すると、1秒間隔でLEDが点滅するはずです。

18
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
8