Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
SystemVerilog を使用したXilinx FPGA開発
Search
tethys_seesaa
September 23, 2017
Technology
0
2.5k
SystemVerilog を使用したXilinx FPGA開発
2017年9月24日(日)に開催した
RTLを語る会(14)~FPGAの現実~の発表スライド(公開版)
tethys_seesaa
September 23, 2017
Tweet
Share
More Decks by tethys_seesaa
See All by tethys_seesaa
RTLを語る会(17)あいさつ
tethys_seesaa
0
420
UVVMをさわってみた
tethys_seesaa
0
590
Vivado2019.2でUVMを使った話
tethys_seesaa
0
840
RTLを語る会(16)あいさつ
tethys_seesaa
0
500
あいさつ
tethys_seesaa
0
560
Other Decks in Technology
See All in Technology
AWS と定理証明 〜ポリシー言語 Cedar 開発の舞台裏〜 #fp_matsuri / FP Matsuri 2025
ytaka23
8
2.3k
Two-Tower モデルで実現する 検索リランキング / Shibuya_AI_2
visional_engineering_and_design
2
180
データベースの引越しを Ora2Pg でスマートにやろう
jri_narita
0
200
AI とペアプロしてわかった 3 つのヒューマンエラー
takahiroikegawa
1
640
型システムを知りたい人のための型検査器作成入門
mame
14
3.5k
kotlin-lsp を Emacs で使えるようにしてみた / use kotlin-lsp in Emacs
nabeo
0
120
産業機械をElixirで制御する
kikuyuta
0
140
今からでも間に合う! 生成AI「RAG」再入門 / Re-introduction to RAG in Generative AI
hideakiaoyagi
1
150
現場で役立つAPIデザイン
nagix
1
250
ハッカー視点で学ぶサイバー攻撃と防御の基本
nomizone
3
1.7k
新規プロダクト開発、AIでどう変わった? #デザインエンジニアMeetup
bengo4com
0
400
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
17k
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.3k
Writing Fast Ruby
sferik
628
61k
What's in a price? How to price your products and services
michaelherold
245
12k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
Scaling GitHub
holman
459
140k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
900
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.3k
Typedesign – Prime Four
hannesfritz
42
2.7k
Done Done
chrislema
184
16k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
657
60k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Transcript
SystemVerilog を使用した Xilinx FPGA開発 〜Zynq-7000〜 @tethys_seesaa
Table of Contents • Vivadoの設計言語としてのSystemVerilog対応 • 合成可能なSystemVerilog記述 • Zynq-7000をターゲットとしたHW/SW開発について
VivadoのSystemVerilog対応話
VivadoのSystemVerilog対応の利点(1/5) • typedef対応 • VHDLのsubtypeのようなもの。 • バグの入りにくいスッキリとしたコード記述ができる。
typedef logic[7:0] Byte_t; // 幅表記が統一できる Byte_t [7:0] ad, dat; logic
[7:0] be; always_ff @(posedge rst, posedge clk) if(rst) begin ad <= '0; // logic型0のaggregationも兼ねる be <= '0; end … … always_comb dat[6] = '1; // バイト6に0xFFを入れる
VivadoのSystemVerilog対応の利点(2/5) • typedefとpacked配列の合わせ技 • packed構造体 • VHDLのrecordのようなもの • コード行を比較的、減らせる
typedef logic[7:0] Byte_t; typedef struct packed unsigned { Byte_t [7:0]
ad; logic [7:0] be; logic frame, irdy; } Pci_t; ... Pci_t pd; ... always_ff @(posedge rst, posedge clk) if(rst) begin pd <= '0; // ほとんどのメンバ信号は0 pd.frame <= '1; // このメンバ信号だけ1を入れる end ...
VivadoのSystemVerilog対応の利点(3/5) • typedefとenumの合わせ技 • VHDLのtypeみたいなもの • 例えばステートマシンでいちいち`defineで文字列にエン コード値を割り振らなくても良い • シミュレータからの波形も文字列で表示される
• ただし、これを用いて設計する場合、Vivadoだと論理合成のデ フォルト(auto)はエンコード値がワンホットに割り当てられるこ とが多いので注意。
typedef enum logic [7:0] { RESET = '0, // Vivadoのデフォルトだと無意味かも
INIT, ... ERROR } St_t; St_t cur, nxt; always_ff @(posedge rst, posedge clk) if(rst) cur <= RESET; else cur <= nxt; ...
VivadoのSystemVerilog対応の利点(4/5) • package, import • packageにて、これまでのtypedef等を共通の定義としてまとめること ができる。 • まとめたpackageは、importで各moduleで使用できる •
VHDLのpackageのようなもの • Vivadoでは論理合成時にちょっとクセがある • 後述します • Vivadoだと、importのimportはどうも対応していないようだ
package common_pack; typedef logic[7:0] Byte_t; ... // SystemVerilogではfunctionの入力はinput文を省略可 function Byte_t
get_data(Byte_t data); return data; endfunction ... endpackage ... import common_pack::*; module module_a( ... endmodule
VivadoのSystemVerilog対応の利点(5/5) • interface • 信号をまとめることができ、Master/Slaveでそれぞれメソッドを記述 することが可能 • modportでMaster/Slaveの指定ができる。 • ただし、今回のプロジェクトには未採用
• Block Designを使用すると、採用する機会が無かった
interface bus_t (); logic sel; logic rw; addr_t addr; //typedefで型指定
data_t rdat; //typedefで型指定 data_t wdat; // Master methods function data_t get_rdata(); return rdat; endfunction task automatic mst_rst(); sel <= ‘0; rw <= ‘0; addr <= ‘0; wdat <= ‘0; endtask // Slave methods function logic get_sel(); return sel; endfunction function data_t get_wdata(); return wdat; endfunction // modportでMaster/Slave決め modport mst( import get_rdata, mst_rst, output sel, rw, addr, wdat, input rdat ); modport slv( import get_sel, get_wdata, input sel, rw, addr, wdat, output rdat ); endinterface
module top(); // interfaceのインスタンス // interfaceの配列はダメっぽい bus_t bus_0(); bus_t bus_1();
... // module_0にbus_0をslaveとして接続 module_0 mod_0( .bus_0(bus_0), .*); ... endmodule module module_0( ... bus_t.slv bus_0 ); data_t dat; // Slave methods呼び出し always_ff @(posedge RST, posedge CLK) if(RST) dat <= ‘0; else if(bus_0.get_sel()) dat <= bus_0.get_wdata(); ... endmodule
VivadoのSystemVerilog対応まとめ • VHDLなみの型を意識しつつ、シンプルに記述できる • バグが発生しにくいコードが書ける • typedefを駆使して、packageを使用する • ただし、あくまでVerilog HDL
• バス幅表記とか • interfaceにも対応している • ここは個人的に意外だった
ここからはVivadoを使用した 開発の話
このZynq-7000システムを支えるボード • Zynq-7000 All Programmable SoC ZC706 評価キット • 一家に一台は欲しいZC706ボード
本当に起こっていた事実
開発フロー • Block Design • SystemVerilo g/Verilog • その他IP HW開発、
Vivado(RH EL6.x) Petalinux SW開発、 OSビルド (Ubuntu 14.04) ILA等 FPGA動作 確認 (Windows 7)
ハードウェア開発
採用したIP(すべて無償) • Zynqシステム(Block Design) • AXI DMA(Scatter/Gatherではないノーマル) x 2 •
AXI Peripheralテンプレート • Vivadoのユーティリティ • AXI4 Lite Slave • AXI4 Stream Master/Slave • 10GbE PCS/PMA(10GbE用PHY) • ZC706ボード(Zynq-7000?)だと無償 • GbE PCS/PMA(GbE用PHY) • 無償
CDC対策(1)~あるある対応~ • 今回のプロジェクトでは、ほとんどのCDC部分の通信は、ある 時間で局所的にまとまって発生する。 • 常にやり取りするわけではない。 • Dual Port SRAM(Block
RAM)で対応 • 一定量たまったら、送信先クロックドメインに信号送る • 1bit 2段 F/Fで受けて、応答を返す(ハンドシェイク) • Dual Port SRAMは、Vivadoの合成ツールにてRAM推論させる ようにしました。 • Block Memory Generator等を使用しない
// VivadoにDual Port RAM(BlockRAM)推論させるVerilog記述 reg [31:0] mem [0:1023] // RAM定義
always @(posedge WCLK) if(WEN) mem[WADDR] <= WDAT; always @(posedge RCLK) RDAT <= mem[RADDR];
CDC対策(2)~ちょっと面倒な対応~ • Block RAMほど、ワード数の多いモジュールは必要ない • データが受信されたら、すぐにデータを取り出したい • もちろん、空っぽの時はデータを取り出さないように制御する • SystemVerilogにて、FIFOのF/F記述
• read/write ポインタはグレイコードでクロックドメイン渡し • グレイコードの性質を利用して、満タンおよび空っぽ状態をシンプル に表現 • 150行程度のコード • SystemVerilogの .* 接続を活用
FIFO構造 • 「FPGAの部屋」より拝借 • 同期FIFOと非同期FIFO • http://marsee101.blog19.fc2.com/blog -entry-1085.html ココだけ、次のスライドでコード説明
// 空っぽ always_comb begin rbinnext = rbin + (rinc &
~rempty); rgraynext = (rbinnext>>1) ^ rbinnext; rempty_val = (rgraynext == rq2_wptr); end always_ff @(posedge RST, posedge RCLK) if (RST) rempty <= ’1; else rempty <= rempty_val; //満タン always_comb begin wbinnext = wbin + (winc & ~wfull); wgraynext = (wbinnext>>1) ^ wbinnext; wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZ E-1], wq2_rptr[ADDRSIZE-2:0]}); end always_ff @(posedge RST, posedge WCLK) if (RST) wfull <= ’0; else wfull <= wfull_val;
Block Designの作成(比較的簡単) • 時間をかければ、なんとなく慣れる • 初心者に優しい
されどBlock Design • ブロックが多くなると… • 配線がミスしていないか、チェックするのが大変難しい • Validate Designが問題なくとも、バグが無いことを保証するわけではない •
目視チェックしかない! • RTLシミュレーション…あきらめました • IPごとにVerilogだったりVHDLだったり • Vivadoから出力されるシミュレータスクリプトが前時代的 • Incisiveだとirunコマンドで出して欲しい • RTLシミュレーションは、Zynq VIPで今後何とかなるかもしれない • EDAベンダのシミュレータじゃないと面倒(工数のかかる)ところがいろいろ ありそう
けっこう面倒なBlock Design • Block Designに入れるブロックが多くなると問題が発 生しやすくなった • メンテナンスで開発進行に影響が出るケースがあった • 開発には別のプロジェクトを作成して実行
• 専用プロジェクトで生成したBlock Design(bdファイル)をイ ンポートして、論理合成・配置配線を行う • IPも専用のディレクトリで管理 • ディレクトリ構成が深く、かつ複雑怪奇
IPのアサインおよび設定~AXI DMA~ • シンプルな設定 • アーキ検討でここまで絞り込んだ • Block Designで自動配線 •
何故か割り込みをZynqにつないでくれない • 理由はなんとなく想像がつく • 後工程のDevice Tree作成でようやく気づく • Validate Designで指摘してくれせんかね •
IPのアサインおよび設定~MyIP~ • AXI DMAからAXI Streamバス経由 で来るデータとUser Designとの受 け渡し • VivadoのAXI
Peripheral生成ツール にて作成 • 中のVerilogを編集してUser Design I/Fを作る • AXI Stream側は手動結線 • さらにバスを開き、tstrbとtlastを手動結 線する必要がある • tkeep信号の意味?
IPのアサインおよび設定 ~MyIP レジスタ~ • PLのレジスタ設定をAXI Lite I/Fを持つモジュールに集約 • Block Designにおく
• VivadoのAXI Peripheral生成ツールにて作成 • 中のVerilogを編集する
IPのアサインおよび設定 ~10GbE PCS/PMA~ • Licenseは「Purchase(有償)」だが、ZC706ボードでは無償 • …のハズ?
IPのアサインおよび設定 ~10GbE PCS/PMA~ • Include Shared Logic in example design
• Shared Logicをコアの外に出す (ややこしい) • example designをベースに改造す る • ZC706では無償だが、デフォル ト有償 • ライセンスチェックを行うため、 画面遷移で1分ほど待たされる
IPのアサインおよび設定 ~GbE PCS/PMA~ • Licenseは「Included(無償)」
IPのアサインおよび設定 ~GbE PCS/PMA~ • Include Shared Logic in Core •
Shared Logicも含める • ZC706ボードのSFPポート1個し か使用しないため
GbE PCS/PMAにおけるわたしの凡ミス • Vivado 2016.2に含まれている同IP • v15.2 • Vivado 2016.4に含まれている同IP
• v16.0 • プロジェクト開始時、2016.4のドキュメントを読んでいた • MDIO関係の、1bitのあるレジスタの設定値の定義が反転していた • 2016.2と2016.4で異なる! • 実機デバッグにて発覚するまで1日浪費してしまった • ドキュメントは使うIPのバージョンに気をつけましょう
VivadoのフローとSystemVerilog(1/2) • IP設定が固まったら、基本はtclモード(CUI)でVivadoを実行 • 合成 • 配置配線 • bitファイル生成 •
SDK Export • tclモードには2つのモードがある • プロジェクトモード • 非プロジェクトモード
VivadoのフローとSystemVerilog(2/2) • Cadence Incisive等のシミュレータは、typedef等、共通ファイ ルは共通のコンパイルスコープで実施される。 • よって、package, import等は明確に記述しなくても良い • Vivado非プロジェクトモードも同様
• Block Designはプロジェクトモードで作られる • packageで指定しないと、typedefで指定した型がVivadoで見つけてく れない • 合成以前に、エラボレーションでエラーとなる • やむなく、package, importを明示して使用した
Vivado実行スクリプト #!/bin/sh # 以下のようにシェルスクリプトを実行 # ./run.sh clean; ./run.sh work fpga_top
if [ $# -lt 1 ]; then echo "usage: ./run.sh workdir top_name " exit 1 fi if [ $1 ="clean"]; then TRASH=$(ls -a -I . -I .. -I run.sh -I top.xdc -I pin.xdc) rm -rf ${TRASH} exit 0 fi # set environment source ../env/current.env source /opt/Xilinx/Vivado/2016.2/settings64.sh # Block Design用プロジェクトからのエクスポート vivado -mode tcl -source ../tcl/gen_bd.tcl # ワークディレクトリとトップモジュール設定 export WORKDIR=$1 export TOPMODULE=$2 # Vivado実行 vivado -mode tcl -source ../tcl/syn.tcl
ソフトウェア開発
OS/ソフトウェア • OSはPetalinux 2016.2 • ブートおよびソフトウェア実行はUARTコンソールより実行 • C++/Cアプリ用テンプレートを生成し、作成
メモリ/レジスタダンプ用アプリ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #define
MAP_LENG 0x00100000 void main (int argc, char **argv){ int fd , i; unsigned int *addr; unsigned int offset, count; fd = open( "/dev/mem", O_RDWR ); if ( fd == -1 ){ printf ( "Can't open /dev/mem. ¥n" ); return ; } offset = strtol ( argv[1], NULL, 16 ); count = strtol ( argv[2], NULL, 10 ); addr = mmap ( NULL, MAP_LENG, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset & 0xFFFF0000) ; if ( addr == MAP_FAILED ) { printf( "Error: mmap()¥n" ); } printf (" usage: memdump ADRS(hex) LEN(dec) ¥n" ); for( i=0; i<count; i++){ printf ( "%08X: %08X¥n", ( (offset & 0xFFFFFFFC) + (i * 4) ), ( addr[((offset & 0x0000FFFC) /4 ) + i] ) ); } printf ( "¥n" ); return ; }
メモリ/レジスタライトアプリ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #define
MAP_LENG 0x00100000 void main (int argc, char **argv){ int fd , i; unsigned int *addr; unsigned int offset, data; fd = open( "/dev/mem", O_RDWR ); if ( fd == -1 ){ printf ( "Can't open /dev/mem. ¥n" ); return ; } offset = strtol ( argv[1], NULL, 16 ); data = strtol ( argv[2], NULL, 16 ); addr = mmap ( NULL, MAP_LENG, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset & 0xFFFF0000) ; if ( addr == MAP_FAILED ) { printf( "Error: mmap()¥n" ); } printf (" usage: memwrite ADRS(hex) LEN(dec) ¥n" ); addr[(offset & 0x0000FFFC) / 4] = data; printf ( "%08X: %08X¥n", ( offset & 0xFFFFFFFC ), ( addr[(offset & 0x0000FFFC) /4] ) ); printf ( "¥n" ); return ; }
Petalinuxブート用SDカードイメージ作成 #!/bin/sh PETAPROJ='petaprj' VIVPROJ='fpgaprj' BD_NAME='design_1_wrapper' VIVPROJ_DIR='/home/tethys/work' VIVPROJ_SDK_DIR=${VIVPROJ_DIR}/${VIVPROJ}.sdk source /opt/Xilinx/Vivado/2016.2/settings64.sh source
/opt/Xilinx/petalinux-v2016.2-final/settings.sh #Create Project petalinux-create --force --type project ¥ --template zynq ¥ --name ${PETAPROJ} #Import HDF cd ${PETAPROJ} petalinux-config --get-hw-description=${VIVPROJ_SDK_DIR} #Create new app #petalinux-create -t apps --template c --name myapp #Choice Apps petalinux-config -c rootfs #Build Petalinux LANG=C petalinux-build #Make bood.bin petalinux-package ¥ --boot ¥ --fsbl ./images/linux/zynq_fsbl.elf ¥ --fpga ./images/linux/${BD_NAME}.bit ¥ --u-boot
スクリプト一発で完了させるつもりが… • Device Tree生成で、dtsiファイルに同じモジュールのエントリ が2つ生成される • たぶん、Vivado 2016.2のバグ • 仕方ないのでビルド前の段階で毎回手修正
まとめ • Zynq-7000をスクラッチで開発できた
Reference 1. 小林優, (2016). FPGAプログラミング大全. ISBN 4798047538. 2. FPGAマガジン, (2013).
高速Ethernet x FPGA. ISBN 478984613X 3. FPGAマガジン, (2016). ARMコアFPGA x Linux初体験. ISBN 4789846229 4. Clifford E. Cummings, (2001). Simulation and Synthesis Techniques for Asynchronous FIFO Design. Sunburst Design, Inc. http://www.sunburst- design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf 5. zakii, (2011). RAMのRTL記述. http://zakii.la.coocan.jp/hdl/44_ram_rtl.htm 6. ikwzm, (2016). VivadoをGUIを使わずに実行するためのTclスクリ プト達. http://qiita.com/ikwzm/items/a0120079d2f7f86a5904