LoginSignup
0
0

More than 1 year has passed since last update.

ZYBO導入記録 (3) Lチカ

Last updated at Posted at 2021-10-21

はじめに

この記事は以下の続きとなります。
ZYBO導入記録 (2) Hello worldの表示
今回はZYBOボードでLチカを行っていきます。

開発環境

  • 開発用PC : Windows 10 64-bit
    • Vivado 2020.2
    • Xilinx Vitis 2020.2
    • ターゲットボード : ZYBO (旧ZYBO)

開発の流れ

VivadoでFPGA内部のハードウェア構成を定めるハードウェアデザインを開発し、XSAファイルとしてエクスポートする。
VitisでXSAファイルを読み込んでアプリケーションプロジェクトを作成し、Lチカのソースコードを作成してビルドする。
完成したプロジェクトをZYBOボードに書き込む。

ハードウェア設計 (Vivado)

Vivadoを起動する。
image (0).png
[Create Project]をクリック
image (8).png
[Next] をクリック
image (9).png
Project nameを入力する。ここでは "LED_flashing" と入力して [Next]
image (10).png
"RTL Project" を選択して [Next] をクリック。
image (11).png

[Next] をクリック
image (12).png

[Next] をクリック。
image (13).png

[Boards] タブを選択し、Searchに "zybo" を入力して [Zybo] を選択し [Next] を選択。

image (14).png

[Finish] を選択。

image (15).png

プロジェクトが作成され、下記の画面が立ち上がる。

image.png

[Project manager] から [Create Block Design] を選択。

image (16).png

デザイン名を聞かれるので入力して[OK]を選択。今回は"LED_flashing_system"とする。

image (17).png

[Diagram]ウインドウで中央の[+]マークをクリックするか、右クリックして[Add IP...]をクリックする。

image (18).png

出てきたウインドウで[ZYNQ7 Processing System]を選択してダブルクリック。(最初のDefault Partのボード選択でZyboを選んでいないと表示されない)

image (19).png

選択すると、図のように [ZYNQ] のプロセッサコアを表す “processing_system_7_0” という名前のIPが追加。
[Run Block Automation]をクリック。

image (20).png

[OK]をクリック。

image (21).png

IP “processing_system_7_0″に接続ポート[DDR]と[FIXED_IO]が追加。

image (22).png

[FLCK_CLK0]にマウスカーソルを合わせると鉛筆マークに変化するので、ドラッグし[M_AXI_GP0_ACLK]にクロック出力を繋げる。

image (23).png

[Diagram] の余白で右クリックし、[Add IP] を選択する

image (24).png

[Search] に "gpio" を入力し、表示された [AXI GPIO] をダブルクリック

image (25).png

[Diagram] に [AXI GPIO] が表示される

image (26).png

見やすいように [AXI GPIO] をドラッグして [ZYNQ] の右側に移動する
[Run Connection Automationon] をクリック

image (27).png

[GPIO] をクリック

image (28).png

詳細画面が表示される。

image (29).png

[Options] から [leds_4bits ( 4 LEDs ) ] を選択

image (30).png

[All Automation] にチェックを入れて [OK]

image (31).png

IPが追加されて、自動でIP間が接続される

image (32).png

[Interfaces View] を選択するとよりシンプルで可読性が良い表示に切り替えられる。

image (33).png

[Interfaces View] ではクロックやリセットなどの配線が省略される

image (34).png

[BLOCK DESIGN] ウインドウから [Sources] タブを選択。
[Design sources] > [LED_flashing_system] を右クリックし、[Create HDL Wrapper] をクリック。

image (35).png

このまま [OK] をクリック。

image (36).png

そのまま [OK] をクリック。

image (37).png

LEDへの出力信号がFPGAのどのピンから出力されるか、制約ファイル上で定義していく。

作成された [LED_flashing_system_wrapper(LED_flashing_system_wrapper.v)]をダブルクリックする。

image (38).png

[LED_flashing_system_wrapper.v] の内容が表示される。

image (2).png

下に行くと、LEDへの出力を表す変数名が表示されている。
変数名が [led_4bits_tri_o] という名前であることがわかる。

image (39).png

[Sources] タブの [Constraints] フォルダを右クリックし、[Add Sources...] をクリックする。

image (40).png

