はじめに
KV260 には ZynqMP チップを冷却するためのファンがついています。この冷却ファンを Debian/Ubuntu から制御するための方法を3回に分けて説明します。今回はその1回目です。
冷却ファン関連のハードウェア/ソフトウェアスタック
Debian/Ubuntu では、冷却ファンを制御するために下の図で示すようなソフトウェア/ハードウェアスタックになっています。
Fig.1 KV260 Fan Control Stack
PWM制御機能付きファン
概要
PWM制御機能とは、Pulse Width Modulation (パルス幅変調) を用いた制御機能です。PWM制御機能付きファンは、コントロール端子に入力するパルス信号のデューティ比を変化させることによって、ファンの回転速度を外部から制御することが出来ます。
Fig.2 PWM Controlled FAN
Programmable Logic
概要
この章では Prgrammable Logic 部の説明をします。Programmble Logic は下の図のシェードがかかった部分です。
Fig.3 KV260 Fan Control Stack (Programmable Logic)
KV260 では PWM制御機能付きファンを制御するためのコントロール信号が ZynqMP の A12 ピンに接続されています。この A12 ピンはZynqMP の Programmable Logic に接続されています。Programmable Logic でパルス信号を生成することでファンの回転数を制御することが出来ます。
なお、Programmable Logc がプログラムされていない時や、Programmable Logic が A12 ピンを制御しないようにプログラムされている場合、コントロール信号は High になって、常にフル回転でファンが回転するようになっています。
プログラム例(簡易版)
概要
この節では、PWMの波形を生成するのに ZynqMP の TTC(Triple Timer Counter) モジュールを使った、非常に簡単な例の作り方を示します。
ここで示すプログラム例は、次の図が示すように、ZynqMP の ttc0 の wave 出力信号を FAN_EN ポート(A12) に直接つなげるだけの非常に簡単なものです。
Fig.4 K26-Fan-Enable
TTC(Triple Timer Counter) モジュールは、ZynqMP の PS (Processing System) 部にあるハードウェアで、3つの独立したタイマ/カウンタモジュールを提供します。ZynqMP にはこのTTCが4つ(ttc0、ttc1、ttc2、ttc3) 搭載されています。
この例では ttc0 のチャネル2を使います。そのため、ttc0 からの出力 emio_ttc0_wave_o[2:0] のうち emio_ttc0_wave_o[2] だけを取り出すために Slice IP (ttc0_slice) を使っています。
この例を Vivado の GUI を使って生成する方法は、Ryuz88 さんが次の記事で詳細に説明されているので、そちらをご覧ください。
ここでは Tcl を使って生成する方法を説明します。
GitHub リポジトリの紹介
この例で説明する Tcl スクリプトは以下の Github のリポジトリで公開しています。ビルド済みのビットストリームファイルも提供しているので、ビルドするのが面倒な人がこちらを利用してください。
開発環境
・ Xilinx Vivado 2021.2
・ KV260 のボード情報
Tclスクリプトの説明
まず次のような Tcl スクリプトを使います。
proc add_fan_enable { zynq_ultra_ps_e_0 port_name prefix} {
variable slice_cell
variable cell_name
variable net_name_din
variable net_name_dout
if { $port_name eq "" } {
set port_name FAN_EN
}
if { $prefix eq "" } {
set prefix ttc0
}
append cell_name $prefix "_slice"
append net_name_din $cell_name "_din"
append net_name_dout $cell_name "_dout"
set_property -dict [list CONFIG.PSU__TTC0__WAVEOUT__ENABLE {1} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__TTC0__WAVEOUT__IO {EMIO} ] $zynq_ultra_ps_e_0
set slice_cell [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 $cell_name ]
set_property -dict [ list CONFIG.DIN_FROM {2} CONFIG.DIN_TO {2} CONFIG.DIN_WIDTH {3} ] $slice_cell
create_bd_port -dir O -from 0 -to 0 $port_name
connect_bd_net -net $net_name_dout [get_bd_pins $slice_cell/Dout] [get_bd_ports $port_name]
connect_bd_net -net $net_name_din [get_bd_pins $slice_cell/Din ] [get_bd_pins $zynq_ultra_ps_e_0/emio_ttc0_wave_o]
}
この Tcl スクリプトは次の処理を行うプロシージャを定義しています。
- zynqmp_ultra_ps_e_0 の ttc0 波形出力を有効化
- zynqmp_ultra_ps_e_0 のttc0 波形出力先を EMIO に設定
- Slice IP を追加
- Slice IP の入力ビット幅を3に、出力ビット幅を1に設定
- Slice IP の入力の2番目を出力に設定
- 外部ポートを port_name 名を使って生成
- 外部ポートと Slice IP の出力ポートを接続
- zynqmp_ultra_ps_e_0 の emio_ttc0_wave_o と Slice IP の入力ポートを接続
この Tcl スクリプトを取り込んで add_fan_enable プロシージャを実行します。この例を示します。
source [file join $project_directory "add_fan_enable.tcl" ]
set zynq_ultra_ps_e_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:zynq_ultra_ps_e:3.3 zynq_ultra_ps_e_0 ]
apply_bd_automation -rule xilinx.com:bd_rule:zynq_ultra_ps_e -config {apply_board_preset "1"} $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__M_AXI_GP0 {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__M_AXI_GP1 {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__IRQ0 {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__FABRIC__RST {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__FPGA_PL0_ENABLE {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__FPGA_PL1_ENABLE {0} ] $zynq_ultra_ps_e_0
add_fan_enable $zynq_ultra_ps_e_0 FAN_EN ttc0
この例では、以下のことを実行しています。
- add_fan_enable.tcl を読み込み
- zynqmp_ultra_ps_e を Add IP
- プリセットされているボード情報を元に zynqmp_ultra_ps_e を設定
- この例では不要な zynqmp_ultra_ps_e の各種ポートを無効化
- add_fan_enable を実行
プロジェクトの生成
Vivado のバッチモードでプロジェクトを生成する場合は次のようにします。
shell$ cd fpga
shell$ vivado -mode batch -source create_project.tcl
Vivado の GUI モードでプロジェクトを生成する場合は次のようにします。
Vivado > Tools > Run Tcl Script... > fpga/create_project.tcl
論理合成と配置配線
Vivado のバッチモードで論理合成と配置配線を行う場合は次のようにします。
shell$ cd fpga
shell$ vivado -mode batch -source implementation.tcl
Vivado の GUI モードで論理合成と配置配線を行う場合は、前節で生成したプロジェクトをVivado で開き、Run Synthesis と Run Imlementation を実行します。
ビットストリームファイルの生成
配置配線後のビットストリームファイルを、Linux で扱うことの出来るビットストリームファイルに変換します。
shell$ cd fpga
shell$ bootgen -arch zynqmp -image k26-fan-enable.bif -w -o ../k26-fan-enable.bin
KV260 のPL部にロード
ここではデバイスツリーオーバーレイを使って、ビットストリームファイルを KV260 の PL 部にロードする例を示します。まず次のようなデバイスツリーファイルを用意します。
/dts-v1/; /plugin/;
/ {
fragment@0 {
target-path = "/fpga-full";
__overlay__ {
firmware-name = "k26-fan-enable.bin";
};
};
};
前節でビルドしたビットストリームファイルを /lib/firmware にコピーします。なお、紹介した GitHub のリポジトリには gz 圧縮したビットストリームファイルが用意されているので、解凍してから /lib/firmware にコピーしてください。
shell$ sudo cp k26-fan-enable.bin /lib/firmware
デバイスツリーオーバーレイを実行します。dtbo-config を使う場合は次のようにします。
shell$ sudo dtbo-config --install k26-fan-enable --dts k26-fan-enable.dts
dtbo-config が無い場合は、次の手順でデバイスツリーオーバーレイを実行できます。
shell$ dtc -I dts -O dtb -@ -o k26-fan-enable.dtb k26-fan-enable.dts
shell$ sudo mkdir /config/device-tree/overlays/k26-fan-enable
shell$ sudo cp k26-fan-enable.dtb /config/device-tree/overlays/k26-fan-enable/dtbo