Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Zynq-7000で,独自回路をIPにして,AXI4でPS-PL通信してプログラムから利用する (Vivado)

More than 5 years have passed since last update.

やりたいこと

Zed boardを買ってZynqいじりしていたのですが,自分でHDLゴリゴリ書いて作った独自回路をPLに書き込んでPSから利用する方法がよく分からなかったので,まとめてみました.
AXI4インタフェースを持った独自IPを作成し,Zynqのコアとつなぎます.

ここでは単純な加算器をAXI4-Liteインタフェースを利用した独自IPとして作成し,CPUから利用してみます.

使用したVivadoのバージョンは2014.2です.

プロジェクトの作成

まずは普通にプロジェクトを作ります.
ここではadder_testという名前にしました.
vivado_create_project2.png
vivado_create_project3.png
vivado_create_project4.png
vivado_create_project.png

Block design

左側のFlow navigatorから,IP Integrator -> Create Block Design でBlock Designを開きます.名前はここではsystemにしました.
vivado_block_design.png

Add IPをクリックして,ZYNQ7 Processing Systemを選択し,Zynqのコアを追加します.
vivado_block_design_zynq.png

Zynqコアをダブルクリックしてカスタマイズします.
vivado_block_design_zynq2.png
PresetsからZed boardを選び,OKします.(IPとの通信のためにAXI Masterインタフェース,テストプログラムのためにUARTがあればよいと思いますが,面倒くさいのでプリセットから選びます.)

独自IP追加

上のメニューから,Tool -> Create and Package IP を選びます.
こんなダイアログが出ます.
vivado_create_ip.png
nextを押します.

vivado_create_ip2.png
Create a new AXI4 peripheralを選んでNextを押します.

vivado_create_ip3.png
IP名を適当に決めて,Nextを押します.今回はsimple_adderにしました.

vivado_create_ip4.png
S00_AXIをS_AXIにリネームしました.リネームする必要は無いと思いますが,一つしかポートが無いので番号は消しました.

vivado_create_ip5.png
Edit IPを選択してFinishを押します.

IP編集

新しいウィンドウが開いて,IPの編集が行えます.
vivado_edit_ip1.png

vivado_edit_ip2.png
Sourcesペインを見ると,ソースファイルが2つできています.
トップレベルのsimple_adder_v1_0の下にAXI slaveインタフェースのsimple_adder_v1_0_S_AXIがあります.
詳しくは中身を読んでください.

ソース編集

simple_adder_v1_0_S_AXI.vを編集して,加算器にします.
このモジュールはslv_reg0, slv_reg1, slv_reg2, slv_reg3というレジスタを持っていて,Writeするとこれらのレジスタにデータが入り,Readするとこれらのレジスタから値が読み出されるようになっています.
ベースアドレスでアクセスするとslv_reg0にWrite/Readされ,ベースアドレスにオフセットを足してslv_reg1, slv_reg2, slv_reg3にアクセスします.この辺は詳しくは後述します.

今回は例としてslv_reg0slv_reg1の和をslv_reg2に入れるようにしてみます.

slv_reg0, slv_reg1, slv_reg2, slv_reg3をドライブしているalways @( posedge S_AXI_ACLK )~endブロックを探します.
if (slv_reg_wren)~endの中でslv_reg0, slv_reg1, slv_reg2, slv_reg3への書き込みが行われているのがわかります.(これがWrite処理)
ここにelseを足して,

slv_reg2 <= slv_reg0 + slv_reg1;

を書き加えます.(もっとうまいやり方があるのだろうな)

パッケージ

左側のFlow NavigatorからProject Manager -> Package IPを選びます.
vivado_edit_ip3.png
全項目に緑色チェックマークがついているのでOKです.Review and Packageタブを選んでRe-Package IPを押します.
これでIPの編集は終了です.

IP追加

もともとのプロジェクトのウィンドウに戻ってきました.

vivado_add_ip1.png
Add IPを押して,先ほど作った独自IP,simple_adder_v1.0を追加します.

vivado_add_ip2.png
Run Block Automation, Run Connection Automationを実行します.