作成するファイルの種類を選択するウインドウが開く

  • 制約ファイル(constraints)
  • 設計ファイル(design sources)
  • シミュレーションファイル(simulation sources)

制約ファイルを作成するため[Add or create constraints]を選択し、[Next]をクリックする。

image (41).png

[Create File] をクリックする

image (42).png

ウインドウが表示される。
[File name] にファイルの名前を、[File location] にファイルの格納先を入力し、[OK] をクリック
ここではファイル名を "led_constraints" ファイルの格納先を "C:/Users/user/FPGA_Xilinx" とした。

image (43).png

[Finish] をクリック

image (44).png

[Sources] タブの [Constraints] > [constrs_1] の中に作成された [led_constraints.xdc] があるのでダブルクリック

image (45).png

編集画面が表示される

image (3).png

以下のコードを記述する。

set_property PACKAGE_PIN M14 [get_ports {leds_4bits_tri_o[0]}]  
set_property IOSTANDARD LVCMOS33 [get_ports {leds_4bits_tri_o[0]}]  

set_property PACKAGE_PIN M15 [get_ports {leds_4bits_tri_o[1]}]  
set_property IOSTANDARD LVCMOS33 [get_ports {leds_4bits_tri_o[1]}] 

set_property PACKAGE_PIN G14 [get_ports {leds_4bits_tri_o[2]}]  
set_property IOSTANDARD LVCMOS33 [get_ports {leds_4bits_tri_o[2]}]  

set_property PACKAGE_PIN D18 [get_ports {leds_4bits_tri_o[3]}]  
set_property IOSTANDARD LVCMOS33 [get_ports {leds_4bits_tri_o[3]}]

FPGAのLED関連のピン配置は下記リンク先の"13 Basic I/O"で確認できる。
https://reference.digilentinc.com/reference/programmable-logic/zybo/reference-manual

io1.png

[Generate Bitstream] をクリック。

image (46).png

bitstreamファイル作成までしばらく時間がかかる。
作成中は右上スミに作業中の表示が出る。

image (5).png

この画面が出れば完了。[Cancel] をクリック。

image (47).png

メニューバーの [File] から [Export] > [Export Hardware...] を選択する。

image (48).png

[Next] を選択。

image (49).png

[Include bitstream] を選択して [Next] を選択。
image (50).png

XSAファイル名と格納するディレクトリを指定する。
ファイル名は "LED_flashing_system_wrapper" とする。
[Next] をクリック。

image (51).png

[Finish] を選択する。
image (52).png

ソフトウェアアプリケーション設計 (Vitis)

[Tools] > [Launch Vitis IDE] をクリック。

image (53).png

Workspaceのディレクトリを指定して [Launch] をクリック。

image (54).png

Vitisの画面が立ち上がる。
image (1).png

既存のワークスペースを選んでいると以前のプラットフォームプロジェクトが既に表示されているので、右クリックで [Delete] を選択し、ワークスペースから削除する。

image (55).png

この画面で [OK] を押す。
[Delete project contents on disk] にチェックをつけるとXSAファイルがドライブからも削除されてしまうので、チェックを入れないこと。

image (56).png

アプリケーションプロジェクトもあれば合わせてDeleteし、ワークスペースから削除する。

image (57).png

メニューバーより [File] > [New] > [Application Project] を選択

image (58).png

[Next] をクリック。

image (59).png

[Create a new platform from hardware (XSA) ] タブから [Browse] をクリック。

image (60).png

[Vivado] で作成した ”LED_flashing_system_wrapper.xsa” を選択して [開く] をクリック。

image (61).png

[Next] をクリック。

image (62).png

アプリケーションプロジェクト名を入力し、[Next] をクリックする。
アプリケーションプロジェクト名は ”LED_flashing_apprication” とした。

image (63).png

[Next] をクリック。

image (64).png

[Empty Application] を選択して [Finish]

image (65).png

空のCプロジェクトが作成される。

image (6).png

[Explorer] 内の [LED_flashing_application_system] > [LED_flashing_application] > [src] を右クリックし、 [New] > [File] を選択する。

image (66).png

[Create New File] ウインドウが立ち上がる。
File nameを入力する。
拡張子は [***.c] とすること。
今回は "led.c" にして [Finish] を選択する。

