Linux

【Zynq7】1.FSBL(1stStageBootLoader)の構築

1.記事一覧

記事は複数回に分けて投稿します。Zynq7020SoCで動作する、YoctoベースのPetaLinuxを使わない素のLinuxを構築します。

ZynqMP(arm64版)はこちら

エッジArm Linux構築編(armv7l)

エッジArm Linux実践編(armv7l)

2.環境

参考書の内容より新しいVivadoとVitisのバージョンを使用します。これらは先にインストール済みの前提で進めます。開発PCにUbuntuを使用していますが、Windowsでも問題ありませんが、U-boot以降の手順はLinux環境が必要になるので、WSL2を使用するなどしてください。

開発PCUbuntu20.04, intel core i5 750 RAM 16G
XilinxツールVivado,Vitis 2022.2(現在最新2023/1)
ターゲットボードDigilent Zybo z7-20 Rev.B.2 (XC7Z020-1CLG400C, DDR3 1GB)

3.FSBL作成の流れ

FSBL作成の流れを説明します。FSBL(First Stage Boot loader)はハードウェアの初期化を行い、U-bootブートローダを呼び出すための前段のブートローダになります。

今回はZynqSoCデバイスにかなり依存する内容のため、Zynqデバイスの概要や作法を説明します。まず、ZynqSoCについて簡単に説明します。

出典<https://japan.xilinx.com/products/boards-and-kits/1-t5lnks.html>

ZynqデバイスはXilinx(ザイリンクス、現在はAMD傘下)社製のARMプロセッサを搭載するFPGA SoCです。橙色枠のPL部(ProgrammableLogic)と青枠のPS部(ProcessingSystem)に別れています。PL部はFPGAに該当します。PS部はArmプロセッサ(Cortex-A9×2)とDDRメモリコントローラ、クロック、そしてI/Oペリフェラルで構成されます。

Xilinxツールの開発の流れです。FSBLとBitStreamの2つのファイルを作る必要があります。

  1. Vivadoにより、PS部のIPを配置し、バス、クロック信号を配線する
  2. Vivadoでハードウェアを構成するための情報BitStreamファイルを生成する
  3. Vivadoからハードウェア情報をVitisに移動し、BSP(BoardSupportPackage)を生成
  4. VitisはPSのプロセッサで実行するFSBLプログラムをビルドし生成する

ポイントは

  • Vivado(ハードウェア(BitStream)構築)→Vitis(ソフトウェア(FSBL)構築)の流れ

4.VivadoによるPL部の設定とBitStream生成

Vivado(読み:ビバド)はFPGA開発向けのツールになります。プロジェクトを作成し、ハードウェア構成情報のBitStreamデータを生成していきます。

4-1. プロジェクト作成

Vivadoを立ち上げ、Quick Start>Create Projectで新規作成します。

Bash
$ source /tools/Xilinx/Vivado/2022.2/settings64.sh
$ source /tools/Xilinx/Vitis/2022.2/settings64.sh
$ vivado &

nextをクリックしプロジェクト名を入力し、フォルダを選択します。

RTL Projectと2つのチェックを入れnextします。

Boardsタブを選択し、Searchに”zybo”と入力、今回のターゲットボードである、「Zybo Z7-20」を選択し、nextします。

次のページでFinishをクリックすると、プロジェクト生成完了です。

4-2. PS部にクロックを供給する

クロックの設定をしていきます。IPコンフィグレータを使用し、IPをブロック線図のように配置、配線を行います。IP(Intellectual Property)とは誤解を恐れず言うと回路情報でここではハードウェアのブロックとして扱います。左カラムの「Create Block Design」をクリックします。

デフォルトでOKをクリックします。

「+」印のAddIPをクリックし、表示されたリストに「zynq」と入力、ZYNQ7 Processing Systemをダブルクリックすると、IPブロックが追加されます。

PS部のIPブロックが配置されました。Run Block Automationをクリックし、自動配線します。

デフォルトでOKをクリックします。

