入門 · レッスン 10 / 10

RTLからボードへ: フローの全体像

AMD、Altera、Lattice、Gowinの制約ファイル、ピン割り当てとI/O規格、タイミングレポートの読み方、そしてBasys 3とTang Nano 9KでのLチカの実例を解説します。

入門AMDGowinオープンソース45 分更新 2026年11月13日無料期間 2027年1月31日

このレッスンで学ぶこと

  • ピンを割り当て、I/O規格を設定し、クロックを定義する制約ファイルを書ける
  • タイミングレポートを読み、タイミングを満たしたとはどういうことか、ワーストネガティブスラックとは何かを説明できる
  • VivadoでBasys 3に、Yosys、nextpnr、openFPGALoaderでTang Nano 9Kに、設計をビルドして書き込める
  • 初回によくあるエラーを診断できる: 制約のないピン、誤った電圧規格、クロック制約の欠落、書き込めないボード

前提レッスン: メモリ、ブロックRAMとFIFO

モジュールを書き、シミュレーションし、合成ツールがそれをどう扱うかを学びました。このレッスンで輪を閉じます。設計をソースファイルから2枚の実機ボード上で点滅するLEDまで持っていき、まだ書いていない唯一のファイル、制約ファイルを説明します。Digilent Basys 3をVivadoで、Sipeed Tang Nano 9Kをオープンソースフローで扱うので、ベンダーツールと無料ツールが同じ仕事をするところを見られます。レッスン02はフローの概略を説明しました。ここではそれを実行します。

フローをもう一度、今度はファイル付きで

top.v合成配置配線ビットストリームボードnetlistJTAG制約.xdc .sdc .cst .pcfタイミングレポートslack, WNS, fmax
実装フロー。制約ファイルは合成以降のすべての段階で読まれ、タイミングレポートは配線後に生成される。

合成はHDLを、デバイスのプリミティブ、つまりLUT、フリップフロップ、ブロックRAM、I/Oバッファのネットリストに変換します。配置配線は、それぞれがどの物理的なLUTやフリップフロップになり、どの配線がそれらを接続するかを決めます。ビットストリーム生成はその結果をコンフィギュレーションデータに符号化し、プログラマがJTAG経由でチップに送り込みます。シミュレーションはこの経路上にはまったくありません。それは前に行われたものであり、前に行われているべきものです。

制約ファイルは、HDL以外で唯一の入力です。ツールが自力では知りえない2つのことを伝えます。各トップレベルポートがどのパッケージピンに、どの電気規格で接続されているか、そしてクロックがどれだけ速く動くかです。

ベンダー別の制約ファイル

どのベンダーも、同じ情報に対して独自の形式を持っています。

ベンダー ツール ファイル クロック制約 ピン制約
AMD Vivado .xdc create_clock set_property PACKAGE_PIN、IOSTANDARD
Altera Quartus Prime タイミングは.sdc、ピンは.qsf create_clock set_location_assignment、set_instance_assignment
Lattice Radiant、Diamond .pdc(Radiant。合成前は.sdcまたは.ldc)または.lpf(Diamond。ピンとタイミングを一緒に記述) create_clock(Radiant)、FREQUENCY(Diamond LPF) ldc_set_location、LOCATE COMP
Lattice iCE40 Yosysとnextpnr-ice40 .pcf --freqまたは.py制約 set_io
Gowin Gowin EDA、nextpnr-himbaechel ピンは.cst、タイミングは.sdc create_clock IO_LOC、IO_PORT

クロック側はほぼ共通です。AMD、Altera、LatticeはいずれもSynopsys Design Constraints言語を使い、create_clock -period 10.000で100 MHzのクロックを宣言します。ピン側はさまざまですが、常にポート名、ピン名、I/O規格の組に帰着します。

ピンとI/O規格