image (67).png

何も書かれていない空白のファイルのled.cが立ち上がる。

image (68).png

下記のソースコードを記述する。

#include "xparameters.h" 
#define LED      *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x00)) 
#define LED_ctrl *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x04)) 
int main() 
{ 
   LED_ctrl = 0x0; 
   LED = 0x1; 
   return 0; 
}

プラットフォームプロジェクト (led_flashing_system_wrapper) を選択して右クリックし、[Build Project] を選択してビルドを行う。

image (69).png

システムプロジェクト (led_flashing_application_system) を選択して右クリックし、[Build Project] を選択してビルドを行う。

image (70).png

ZYBOをPCにつなぐ

image1.png

ジャンパがJTAGであることを確認する。
image4.png

電源を入れる。

image2.png

PGOODの赤LEDが点灯していることを確認する。

image3.png

[LED_flashing_application_system] を右クリックし、[Debug as ] > [Launch Hardware] を選択する。

image (71).png

PC側からFPGAへのbitstreamファイルの書き込み(コンフィギュレーション)とアプリケーションソフトウェアのDDRへの書き込みが実施される。緑の行でプログラムはストップしている。
Resumeアイコンをクリックしてプログラムを実行する。

image (72).png

以下の画面が表示される。

image (74).png

右から1つ目のLEDのみが点灯する。

image (73).png

プログラムを変更する。
[led.c] タブを選択する。

image (75).png

GPIOのデータレジスタ(変数名[LED])に"0x3"(2進数表示で0011)を代入してみる。

#include "xparameters.h" 
#define LED      *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x00)) 
#define LED_ctrl *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x04)) 
int main() 
{ 
   LED_ctrl = 0x0; 
   LED = 0x3; 
   return 0; 
}

Ctrl+s で変更した [led.c] を保存する。
システムプロジェクト (led_flashing_application_system) を選択して右クリックし、Build Projectを選択してビルドを行う。
一度書込みを行ったことでDebugタブが表示され、システムプロジェクトの表示場所が変わっているので注意すること。

image (76).png

プラットフォームプロジェクトはビルドする必要はなし。
ビルドを忘れるとプログラムが更新されないので注意する。

ビルドを行ったら、前回と同様に [LED_flashing_application_system] を右クリックし、[Debug as ] > [Launch Hardware] を選択して
コンフィギュレーションと書込みを行う。前回と同様にプログラムが途中で止まるので、同様にResumeボタンを押す。

右から1番目と2番目のLEDが点灯する。

IMG_8665.JPG

[led.c] で同様に

   LED = 0x7;

とすると右から1、2、3番目のLEDが点灯する。

IMG_8666.JPG

   LED = 0xF;

とすると4つ全てのLEDが点灯する。

IMG_8667.JPG

変数LEDは

   LED = 0b0100;

のようにバイナリで指定しても良い。

IMG_8664.JPG

LEDの単純な点灯はできたので、Lチカをやってみる。
LEDを点滅させるために、whileループと時間遅延の行を追加する。

#include "xparameters.h" 
#define LED      *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x00)) 
#define LED_ctrl *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x04)) 
int main() 
{ 
    int i, j; 
    LED_ctrl = 0x0; //write to control register 
   while(1) { 
           for ( i=0; i<2; i++ ) { 
            //switching on and off 
            if(i==0){ 
                LED = 0x1; //on 
            }else{ 
                LED = 0x0; //off 
            } 
               for ( j=0; j<100000000; j++); //Latency 
           } 
       } 
   return 0; 
}

while(1)で無限ループを発生させ、iに関するforループでLEDのONとOFFを切り替える。
jは100メガ秒数えてwhileの1ループを約1秒にしている。

Vivadoで [BLOCK DESIGN] ウインドウから [Design] タブ > [processing_system7_0] > [FCLK_CLK0] を選択すると、下の [Block Pin Properties] にクロックソースである [FCLK_CLK0] の詳細が表示される。
ここからクロック周波数が100MHzであることがわかるので、数え上げるのは100メガ秒で良い。

image (77).png

書き込むと、一番右のLEDが約1秒ごとに点滅する。
IMG_8678.gif

4つのLEDを別々に点滅させることもできる。
以下は左から1秒、0.5秒、0.25秒、0.125秒ごとにLEDがそれぞれ点滅するプログラム。