DDR SDRAMインターフェイスとFIXED_IOが自動配線されます。次にクロックを手動で配線します。FCLK_CLK0をドラッグしながらM_AXI_GP0_ACLKに接続してください。

次にリセット生成IPを配置します。「+」印のAddIPをクリックし、表示されたリストに「reset」と入力、Processor System Resetをダブルクリックすると、IPブロックが追加されます。

Run Block Automationをクリックし、自動配線します。ウィンドウが出てきたらすべてチェックを入れてください。

配線が完了するので、Regenerate Layoutボタンをクリックして、配置を整理します。

配線のチェックを行います。Validate Designボタンをクリックします。

エラーがでなければ問題ありません。しかし、DDR周りで警告が出る場合は無視して良いです(PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_x)。DDRの信号タイミング設定値がマイナス値であるため警告が出ていますが、zyboボード固有の設定値になるので、変える必要はありません。

次にPlatform Setupタブを選択して、エラーがあれば解消します。エラーを残すと、この後、Vitis向けにハードウェア情報をExportできなくなります。

AXI Portの設定をします。AXI Portバスマスタを最低1つ有効にしろとエラー書きがあるので、M_AXI_GP0のEnabledをチェックします。AXIPortとはPS-PL間のバスの接続部分を指します。今回はPL側にバススレーブIPを何も配置していないので使いません。

つづいてClockです。FCLK_CLK0に関連するリセットブロックが無いよと注意書きがあります。リセットブロックは先ほど追加したリセット生成IPのことです。再認識させるために、Enabledのチェックを一度外し、入れ直します。

Is Defaultのチェックも入れ直します。リセット生成IPが認識されてエラーが消えます。

続いてプロジェクトの上位階層を作成します。BitStreamを生成するために必要な階層になります。Sourcesウィンドウ>Design Sources>design_1(design_1bd)を右クリックし、Create HDL Wrapperをクリックします(右クリックメニューのスクショ写っていませんがご了承ください)。

オプションのダイアログはそのままOKをクリックしてください。完了すると”*_wrapper”に変わります。

4-3. 制約ファイルの読み込みと論理合成・配置配線の実行

制約ファイルを読み込みます。制約ファイルとはFPGAやZynqデバイスの端子に関しての

  • 回路記述のポートに対するFPGA外部端子の割当
  • 各端子の信号レベルを設定
  • クロック周波数の波形の設定

を記述したファイル(.xdc)になります。zyboボードのメーカーであるDigilentより配布されていますので、これを利用します。コメントアウトされているので各々で外して使います。

私が改変したZybo-Z7-Custom.xdcをおいておきます。これをvivadoのプロジェクトフォルダ内にコピーします。