FPGAのピンは多くの電気規格に設定できます。3.3 V CMOS、2.5 V、1.8 V、1.5 V、いくつかの差動規格などです。規格はボード上でそのピンに配線されているものと一致していなければならず、1つのI/Oバンク内のすべてのピンはバンクの供給電圧と整合していなければなりません。Basys 3では、使うピンはすべて3.3 Vで給電されるバンクにあるので、規格はLVCMOS33です。Tang Nano 9Kでもバンクは3.3 Vです。誤った規格を選ぶと、良くてツールのエラー、悪ければデバイスの損傷なので、記憶ではなくボードのドキュメントから取ってください。

ボードメーカーは、ボード上のすべてのピンを列挙したマスター制約ファイルを公開しています。通常の作業方法は、それをコピーし、使わないものをすべて削除し、ポート名を自分のモジュールに合わせて変更することです。このレッスンの両ボードのピン情報は、それらのファイルから取ったものです。

実例: VivadoでBasys 3

設計はボタン付きのLチカです。LED0が約1.5 Hzで点滅し、LED1が中央ボタンを反映し、SW0が点滅を止めます。Basys 3では、100 MHzの発振器がピンW5、LED0がU16、LED1がE19、中央ボタンBTNCがU18、SW0がV17にあります。

// Blinky plus a button for the Digilent Basys 3.
// LED0 blinks at about 1.5 Hz, LED1 shows the centre button, SW0 pauses the blink.
module top_basys3 (
  input  wire clk,     // 100 MHz
  input  wire btnc,
  input  wire sw0,
  output wire led0,
  output wire led1
);
  reg [25:0] count = 26'd0;

  always @(posedge clk)
    if (!sw0)
      count <= count + 1'b1;

  assign led0 = count[25];   // 100 MHz / 2^26 = 1.49 Hz
  assign led1 = btnc;
endmodule

カウンタはリセットではなく= 26'd0で初期化しており、AMDのパーツではビットストリームがこれを尊重します。スイッチはイネーブルとして直接読んでいます。Lチカならそれで構いません。状態機械を含むものでは、ボタンとスイッチをレッスン08の同期化回路に通すことになります。

制約ファイルbasys3.xdcです。

## Clock: 100 MHz oscillator on W5
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports clk]
create_clock -add -name sys_clk -period 10.000 -waveform {0 5} [get_ports clk]

## LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports led0]
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports led1]

## Centre button and switch 0
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports btnc]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports sw0]

## Configuration bank voltage, needed to silence a DRC warning on this family
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

XDCはTclです。各set_property行は、get_portsで見つけたポートにピンと規格を付けます。create_clock行は、clk上の信号が周期10 ns、立ち上がりエッジ0 ns、立ち下がりエッジ5 nsのクロックであると宣言します。これがないとタイミングツールには照合すべきものがなく、何も伝えないままタイミングを満たしたと報告します。最後の2行は、このファミリでのコンフィギュレーションバンク電圧に関する警告を止めます。

Vivadoでは、パーツxc7a35tcpg236-1向けのプロジェクトを作り、top_basys3.vを設計ソースとして、basys3.xdcを制約として追加し、Generate Bitstreamをクリックします。Vivadoは合成、実装、ビットストリーム生成を順に実行します。同じ手順をTclで書くと次のようになり、バージョン管理に置けるスクリプトになります。

read_verilog top_basys3.v
read_xdc basys3.xdc
synth_design -top top_basys3 -part xc7a35tcpg236-1
opt_design
place_design
route_design
report_timing_summary -file timing.rpt
write_bitstream -force top_basys3.bit

ボードを接続し、Hardware Managerを開き、Open Target、Auto Connect、続いてProgram Deviceでtop_basys3.bitを選びます。Basys 3はJTAGプログラマが電源と同じUSBコネクタ上にあるので、ケーブル1本で両方をまかなえます。LED0が点滅し、LED1がボタンに追従し、SW0を上げると点滅が止まるはずです。

実例: オープンソースフローでTang Nano 9K

Tang Nano 9KはGowin GW1NR-LV9QN88PC6/I5を搭載し、27 MHzの水晶がピン52に、6つのLEDがピン10、11、13、14、15、16に、2つのボタンのうちS1がピン4にあります。LEDとボタンはアクティブLowで、I/Oバンクは3.3 Vです。モジュールはそれに合わせて変わります。

