前回の#1ではVivado 2024.1をUbuntu 24.04にインストールしました。#2の今回は初歩の定番、LEDチカチカ、略してLチカをやってみたいと思います。Lチカを通してVivadoやFPGAボードの基本的な使い方を学んでいきましょう。FPGAボードはNexys4を使用します。
目次
Vivadoの立ち上げと新規プロジェクト作成
まずは、Vivadoを立ち上げましょう。立ち上げ方はいろいろあると思いますが、Ubuntuのターミナル上で”vivado”と入力します。すると、下記のGUI画面が起動し、Vivadoの立ち上げが完了です。

次に、今回のLチカプロジェクトを作成していきます。”Quick Start”の”Create Project”をクリックします。

New Projectのウィザードが立ち上がるので、”Next”を選択します。

任意のプロジェクト名と保存先を設定します。今回プロジェクト名はBlink_LEDとしました。入力後”Next”を選択します。

プロジェクトタイプを選択します。”RTL Prject”を選択し、”Next”で次へ。

ソースコードの追加を行います。今回はVerilogを使用して作成していきますので、左下の”Target language”がVerilogになっていることを確認し、左上の+マークを押すか、”Create File”を選択します。

すると、Create Source Fileのウィンドウが立ち上がりますので、ファイル名を入力します。今回はプロジェクト名と同じ”Blink_LED”としました。入力後”OK”を押します。

先ほど作成したBlink_LED.vが追加されたので、”Next”を選択します。

次は制約ファイルの追加画面になります。ソースコードの追加と同様に左上の+マークを押すか、”Create File”を選択します。

Create Constraints Fileのウィンドウが立ち上がりますので、任意のファイル名を入力します。今回はBlink_LED_Nexys4としました。(画像は間違っています。。)入力後”OK”を押します。

先ほど作成したBlink_LED_Nexys4.xdcが追加されたので、”Next”を選択します。

次に今回使用するFPGAを選択します。Nexys4にはXC7A100T-1CSG324CというFPGAが搭載されています。この名称で検索し、スピードグレードが-3であるxc7a100tcsg324-3を選択して、”Next”を押します。

最後にプロジェクトのサマリが表示されます。”Finish”を押せばプロジェクトの作成が完了となります。
ソースコードと制約ファイルの作成
ソースコードの作成

続いて、ソースコードの作成に移ります。”Define Module”のウィザードが自動的に立ち上がるので、今回作成するソースコードの入出力を”I/O Port Definitions”に入力します。

今回の入出力は上記のようにしました。
・clk – クロック入力
・btnCpuReset – リセット用ボタンの入力
・led – 16個分のLED出力
入力後、OKを押します。

“Sources”の”Design Sources”に今回作成していくVerilogファイルである”Blink_LED.v”があるので、ダブルクリックで開きます。すると、先ほど入力した入出力が記入された状態のモジュールが作成されていますので、下記のロジックを入力しましょう。
module Blink_LED(
input clk,
input btnCpuReset,
output [15:0] led
);
reg [39:0] counter_reg;
always @(posedge clk or negedge btnCpuReset) begin
if(~btnCpuReset) begin
counter_reg<=0;
end
else begin
counter_reg<=counter_reg+1;
end
end
assign led[15:0]=counter_reg[39:24];
endmoduleカウンタをクロックごとにカウントアップし、カウンタの39~24bit目を今回の出力であるledの15~0bit目に出力するものとなります。

入力が完了したら、左上にある保存ボタンを押して、ソースコードの作成は完了です。
制約ファイルの作成