## This file is a general .xdc for the Zybo Z7 Rev. B
## It is compatible with the Zybo Z7-20 and Zybo Z7-10
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
##Clock signal
set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { sysclk }]; #IO_L12P_T1_MRCC_35 Sch=sysclk
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { sysclk }];
##Switches
set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L19N_T3_VREF_35 Sch=sw[0]
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L24P_T3_34 Sch=sw[1]
set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L4N_T0_34 Sch=sw[2]
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L9P_T1_DQS_34 Sch=sw[3]
##Buttons
set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L12N_T1_MRCC_35 Sch=btn[0]
set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L24N_T3_34 Sch=btn[1]
set_property -dict { PACKAGE_PIN K19 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L10P_T1_AD11P_35 Sch=btn[2]
set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L7P_T1_34 Sch=btn[3]
##LEDs
set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L23P_T3_35 Sch=led[0]
set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L23N_T3_35 Sch=led[1]
set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_0_35 Sch=led[2]
set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L3N_T0_DQS_AD1N_35 Sch=led[3]
##RGB LED 5 (Zybo Z7-20 only)
set_property -dict { PACKAGE_PIN Y11 IOSTANDARD LVCMOS33 } [get_ports { led5_r }]; #IO_L18N_T2_13 Sch=led5_r
set_property -dict { PACKAGE_PIN T5 IOSTANDARD LVCMOS33 } [get_ports { led5_g }]; #IO_L19P_T3_13 Sch=led5_g
set_property -dict { PACKAGE_PIN Y12 IOSTANDARD LVCMOS33 } [get_ports { led5_b }]; #IO_L20P_T3_13 Sch=led5_b
##RGB LED 6
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led6_r }]; #IO_L18P_T2_34 Sch=led6_r
set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS33 } [get_ports { led6_g }]; #IO_L6N_T0_VREF_35 Sch=led6_g
set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { led6_b }]; #IO_L8P_T1_AD10P_35 Sch=led6_b
##Audio Codec
set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { ac_bclk }]; #IO_0_34 Sch=ac_bclk
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ac_mclk }]; #IO_L19N_T3_VREF_34 Sch=ac_mclk
set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ac_muten }]; #IO_L23N_T3_34 Sch=ac_muten
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { ac_pbdat }]; #IO_L20N_T3_34 Sch=ac_pbdat
set_property -dict { PACKAGE_PIN T19 IOSTANDARD LVCMOS33 } [get_ports { ac_pblrc }]; #IO_25_34 Sch=ac_pblrc
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ac_recdat }]; #IO_L19P_T3_34 Sch=ac_recdat
set_property -dict { PACKAGE_PIN Y18 IOSTANDARD LVCMOS33 } [get_ports { ac_reclrc }]; #IO_L17P_T2_34 Sch=ac_reclrc
set_property -dict { PACKAGE_PIN N18 IOSTANDARD LVCMOS33 } [get_ports { ac_scl }]; #IO_L13P_T2_MRCC_34 Sch=ac_scl
set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ac_sda }]; #IO_L23P_T3_34 Sch=ac_sda
##Additional Ethernet signals
set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 PULLUP true } [get_ports { eth_int_pu_b }]; #IO_L6P_T0_35 Sch=eth_int_pu_b
set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rst_b }]; #IO_L3P_T0_DQS_AD1P_35 Sch=eth_rst_b
##USB-OTG over-current detect pin
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { otg_oc }]; #IO_L3P_T0_DQS_PUDC_B_34 Sch=otg_oc
##Fan (Zybo Z7-20 only)
set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS33 PULLUP true } [get_ports { fan_fb_pu }]; #IO_L20N_T3_13 Sch=fan_fb_pu
##HDMI RX
set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_hpd }]; #IO_L22N_T3_34 Sch=hdmi_rx_hpd
set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_scl }]; #IO_L22P_T3_34 Sch=hdmi_rx_scl
set_property -dict { PACKAGE_PIN Y19 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_sda }]; #IO_L17N_T2_34 Sch=hdmi_rx_sda
set_property -dict { PACKAGE_PIN U19 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_clk_n }]; #IO_L12N_T1_MRCC_34 Sch=hdmi_rx_clk_n
set_property -dict { PACKAGE_PIN U18 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_clk_p }]; #IO_L12P_T1_MRCC_34 Sch=hdmi_rx_clk_p
set_property -dict { PACKAGE_PIN W20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_n[0] }]; #IO_L16N_T2_34 Sch=hdmi_rx_n[0]
set_property -dict { PACKAGE_PIN V20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_p[0] }]; #IO_L16P_T2_34 Sch=hdmi_rx_p[0]
set_property -dict { PACKAGE_PIN U20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_n[1] }]; #IO_L15N_T2_DQS_34 Sch=hdmi_rx_n[1]
set_property -dict { PACKAGE_PIN T20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_p[1] }]; #IO_L15P_T2_DQS_34 Sch=hdmi_rx_p[1]
set_property -dict { PACKAGE_PIN P20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_n[2] }]; #IO_L14N_T2_SRCC_34 Sch=hdmi_rx_n[2]
set_property -dict { PACKAGE_PIN N20 IOSTANDARD TMDS_33 } [get_ports { hdmi_rx_p[2] }]; #IO_L14P_T2_SRCC_34 Sch=hdmi_rx_p[2]
##HDMI RX CEC (Zybo Z7-20 only)
set_property -dict { PACKAGE_PIN Y8 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_cec }]; #IO_L14N_T2_SRCC_13 Sch=hdmi_rx_cec
##HDMI TX
set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_hpd }]; #IO_L5P_T0_AD9P_35 Sch=hdmi_tx_hpd
set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_scl }]; #IO_L16P_T2_35 Sch=hdmi_tx_scl
set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_sda }]; #IO_L16N_T2_35 Sch=hdmi_tx_sda
set_property -dict { PACKAGE_PIN H17 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_clk_n }]; #IO_L13N_T2_MRCC_35 Sch=hdmi_tx_clk_n
set_property -dict { PACKAGE_PIN H16 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_clk_p }]; #IO_L13P_T2_MRCC_35 Sch=hdmi_tx_clk_p
set_property -dict { PACKAGE_PIN D20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_n[0] }]; #IO_L4N_T0_35 Sch=hdmi_tx_n[0]
set_property -dict { PACKAGE_PIN D19 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_p[0] }]; #IO_L4P_T0_35 Sch=hdmi_tx_p[0]
set_property -dict { PACKAGE_PIN B20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_n[1] }]; #IO_L1N_T0_AD0N_35 Sch=hdmi_tx_n[1]
set_property -dict { PACKAGE_PIN C20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_p[1] }]; #IO_L1P_T0_AD0P_35 Sch=hdmi_tx_p[1]
set_property -dict { PACKAGE_PIN A20 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_n[2] }]; #IO_L2N_T0_AD8N_35 Sch=hdmi_tx_n[2]
set_property -dict { PACKAGE_PIN B19 IOSTANDARD TMDS_33 } [get_ports { hdmi_tx_p[2] }]; #IO_L2P_T0_AD8P_35 Sch=hdmi_tx_p[2]
##HDMI TX CEC
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_cec }]; #IO_L5N_T0_AD9N_35 Sch=hdmi_tx_cec
##Pmod Header JA (XADC)
set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L21P_T3_DQS_AD14P_35 Sch=JA1_R_p
set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L22P_T3_AD7P_35 Sch=JA2_R_P
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L24P_T3_AD15P_35 Sch=JA3_R_P
set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L20P_T3_AD6P_35 Sch=JA4_R_P
set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L21N_T3_DQS_AD14N_35 Sch=JA1_R_N
set_property -dict { PACKAGE_PIN L15 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L22N_T3_AD7N_35 Sch=JA2_R_N
set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L24N_T3_AD15N_35 Sch=JA3_R_N
set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L20N_T3_AD6N_35 Sch=JA4_R_N
##Pmod Header JB (Zybo Z7-20 only)
set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L15P_T2_DQS_13 Sch=jb_p[1]
set_property -dict { PACKAGE_PIN W8 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L15N_T2_DQS_13 Sch=jb_n[1]
set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L11P_T1_SRCC_13 Sch=jb_p[2]
set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L11N_T1_SRCC_13 Sch=jb_n[2]
set_property -dict { PACKAGE_PIN Y7 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L13P_T2_MRCC_13 Sch=jb_p[3]
set_property -dict { PACKAGE_PIN Y6 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L13N_T2_MRCC_13 Sch=jb_n[3]
set_property -dict { PACKAGE_PIN V6 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L22P_T3_13 Sch=jb_p[4]
set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L22N_T3_13 Sch=jb_n[4]
##Pmod Header JC
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { jc[0] }]; #IO_L10P_T1_34 Sch=jc_p[1]
set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { jc[1] }]; #IO_L10N_T1_34 Sch=jc_n[1]
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { jc[2] }]; #IO_L1P_T0_34 Sch=jc_p[2]
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { jc[3] }]; #IO_L1N_T0_34 Sch=jc_n[2]
set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { jc[4] }]; #IO_L8P_T1_34 Sch=jc_p[3]
set_property -dict { PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 } [get_ports { jc[5] }]; #IO_L8N_T1_34 Sch=jc_n[3]
set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L2P_T0_34 Sch=jc_p[4]
set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L2N_T0_34 Sch=jc_n[4]
##Pmod Header JD
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L5P_T0_34 Sch=jd_p[1]
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L5N_T0_34 Sch=jd_n[1]
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L6P_T0_34 Sch=jd_p[2]
set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L6N_T0_VREF_34 Sch=jd_n[2]
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L11P_T1_SRCC_34 Sch=jd_p[3]
set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L11N_T1_SRCC_34 Sch=jd_n[3]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L21P_T3_DQS_34 Sch=jd_p[4]
set_property -dict { PACKAGE_PIN V18 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L21N_T3_DQS_34 Sch=jd_n[4]
##Pmod Header JE
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { je[0] }]; #IO_L4P_T0_34 Sch=je[1]
set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { je[1] }]; #IO_L18N_T2_34 Sch=je[2]
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { je[2] }]; #IO_25_35 Sch=je[3]
set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { je[3] }]; #IO_L19P_T3_35 Sch=je[4]
set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { je[4] }]; #IO_L3N_T0_DQS_34 Sch=je[7]
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { je[5] }]; #IO_L9N_T1_DQS_34 Sch=je[8]
set_property -dict { PACKAGE_PIN T17 IOSTANDARD LVCMOS33 } [get_ports { je[6] }]; #IO_L20P_T3_34 Sch=je[9]
set_property -dict { PACKAGE_PIN Y17 IOSTANDARD LVCMOS33 } [get_ports { je[7] }]; #IO_L7N_T1_34 Sch=je[10]
##Pcam MIPI CSI-2 Connector
## This configuration expects the sensor to use 672Mbps/lane = 336 MHz HS_Clk
#create_clock -period 2.976 -name dphy_hs_clock_clk_p -waveform {0.000 1.488} [get_ports dphy_hs_clock_clk_p]
#set_property INTERNAL_VREF 0.6 [get_iobanks 35]
set_property -dict { PACKAGE_PIN J19 IOSTANDARD HSUL_12 } [get_ports { dphy_clk_lp_n }]; #IO_L10N_T1_AD11N_35 Sch=lp_clk_n
set_property -dict { PACKAGE_PIN H20 IOSTANDARD HSUL_12 } [get_ports { dphy_clk_lp_p }]; #IO_L17N_T2_AD5N_35 Sch=lp_clk_p
set_property -dict { PACKAGE_PIN M18 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_n[0] }]; #IO_L8N_T1_AD10N_35 Sch=lp_lane_n[0]
set_property -dict { PACKAGE_PIN L19 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_p[0] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=lp_lane_p[0]
set_property -dict { PACKAGE_PIN L20 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_n[1] }]; #IO_L9N_T1_DQS_AD3N_35 Sch=lp_lane_n[1]
set_property -dict { PACKAGE_PIN J20 IOSTANDARD HSUL_12 } [get_ports { dphy_data_lp_p[1] }]; #IO_L17P_T2_AD5P_35 Sch=lp_lane_p[1]
set_property -dict { PACKAGE_PIN H18 IOSTANDARD LVDS_25 } [get_ports { dphy_hs_clock_clk_n }]; #IO_L14N_T2_AD4N_SRCC_35 Sch=mipi_clk_n
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVDS_25 } [get_ports { dphy_hs_clock_clk_p }]; #IO_L14P_T2_AD4P_SRCC_35 Sch=mipi_clk_p
set_property -dict { PACKAGE_PIN M20 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_n[0] }]; #IO_L7N_T1_AD2N_35 Sch=mipi_lane_n[0]
set_property -dict { PACKAGE_PIN M19 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_p[0] }]; #IO_L7P_T1_AD2P_35 Sch=mipi_lane_p[0]
set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_n[1] }]; #IO_L11N_T1_SRCC_35 Sch=mipi_lane_n[1]
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVDS_25 } [get_ports { dphy_data_hs_p[1] }]; #IO_L11P_T1_SRCC_35 Sch=mipi_lane_p[1]
set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS33 } [get_ports { cam_clk }]; #IO_L18P_T2_AD13P_35 Sch=cam_clk
set_property -dict { PACKAGE_PIN G20 IOSTANDARD LVCMOS33 PULLUP true} [get_ports { cam_gpio }]; #IO_L18N_T2_AD13N_35 Sch=cam_gpio
set_property -dict { PACKAGE_PIN F20 IOSTANDARD LVCMOS33 } [get_ports { cam_scl }]; #IO_L15N_T2_DQS_AD12N_35 Sch=cam_scl
set_property -dict { PACKAGE_PIN F19 IOSTANDARD LVCMOS33 } [get_ports { cam_sda }]; #IO_L15P_T2_DQS_AD12P_35 Sch=cam_sda
##Unloaded Crypto Chip SWI (for future use)
set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS33 } [get_ports { crypto_sda }]; #IO_L13N_T2_MRCC_34 Sch=crypto_sda
##Unconnected Pins (Zybo Z7-20 only)
set_property PACKAGE_PIN T9 [get_ports {netic19_t9}]; #IO_L12P_T1_MRCC_13
set_property PACKAGE_PIN U10 [get_ports {netic19_u10}]; #IO_L12N_T1_MRCC_13
set_property PACKAGE_PIN U5 [get_ports {netic19_u5}]; #IO_L19N_T3_VREF_13
set_property PACKAGE_PIN U8 [get_ports {netic19_u8}]; #IO_L17N_T2_13
set_property PACKAGE_PIN U9 [get_ports {netic19_u9}]; #IO_L17P_T2_13
set_property PACKAGE_PIN V10 [get_ports {netic19_v10}]; #IO_L21N_T3_DQS_13
set_property PACKAGE_PIN V11 [get_ports {netic19_v11}]; #IO_L21P_T3_DQS_13
set_property PACKAGE_PIN V5 [get_ports {netic19_v5}]; #IO_L6N_T0_VREF_13
set_property PACKAGE_PIN W10 [get_ports {netic19_w10}]; #IO_L16P_T2_13
set_property PACKAGE_PIN W11 [get_ports {netic19_w11}]; #IO_L18P_T2_13
set_property PACKAGE_PIN W9 [get_ports {netic19_w9}]; #IO_L16N_T2_13
set_property PACKAGE_PIN Y9 [get_ports {netic19_y9}]; #IO_L14P_T2_SRCC_13