vivado_add_ip3.png
こんな感じで配線されます.(Regenerate Layoutボタンを押すと再配置されて見やすくなります.)

Address Editorタブを選択してみます.
vivado_add_ip4.png

追加したsimple_adderにアドレスが割り振られているのが確認できます.

Bitstream作成

Sourcesペインでsystem_i - system (system.bd)を右クリックして,メニューからCreate HDL Wrapperを選びます.ダイアログではLet Vivado manage wrapper and auto-updateを選んでおくと良いと思います.
これでトップレベルのHDLが生成されます.

またsystem_i - system (system.bd)を右クリックして,メニューからGenerate Output Productsを選びます.ダイアログでGenerateをクリックします.

そうしたら,Generate Bitstreamを押してビットストリームを作成します.ダイアログでsaveするかとかsynthesisとimplementationするかとか聞かれますがyesで.

ソフトウェアの作成

SDKへエクスポート

Bitstreamができたら,上部のメニューからFile -> Export -> Export Hardwareを選択します.
ダイアログでInclude bitstreamにチェックが入っていることを確認して,OKを押します.

File -> Launch SDK を選択してSDKを起動します.
これでハードウェアの情報がSDKにも読み込まれます.

vivado_sdk_1.png
SDKの起動直後の画面でsimple_adderのアドレスがあることを確認

SDKでプロジェクト作成

上部のメニューから File -> New -> Application Projectを選択.
vivado_sdk_2.png
プロジェクト名を適当に決めて,あとはデフォルトのままNext.

vivado_sdk_3.png
Hello World を選んでFinish

ソース編集

adder_testプロジェクト以下のsrc -> helloworld.c を編集します.

#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"

#define SIMPLE_ADDER_ADDR_OFFSET1 4
#define SIMPLE_ADDER_ADDR_OFFSET2 8

int main()
{
    u32 result;

    init_platform();

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

    Xil_Out32(XPAR_SIMPLE_ADDER_0_S_AXI_BASEADDR, 123);
    Xil_Out32(XPAR_SIMPLE_ADDER_0_S_AXI_BASEADDR + SIMPLE_ADDER_ADDR_OFFSET1, 456);
    result = Xil_In32(XPAR_SIMPLE_ADDER_0_S_AXI_BASEADDR + SIMPLE_ADDER_ADDR_OFFSET2);

    xil_printf("123 + 456 = %d\r\n", result);

    cleanup_platform();

    return 0;
}
#define SIMPLE_ADDER_ADDR_OFFSET1 4

はsimple_adder_v1_0.vに定義されている

        parameter integer C_S_AXI_ADDR_WIDTH    = 4

にもとづいています.

simple_adder.h

インクルードファイルはadder_test_bspプロジェクト以下のSrc -> include内にあります.
たまにsimple_adder.hが生成されてsimple_adderとやりとりするのに便利なマクロが定義されたりするんですが,どうやったらこのファイルが生成されてくれるのかわかりません…
誰か教えてください

デバッグ実行

adder_testを選択した状態で上部のメニューからRun -> Debug Configurationsを選択します.

ダイアログでXilinx C/C++ application (GDB)をダブルクリックします.

vivado_sdk_4.png
Reset Entire Systemを選択し,Program FPGAにチェックが入った状態にします.

vivado_sdk_5.png
STDIO Connectionタブでコンソールの設定を行います.
Tera term等,別のターミナルソフトを使う場合は不要です.

設定が終わったら,Applyして設定を保存し,Debugを押します.パースペクティブを変えますか的なダイアログが出たらOKします.

確認

デバッグモードなのでステップ実行が始まります.とりあえずここではResumeを押して普通に実行してしまいます.

vivado_sdk_6.png
コンソールに

Hello World
123 + 456 = 579

と表示され,加算回路にAXIを使ってアクセスし利用することができたのがわかります.

言い訳

以上です.
Zynqを触り始めて1ヶ月くらいの初心者なのでご指摘などなどぜひよろしくお願いします.

whitphx
最近はPythonでおしごと, TypeScript + Reactでindie hacking
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away