// Blinky plus a button for the Sipeed Tang Nano 9K.
// LEDs and the button are active low on this board.
module top_tangnano9k (
  input  wire       clk,    // 27 MHz
  input  wire       btn_n,  // S1, low when pressed
  output wire [5:0] led_n   // low lights the LED
);
  reg [24:0] count = 25'd0;

  always @(posedge clk)
    count <= count + 1'b1;

  // LED0 blinks at 27 MHz / 2^25 = 0.8 Hz. LED1 follows the button.
  // The remaining LEDs are driven high, which turns them off.
  assign led_n = {4'b1111, btn_n, ~count[24]};
endmodule

ピン制約はGowinのCSTファイルtangnano9k.cstに書きます。

IO_LOC "clk" 52;
IO_PORT "clk" PULL_MODE=UP;
IO_LOC "btn_n" 4;
IO_PORT "btn_n" PULL_MODE=UP;
IO_LOC "led_n[0]" 10;
IO_LOC "led_n[1]" 11;
IO_LOC "led_n[2]" 13;
IO_LOC "led_n[3]" 14;
IO_LOC "led_n[4]" 15;
IO_LOC "led_n[5]" 16;
IO_PORT "led_n[0]" IO_TYPE=LVCMOS33 DRIVE=8;
IO_PORT "led_n[1]" IO_TYPE=LVCMOS33 DRIVE=8;
IO_PORT "led_n[2]" IO_TYPE=LVCMOS33 DRIVE=8;
IO_PORT "led_n[3]" IO_TYPE=LVCMOS33 DRIVE=8;
IO_PORT "led_n[4]" IO_TYPE=LVCMOS33 DRIVE=8;
IO_PORT "led_n[5]" IO_TYPE=LVCMOS33 DRIVE=8;

Gowin向けのオープンソースフローは3つのツールからなります。合成にYosys、配置配線にhimbaechelバックエンドとApiculaデバイスデータベースを使うnextpnr、ビットストリーム書き出しにApiculaのgowin_packです。書き込みはopenFPGALoaderが行います。

yosys -p "read_verilog top_tangnano9k.v; synth_gowin -top top_tangnano9k -json top.json"
nextpnr-himbaechel --json top.json --write top_pnr.json \
  --device GW1NR-LV9QN88PC6/I5 \
  --vopt family=GW1N-9C --vopt cst=tangnano9k.cst
gowin_pack -d GW1N-9C -o top.fs top_pnr.json
openFPGALoader -b tangnano9k top.fs

synth_gowinは、Gowinのプリミティブにマッピングを行うYosysスクリプトです。nextpnrは配線の最後に独自のタイミング見積もりを表示し、そこにはクロックが動作できると見込む最大周波数も含まれます。openFPGALoaderの行はビットストリームをSRAMにロードするので、電源を切ると失われます。代わりにオンボードのフラッシュに書くには-fを付けます。

Gowin自身のツールGowin EDAでの同じフローは、同じCSTファイルと、create_clock -name clk -period 37.037 [get_ports {clk}]を含むSDCファイルを使います。無料ライセンスでこのデバイスをカバーできます。

タイミングレポート

配線後、ツールはフリップフロップ出力からロジックと配線を通って次のフリップフロップ入力に至るすべての経路を検査し、その遅延を宣言したクロック周期と比較します。結果は経路ごとのスラックです。周期から遅延を引き、さらにセットアップ時間とクロック不確定性を差し引いたものです。正のスラックは信号が間に合うことを意味します。負のスラックは間に合わないことを意味し、完璧にシミュレーションできた設計でも、その周波数では誤動作します。

Vivadoのサマリは3つの数値で始まります。WNS(ワーストネガティブスラック)は、最も悪い単一のセットアップ経路のスラックです。TNS(トータルネガティブスラック)は負のスラックすべての合計で、合格からどれだけ遠いかの尺度です。WHS(ワーストホールドスラック)はホールド時間について同じ考え方をしたもので、信号が遅すぎるのではなく早すぎる変化についてのものです。「タイミングを満たした」とは、この3つがすべて0以上であることです。Lチカではカウンタのキャリーチェーンが最長経路で、WNSは正の数ナノ秒になるでしょう。

Quartus Primeは同じ情報をTiming Analyzerで提示し、クロックごとのFmaxサマリと失敗した経路のリストを示します。nextpnrはクロックごとのFmaxの行を表示し、目標に対してPASSかFAILかを示します。タイミングのトピックと中級トラックでは、経路が失敗したときに何をすべきかをさらに深く扱います。

初回によくあるエラー

制約のないポート。Vivadoはデフォルトで、ピン割り当てのないポートがあるとビットストリームの書き出しを拒否し、UCIO-1(制約のないピン)またはNSTD-1(I/O規格なし)という名前のDRCエラーを出します。修正は、欠けている行をXDCに追加することです。制約中のポート名は、led[0]のようなバスのインデックスも含めて、HDLと正確に一致しなければなりません。

存在しないポート。XDCがモジュールにないポートを指定していると、Vivadoは警告して続行するため、制約のタイプミスは、ビルドは通るが何もしない設計を生みます。書き込む前にクリティカル警告を読んでください。

バンクに対して誤ったI/O規格。ツールは同じバンク内のピン間の電圧の衝突を報告します。ここで扱う入門用ボードでは、すべてLVCMOS33です。

アクティブLowの混乱。Tang Nano 9Kでは、1で駆動したLEDは消灯し、ボタンは押されるまで1を読みます。ポート名の_n接尾辞は、それを思い出させるためにあります。

クロック対応ピンでないクロックピン。専用クロック入力は特定のピンにあります。ボード設計者は発振器をそのひとつに置いていますが、汎用ヘッダピンからクロックを入れると、ツールは文句を言うか、配線が悪くなります。ボードが用意したピンを使ってください。

ボードに書き込めない。よくある原因は、順に、USBケーブルが電源専用である、プログラマ用のドライバやudevルールがない、別のプログラムがポートを開いている、ボードがフラッシュブートモードになっている、です。openFPGALoader --detectとVivadoのAuto Connectはどちらも、デバイスがそもそも見えているかどうかを教えてくれるので、ケーブルの問題と設計の問題を切り分けられます。

ビルドは通ったのにLEDが何もしない。クロック制約が実際の発振器と一致していること、カウンタが目に見える周波数を生むのに十分な幅であること、古いビットストリームではなく当該の設計が実際に書き込まれたことを確認してください。それからトップレベルモジュールを、カウンタ幅を減らしたテストベンチに入れ、シミュレーションで点滅するのを見てください。「ボードが壊れている」という報告の大半はそこで終わります。

演習

レッスン08のデバウンサをBasys 3の設計に追加し、BTNCを押すたびに点滅速度が4段階で切り替わるようにし、その設定をLED1からLED4に表示してください。追加のLEDピンはDigilentのマスターXDCで調べる必要があります。ビルドし、タイミングサマリを開き、WNSを書き留めてください。次にクロック制約を5 nsに変えて再ビルドし、200 MHzでも設計がタイミングを満たすかどうかを見てください。Tang Nano 9Kでは、S2と残りのLEDで同じことをし、nextpnrが報告するFmaxを、要求した27 MHzと比較してください。

まとめ

  • 制約ファイルは、HDLでは与えられないものを供給します。各ポートが使うピン、そのI/O規格、クロック周期です。ベンダーごとに形式がありますが、クロック側はほぼ常にSDCです。
  • ピン番号とI/O規格はボードのマスター制約ファイルから取り、バンク電圧の整合を保ってください。
  • タイミングレポートは、すべてのレジスタ間経路をクロック周期と比較します。タイミングを満たしたとはワーストネガティブスラックが0以上であることで、クロック制約がなければ何の意味もありません。
  • VivadoとYosys・nextpnr・Apiculaのフローは同じ仕事をします。一方はGUIとTclスクリプト、もう一方は4つのコマンドです。
  • ボードが何もしないときは、ハードウェアを疑う前に、クリティカル警告、制約の名前、プログラマの接続を確認してください。

さらに読む