Add Sourcesをクリックし、Add or create constraintsを選択してnextをクリックします。

Add Filesを押して先ほどプロジェクト内にコピーした.xdcファイルを取り込みます。

Finishを押して完了です。

最後に論理合成・配置配線を行い、BitStreamファイルを出力します。論理合成・配置配線は詳細な説明は省きますが、ソフトウェアで言うコンパイル工程のようなものです。左下のPROGRAM AND DEBUG>Generate Bitstreamをクリックします。

実行ジョブ数のダイアログが出ますが、そのままOKします。

「No Implementation Results Available」のメッセージが出たらYesをクリックします。

論理合成・配置配線が開始します。開発PCのスペックによりますが、5~10分かかります。ウィンドウ右上の緑のぐるぐるマークがチェックになるまで待ちます。

終了すると、Bitstream Generation successfully completed.とメッセージが出れば問題ありません。キャンセルして閉じます。

BitstreamファイルはVivadoプロジェクトフォルダ内の
“プロジェクト名.runs/impl_1/design_1_wrapper.bit”
にあります。

5.VitisによるFSBLの生成

Vitis(読み:バイティス)はZynq搭載のARMプロセッサのソフトウェアを開発するツールです。これでFSBLソースコードをビルドしていきます。

5-1. Vivadoからハードウェア情報をエクスポート

