Prismjs

2019年1月16日水曜日

ZYBO Z7-20 (zynq-7020)で自作IPを使ってLチカ

前回(ZYBO Z7-20 (zynq-7020)でPSからPL部のIPを制御してLチカ)はAXI GPIOというIPを追加してLチカさせました。
AXI GPIOはXilinxが用意したIPですが今回は自作のAXIバスを利用したIPを作成して、それを使ってLチカします。


まずは前回までを参考に新規でVivadoプロジェクトを作成してください。



IPの雛形RTLを作成する

Vivado上部メニューのToolsCreate and Package New IPをクリックします。 

ここではIPを作成できますよ的な案内なのでNextをクリックして次の画面に進みます。

Create AXI4 PeripheralCreate a new AXI4 peripheralを選択して、Nextをクリックします。

NameIPの名前を入力します。Display nameNameに合わせて自動で入力されます。保存場所IP locationは変えてもいいですがデフォルトのままでNextをクリックします。

この画面(Add Interfaces)ではどのAXIバスを使うかやデータ幅やレジスタの数などの設定ができます。デフォルトのままNextをクリックします。

次に何を行うか聞かれているので、Edit IPを選択してFinishをクリックします。

すると新しくIP作成用のVivadoウィンドウが開きます。

Source内に自動でIP用の雛形が作成されています。Lchika_IP_v1_0とその中でインスタンスされているLchika_IP_v1_0_S00_AXIが雛形なのでそれらを編集してIPを作っていくことになります。ソース内にユーザーが追記できる場所にはコメントが書かれています(例:// Users to add ports hereなど)。また雛形の説明も適宜コメントで書かれています(英語ですが)。


Lchika_IP_v1_0_S00_AXIを編集する

CPUXilinx SDKで作成するC or C++プログラム)からはAXIバスを通してLchika_IP_v1_0_S00_AXI内のレジスタ(slv_reg0slv_reg1slv_reg2slv_reg3 はじめのほうの設定Add Interfacesでレジスタ数をデフォルトのまま=4にしたので4つのレジスタがあります)にアクセスしてIPに指示を与えることになります。

slv_reg0をスイッチレジスタ、slv_reg1LED選択レジスタ、slv_reg2を周期設定レジスタとしてLチカIPを作成してみます。(slv_reg3は使いません)
slv_reg00ビット目が1ならLチカ動作開始0ならLチカ動作停止します。slv_reg11が立っているビットがLチカ動作の対象LEDになります(ZYBO4つのLEDを使うので03ビット目まで有効)。slv_reg0で動作開始後slv_reg2の値の数だけクロックが来たらLEDの明暗を反転させます。

まずはLEDを光らせるための出力ポートを記述しておきます。
// Users to add ports hereというコメントの下に「output wire [3:0] led,」と記述します。