#include "xparameters.h" 
#define LED      *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x00)) 
#define LED_ctrl *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x04)) 
int main() 
{ 
    int i, j; 
    LED_ctrl = 0x0; //write to control register 
   while(1) { 
           for ( i=0; i<16; i++ ) { 
            //switching on and off 
            if(i == 0){ 
                LED = 0x0; // LD3 and LD2 on 
            }else if(i == 1) { 
                LED = 0x1; // LD2 on 
            }else if(i == 2){ 
                LED = 0x2; // LD3 on 
            }else if(i == 3){ 
                LED = 0x3; // LD3 on 
            }else if(i == 4){ 
                LED = 0x4; // LD3 on 
            }else if(i == 5){ 
                LED = 0x5; // LD3 on 
            }else if(i == 6){ 
                LED = 0x6; // LD3 on 
            }else if(i == 7){ 
                LED = 0x7; // LD3 on 
            }else if(i == 8){ 
                LED = 0x8; // LD3 on 
            }else if(i == 9){ 
                LED = 0x9; // LD3 on 
            }else if(i == 10){ 
                LED = 0xA; // LD3 on 
            }else if(i == 11){ 
                LED = 0xB; // LD3 on 
            }else if(i == 12){ 
                LED = 0xC; // LD3 on 
            }else if(i == 13){ 
                LED = 0xD; // LD3 on 
            }else if(i == 14){ 
                LED = 0xE; // LD3 on 
            }else{ 
                LED = 0xF; //off 
            } 
            for ( j=0; j<6250000; j++); //Latency 
           } 
       } 
   return 0; 
}

IMG_8669.gif

以下は逆に右から1秒、0.5秒、0.25秒、0.125秒ごとにLEDがそれぞれ点滅するプログラム。

#include "xparameters.h" 
#define LED      *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x00)) 
#define LED_ctrl *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x04)) 
int main() 
{ 
    int i, j; 
    LED_ctrl = 0x0; //write to control register 
   while(1) { 
           for ( i=0; i<16; i++ ) { 
            //switching on and off 
            if(i == 0){ 
                LED = 0xF; // LD3 and LD2 on 
            }else if(i == 1) { 
                LED = 0x7; // LD2 on 
            }else if(i == 2){ 
                LED = 0xB; // LD3 on 
            }else if(i == 3){ 
                LED = 0x3; // LD3 on 
            }else if(i == 4){ 
                LED = 0xD; // LD3 on 
            }else if(i == 5){ 
                LED = 0x5; // LD3 on 
            }else if(i == 6){ 
                LED = 0x9; // LD3 on 
            }else if(i == 7){ 
                LED = 0x1; // LD3 on 
            }else if(i == 8){ 
                LED = 0xE; // LD3 on 
            }else if(i == 9){ 
                LED = 0x6; // LD3 on 
            }else if(i == 10){ 
                LED = 0xA; // LD3 on 
            }else if(i == 11){ 
                LED = 0x2; // LD3 on 
            }else if(i == 12){ 
                LED = 0xC; // LD3 on 
            }else if(i == 13){ 
                LED = 0x4; // LD3 on 
            }else if(i == 14){ 
                LED = 0x8; // LD3 on 
            }else{ 
                LED = 0x0; //off 
            } 
            for ( j=0; j<6250000; j++); //Latency 
           } 
       } 
   return 0; 
}

IMG_8677.gif

参考

主に以下サイトを参考にしました。今回省いた詳細なレジスタの説明もあります。
【LED点滅編(1)】Vitisで”LED点滅”プログラムを実行してみた – ハードウェア構成 –
【LED点滅編(2)】Vitisで”LED点滅”プログラムを実行してみた –プログラムの作成と実行 –

xdcファイルのコードについては下記が詳しいです。
FPGA オリジナルボード設計 I/O ピンの配置を決める「XDC ファイル」の書き方

おわりに

この記事はFPGAもZYBOも初心者の自分が色々調べながらメモ代わりに書いております。現状では動作することは確認できておりますが、間違いがあったり、後から記事を修正する場合があります。ご容赦ください。
もしも間違っている内容等ありましたら、ぜひご指摘ください。

0
0
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
0
0