VitisでFSBLを生成するために、先ほど作成したVivadoのハードウェア情報を読み込む必要があります。まずはVivadoよりプラットフォームファイルをエクスポートします。

Vivadoの左上File>Export>Export Platform…をクリックします。ウィンドウが出てくるのでNextをクリック。Platform TypeはHardwareを選択します。

Pre-synthesisを選択し、Include bitstreamをチェックしてnextをクリックします。

platform名を入力してnextをクリック。

保存先を指定します。デフォルトのパスのままだとVitisで大量のファイルが生成されてVivadoのファイルと混ざって大変なことになるため、Vivadoプロジェクト内に「プロジェクト名.vitis」サブフォルダを作成してその中に保存することにします。

最後にfinishをクリックして完了です。.xsaファイルが生成されます。

5-2. Vitisのプロジェクトの作成

Vivadoの左上ToolsからLaunch Vitis IDEをクリックして起動します。workspaceはvivadoでエクスポートしたプロジェクト名.vitisフォルダにします。

【追記】アプリケーションプロジェクトの作成は不要でした。プラットフォームプロジェクト作成時の”Generate boot components”にチェックが入っていればLinuxがブートできるFSBLが作成されます。逆にアプリケーションプロジェクトを作成すると、FSBLが2重に生成されて、VivadoでHWの更新が反映されません。申し訳ございません。