次に// Add user logic hereというコメントの下に以下を記述します。
reg [31:0] counter;
always @( posedge S_AXI_ACLK )
    begin
      if ( S_AXI_ARESETN == 1'b0 || counter >= slv_reg2 || slv_reg0 == 0 )
        counter <= 0;
      else
        counter <= counter + 1;
    end

reg light;
always @( posedge S_AXI_ACLK )
    begin
      if ( S_AXI_ARESETN == 1'b0 || slv_reg0 == 0 )
        light <= 0;
      else if( counter >= slv_reg2 )
        light <= ~light;
      else
        light <= light;
    end
   
assign led= slv_reg1[3:0] & {light, light, light, light} ;


Lchika_IP_v1_0を編集する

次にLchika_IP_v1_0を編集します。

// Users to add ports hereというコメントの下に「output wire [3:0] led,」と記述します。

次に、Lchika_IP_v1_0_S00_AXIのインスタンス部にled(出力ポート)の接続の記述をします。
) Lchika_IP_v1_0_S00_AXI_inst ( という雛形の記述の下に「.led(led),」と記述してください。

これでLchika_IP_v1_0の編集は終わりです。


IPをパッケージ化する

Package IPタブのCustomization ParametersMerge changes from Customization Parameters Wizardと出ているのでこれをクリックします。

同様にFile Groups Mega changes from File Groups Wizardをクリックします。

さらに同様にReview and PackageIP has been modifiedをクリックします。

警告が消えたらRe-Package IPをクリックします。

YesをクリックするとIP作成のVivadoプロジェクトが閉じます。

これでIPのパッケージ化は完了です。

IPを回路に実装する

以下の作業は普通のIPを使うときとほとんど同じです。
一番初めに作ったプロジェクト(まだ閉じられていないほうのプロジェクト)でCreate Block Designをクリックしてブロックデザインを作成します。
まずはAdd IPZYNQ7 Processing Systemを追加してRun Block Automationをクリックし、Apply Board Presetにチェックがあるのを確認してOKをクリックします。

もう一度Add IPを開きます。よく確認してみると先ほど作成したIPがあるはずです。先ほど作成したIPをクリックしてDiagramに追加します。

追加したら、Run Block Automationをクリックし、デフォルトのままOKをクリックします。

作成したIPから出ている出力端子(led[3:0])を右クリックしてMake Externalをクリックし外部出力端子を作成します。
以下のような回路になったと思います。(Run Block Automation時に自動でProcessor System ResetAXI Interconnectも追加されます。)

CtrlSでデザインを保存し、右クリックからValidate Designをクリックしてブロックデザインに問題がないかチェックします。

Sourcesdesign_1上で右クリックしCreate HDL Wrapperでラッパーファイルを作成します。Let Vivado manage wrapper and auto-updateを選択してOKをクリックします。

Open Elaborated Designをクリックしてピン制約を追加します。(Open Elaborated Designが完了するまで数分かかります)I/O Portsが開けるようになったら、led_0I/O StdLVCMOS33に、Package Pinは、[0]M14[1]M15[2]G14[3]D18に設定し適当な名前で保存します。


Generate Bitstreamを実行してBitstreamファイルの生成を行います。

生成が完了したら、Vivado上部メニューのFileExportExport Hardwareをクリックします。
必ずInclude bitstreamにチェックを入れてからOKをクリックします。
その後、Launch SDKをクリックしてSDKを起動させます。


Xilinx SDKで制御ソフト作成・動作確認する

SDKメニューのFileNewApplication Projectをクリックし、アプリケーションプロジェクトを作成します。
Project nameにプロジェクト名を入力して、Nextに進み、Empty Applicationを選択しFinishをクリックします。

Project Explorerのアプリケーションプロジェクトフォルダのsrcを右クリック→NewSource Fileをクリックします。

適当に名前(拡張子.cまで付ける)を付けてFinishをクリックしてソースファイルを追加します。(ここではmain.cにしました)
追加したソースにmain関数を記述します。
以下にmain.cの記述を示します。
#include "xparameters.h"
#include <unistd.h>

#define IP_SW *((volatile unsigned int*)XPAR_LCHIKA_IP_0_S00_AXI_BASEADDR)
#define IP_FREQ *((volatile unsigned int*)(XPAR_LCHIKA_IP_0_S00_AXI_BASEADDR+0x08))
#define IP_SEL *((volatile unsigned int*)(XPAR_LCHIKA_IP_0_S00_AXI_BASEADDR+0x04))

int main(){
              unsigned int i,j;
              while(1){
                            for(i=0;i<4;i++){
                                          for(j=0;j<5;j++){
                                                        IP_SEL = 0x01 << i;
                                                        IP_FREQ = 0x989680*j;
                                                        IP_SW = 0x01;
                                                        usleep(1000000);
                                          }
                            }
              }
              return 0;
}


IP_FREQ = 0x989680*j;では点滅間隔を0x989680*jクロックカウントつまり10000000*jに設定しています。IPのクロックは100MHzなので0.1×j秒間隔になります。

main関数が完成したらSDKメニューのProjectCleanをクリックし、Clean all projectsを選択しOKをクリックします。

ビルドが終了したらmain関数にエラーがないかチェックします。(あれば修正します)。たまにmain関数以外でエラーが出ることがありますが、ビルド後Console18:02:03 Build Finished (took 1s.116ms)のような記述が書かれていればビルドは通っています。
よくincludeでエラーやワーニングが出ますがビルドが通っていれば無視してOKな場合が多いです。

ZYBOJP5JTAGになっている事を確認してPCと接続し電源(sw4)を入れます。SDKProgram FPGAのアイコンをクリックします。

ProgramをクリックするとZYBObitstreamファイルが書き込まれます。ZYBO上のDONEの緑色LEDが光っていれば正常に書き込まれているはずです。

Project Explorerのアプリケージョンフォルダ(ここではIP_Lchika)を右クリックして、Debug AsDebug Configrationsをクリックします。

Xilinx C/C++ application(System Debugger)をダブルクリックするとSystem Debugger using Debug_IP_Lchika.elf on Localが作成されるのでそれを選択しDebugをクリックします。(再度DebugするときはSystem Debugger using Debug_IP_Lchika.elf on LocalをクリックしてDebugをクリックすれば大丈夫です。)

デバッグ用画面に切り替えるかどうか聞かれるのでYesをクリックします。ちなみに画面はSDKの一番右上の虫マークとCマークをクリックすると切り替えられます。

Resumeボタン(再生マーク)をクリックするとプログラムが動きだし、ZYBOLEDがチカチカするはずです。

Cプログラムの修正する場合はDisconnectボタンをクリックしてから修正し、修正後は同様の手順でビルド・bitstreamファイル書き込み(ZYBOの電源は落とさなくてもいい)・デバッグを行ってください。

これで作ったIPの動作確認ができました。

 自作IPの他プロジェクトでの呼び出し方法

せっかくIPを作ったのでいろんなプロジェクトで流用したいですよね。

呼び出したいプロジェクトのVivadoSettingsをクリックし、IPRepositoryをクリックします。+マークをクリックして自作したIPのフォルダ(component.xmlなどが入っているフォルダ 今回の場合Lchika_IP_1.0というフォルダ)を指定してSelectをクリックし、OKをクリックしてSettingsを閉じます。

登録はこれだけです。

ためしにブロックデザインでAdd IPをしてみると、ちゃんと出てきました。



0 件のコメント:

コメントを投稿