制約ファイルを作成していきます。”Sources”の”Constraints”にある”Blink_LED_Nexys4.xdc”をダブルクリックして制約ファイルを開き下記を入力します。
## Clock signal
##Bank = 35, Pin name = IO_L12P_T1_MRCC_35, Sch name = CLK100MHZ
set_property PACKAGE_PIN E3 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
##Buttons
##Bank = 15, Pin name = IO_L3P_T0_DQS_AD1P_15, Sch name = CPU_RESET
set_property PACKAGE_PIN C12 [get_ports btnCpuReset]
set_property IOSTANDARD LVCMOS33 [get_ports btnCpuReset]
## LEDs
##Bank = 34, Pin name = IO_L24N_T3_34, Sch name = LED0
set_property PACKAGE_PIN T8 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
##Bank = 34, Pin name = IO_L21N_T3_DQS_34, Sch name = LED1
set_property PACKAGE_PIN V9 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
##Bank = 34, Pin name = IO_L24P_T3_34, Sch name = LED2
set_property PACKAGE_PIN R8 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
##Bank = 34, Pin name = IO_L23N_T3_34, Sch name = LED3
set_property PACKAGE_PIN T6 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
##Bank = 34, Pin name = IO_L12P_T1_MRCC_34, Sch name = LED4
set_property PACKAGE_PIN T5 [get_ports {led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}]
##Bank = 34, Pin name = IO_L12N_T1_MRCC_34, Sch name = LED5
set_property PACKAGE_PIN T4 [get_ports {led[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}]
##Bank = 34, Pin name = IO_L22P_T3_34, Sch name = LED6
set_property PACKAGE_PIN U7 [get_ports {led[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}]
##Bank = 34, Pin name = IO_L22N_T3_34, Sch name = LED7
set_property PACKAGE_PIN U6 [get_ports {led[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}]
##Bank = 34, Pin name = IO_L10N_T1_34, Sch name = LED8
set_property PACKAGE_PIN V4 [get_ports {led[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[8]}]
##Bank = 34, Pin name = IO_L8N_T1_34, Sch name = LED9
set_property PACKAGE_PIN U3 [get_ports {led[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[9]}]
##Bank = 34, Pin name = IO_L7N_T1_34, Sch name = LED10
set_property PACKAGE_PIN V1 [get_ports {led[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[10]}]
##Bank = 34, Pin name = IO_L17P_T2_34, Sch name = LED11
set_property PACKAGE_PIN R1 [get_ports {led[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[11]}]
##Bank = 34, Pin name = IO_L13N_T2_MRCC_34, Sch name = LED12
set_property PACKAGE_PIN P5 [get_ports {led[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[12]}]
##Bank = 34, Pin name = IO_L7P_T1_34, Sch name = LED13
set_property PACKAGE_PIN U1 [get_ports {led[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[13]}]
##Bank = 34, Pin name = IO_L15N_T2_DQS_34, Sch name = LED14
set_property PACKAGE_PIN R2 [get_ports {led[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[14]}]
##Bank = 34, Pin name = IO_L15P_T2_DQS_34, Sch name = LED15
set_property PACKAGE_PIN P2 [get_ports {led[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[15]}]制約ファイルにはFPGAの端子と今回作成したモジュールの入出力を紐づけるように記載する必要あります。したがって、例えばFPGAのどの端子がボード上のどこのLEDと接続されているか知っている必要があります。幸いにものNexys4を制作しているDigilint社から本FPGAボードに対応しているXDCファイルが公開されていますので、今回必要な部分のみ抜粋しています。
digilent-xdc/Nexys-4-Master.xdc at master · Digilent/digilent-xdc · GitHub

入力出来たらこちらも忘れず保存を実施し、終了です。
論理合成とビットストリームの作成

FPAGへ実装するため、左の”Run Implementation”をダブルクリックします。


まだ、論理合成を1度も実施していませんので、論理合成が実施される旨を聞かれているのでOKを押し、次の実行ジョブ数などもデフォルトのままでOKを押します。

Implementationが完了すると、上記のウィンドウが立ち上がります。次はビットストリームの作成に移りますので、”Generate Bitstream”を選択してOKを押します。

ビットストリーム作成にあたり、また同じことを聞かれるので、OKを押します。

ビットストリームの作成が完了すると、完了の旨のウィンドウが立ち上がります。いよいよ作成した回路をFPGAに書き込んでいきますので、”Open Hardware Manager”を選択してOKを押します。
FPGAへの書き込み

“Open Hardware Manager”を選択したため、Hardware Managerの画面になっていると思います。

パソコンとNexys4を接続します。接続後、左下にある”PROGRAM AND DEBUG”の”Open Hardware Manager”配下にある”Open Target”を左クリックし、”Auto Conenect”を押します。

FPGAと接続が完了すると、”Program Device”を左クリックすると、接続されているFPGAが選択できますので、それを選択します。

最後にProgram Deviceのウィンドウが立ち上がるので、先ほど作成したビットストリームファイルが選択されていることを確認して”Program”を押します。すると、今回作成したLチカ回路がFPGAへ書き込まれますので、これにて完了となります。
LEDチカチカ!
無事にチカチカしました!


コメント