【修正版】Create new platform projectでプラットフォームプロジェクトを作成します。プロジェクト名は適当です。

先程Vivadoからexportしたプラットフォームファイル(.xsa)を選択します。以下を選択します。

  • Operating System : standalone
  • Processor : ps7_cortex9_0
  • Generate boot components -> チェックを入れる

finishを押して完了です。

5-3. FSBLをビルドする

左のプラットフォームプロジェクト(zyboz7-fsbl)を選択し金槌アイコンを押してビルドします。ソースコードフォルダ内に”fsbl.elf”が生成されたら完了です。

この.elfファイルがFSBLになります。場所は以下にあります。

“ワークスペース名.vitis/プラットフォームプロジェクト名/zynq_fsbl/fsbl.elf”

以上で必要なBitStreamファイルとFSBLが用意できました。

6.(参考)FSBLの設定

6-1. シリアルデバッグメッセージの有効化

なひたふさんの本には、FSBLの設定のポイントがいくつか乗っています。今回はシリアルコンソールにデバッグメッセージを表示する例を参考に設定してみます。

Zyboz7ボードにはオンボードデバッガが搭載されています。デバッガの回路図は非公開ですが、基板上のチップはFTDIのFT2232HQです。1本のUSBケーブルを接続すると、JTAGと仮想COMポートを使用することができます。

