ほぼ積読になっていたFPGAプログラム大全Xilinx編第2版を改めてやり直してみる。
進め方
- 例題はそのままコピーしても面白くないので、できるだけSystemVerilogにしてみる
- Windows11 + vivado2025.1
- Zybo(初代)
第1章
ツールの概要などなのでいまはさらっと読み流す。Vitisに取り組むあたりでもう一度読んだ方がいいかも。
第2章
LED点灯回路とディスプレイ表示回路の作成。
LED点灯回路
- システムクロックを分周して約2Hzを作りLEDの点灯色を変える。初代Zyboには多色LEDがないため、点灯パターンを変化させる(サポートサイトで初代zybo向けに提供されるxdcをそのまま利用)
- プッシュスイッチで切り替え速度を変化させる。チャタリング防止回路を追加する
- 非同期のボタン入力を40Hzでサンプル&シフトさせて初段ffと次段ffの値を比較して、立ち上がりエッジを検出する
ディスプレイ表示回路
- xilinx標準ライブラリのMMCMでピクセルクロックを生成。元々パスに入っているため、明示的にソースコードを追加しなくて良い
- digilent社製IPでHDMI表示制御を行う
- ディスプレイに接続しても何も表示されない→第3章へ(これは筆者によって意図されたシナリオではなく、何らかの記述の問題)
第3章
- vivadoシミュレータの使い方
- Verilog/SystemVerilogの言語仕様で、ファイルデスクリプタはinteger型と決められている
- ディスプレイ表示回路をシミュレーションしてみるとdisp_enable信号が不定になっている
第2章のデザインでディスプレイに表示されない問題の解析
wireとlogicの違い
SystemVerilog置き換えによりdisp_enableを、
// wire disp_enable = (VBLANK <= VCNT) && (HBLANK-10'd1 <= HCNT) && (HCNT < HPERIOD-10'd1);
logic disp_enable = (VBLANK <= VCNT) && (HBLANK-10'd1 <= HCNT) && (HCNT < HPERIOD-10'd1);
のように記述した。ピクセルクロックでカウントされるHCNT,VCNTと定数値を比較、有効領域においてイネーブルを生成する意図であるが、
- VerilogHDLにおけるwireでは宣言+継続代入(assign)を同時にできる
- SystemVerilogにおけるlogicでは宣言と継続代入(assign)は同時にできない
そのため、シミュレーション開始時(HCNT=X, VCNT=X)に一度だけdisp_enableの値が評価された結果、disp_enable=Xになってしまったということのようだ。従って、下記のように書き換える。
// wire disp_enable = (VBLANK <= VCNT) && (HBLANK-10'd1 <= HCNT) && (HCNT < HPERIOD-10'd1);
logic disp_enable;
assign disp_enable = (VBLANK <= VCNT) && (HBLANK-10'd1 <= HCNT) && (HCNT < HPERIOD-10'd1);
disp_enable以外も同様の箇所rgb0,rgb1,hcntendを修正する。
定数値のlocalparam化
誤動作は引き起こさないが、定数信号は定数であることを明示するためlogicではなくlocalparamにするのが良いとのこと。
//logic [9:0] HBLANK = HFRONT + HWIDTH + HBACK;
//logic [9:0] VBLANK = VFRONT + VWIDTH + VBACK;
localparam [9:0] HBLANK = HFRONT + HWIDTH + HBACK;
localparam [9:0] VBLANK = VFRONT + VWIDTH + VBACK;
第4章
- FPGA内部にILA(Integrated Logic Analyzer)を搭載
- ILAとユーザ回路の観測対象信号を接続、指定されたサンプリングクロックで値をILA内蔵BRAMに格納
- 結果をコンフィグレーション用MicroUSBケーブルでPCに転送し、取得した波形はVivadoで確認可能
- 指定した信号の指定した変化でトリガをかける。複数条件を設定し、それらのAND,ORなどでトリガをかけられる
- Window:トリガ成立時の波形を何個取得するか
- 特定のHCNT,VCNTでトリガをかけておけば、Windowフレーム数分の波形を取得可能。ただし、その分サンプリング点数は減る
- Window data depth:Windowあたりサンプリングする回数
- Trigger position:Window内のトリガ位置=トリガ成立前にサンプルする点数
- Capture: 指定した条件に合致したサイクルのみを取得する
- 特定のHCNTをキャプチャ条件に設定すると、列方向に波形を取得してくれる
- トリガ条件との関係はもう少し調べてみる。トリガ成立後、キャプチャ条件にマッチしたサイクルを取得していき、Window data depth分のサンプリングで終了