Vitisプロジェクトのsrc/fsbl_debug.hを適当なエディタで開き、

“#if defined (FSBL_DEBUG_INFO)”

のコンパイルスイッチ手前にFSBL_DEBUG_INFOマクロを定義します。下図のように記載します。

6-2. UARTポートの選択

Zynq z7ボードに搭載されるZynq7020SoCはUART0、UART1の2つあります。

USBJTAGケーブルではUART1が接続されていますが、コンソール出力がきちんと選択されているか確認します。確認する場所はplatformフォルダのbspのコードです。以下のパスにあります。

”workspase/design_1_wrapper_1(plarform名)/ps7_cortexa9_0/standalone_ps7_cortexa9_0/bsp/ps7_cortexa9_0/include/xparameters.h”

UART0=0xE0000000、UART1= 0xE0001000のアドレスになりますので設定は問題ありません。UART0を使いたい場合はこちらを切り替えます。

6-3. UART通信速度の設定

LInuxを起動する場合、実行権がFSBL→U-boot→Linuxと移ります。UARTの通信速度はそれぞれで設定し直されるので注意してください。どれかが異なるとLinux起動中にメッセージの文字化けや文字が出なくなったりします。私はU-boot(115.2kbps)からLinux起動直後に9600bpsに切り替わって、メッセージが出ず、起動失敗したと勘違いしたことがありました。

さて、FSBL実行中の通信設定です。vivadoのIPコンフィグレータでPS部のIPを配置したと思います。そのIPをダブルクリックします。

PS-PL Configration > General > UART1 Baud Rateで設定できます。

設定を変更したら、bitstreamの生成し直し、プラットフォーム情報のエクスポート、VitisでFSBLの再ビルドが必要になります。

ABOUT ME
sh-goto
低レイヤで遊んでいます
関連記事