【FPGAテストベンチ/検証ノウハウ】テストベンチTEXTIOの使い方 ~応用~ Vivado®ロジックアナライザーでキャプチャしたデータを利用する(VHDL編)

皆さん、TEXTIOを使用してテストベンチを作成していますか?
使いこなしてくるともっと便利に活用したくなりますよね。
今回は応用として、Vivado®ロジックアナライザーでキャプチャしたデータを、VHDLで書かれたテストベンチから読み出してシミュレーションを行う方法を紹介します。
(前回ブログ では、Verilog-HDLで書かれたテストベンチから読みだしてシミュレーションする方法を紹介しました。)
なお、テストベンチTEXTIOの使い方の基本編をご覧になりたい方は、以下のブログをご覧ください。
それでは、はじめましょう。
このブログは「FPGA設計ブログ一覧」の
2. シミュレーションのひとつです。
特別無償開催
目次
掲載している内容は次の条件で動作確認を行っています。
- ・ソースはVHDL 1987文法にて記述
・AMD ザイリンクス社 Vivado® ML Edition 2020.2
・Siemens社 ModelSim® SE-64 2021.3 (VHDL 1987文法 オプションを選択)
出典 : ModelSim® SE-64 2021.3 Project Compiler Settings画面
実機の構成
基板上に次のようなCPUとFPGAの構成があったとします。
Vivado®ロジックアナライザーはCPUインタフェース部分につながっており、その部分のデータをキャプチャするものとします。
図1 実機の構成
テストベンチの構成
先ほどの実機構成をテストベンチで次のように構成したとします。
本来であればCPUのモデルもHDL等で記述してシミュレーションを行いますが、このモデルの代わりにVivado®ロジックアナライザーでキャプチャしたCSVデータを使用してFPGAにアクセスを行います。
図2 テストベンチの構成
信号名 [信号の方向 ] : FPGAから見た信号の意味
cpu_cs [CPU → FPGA] : CPUからのチップセレクト信号 (Lowアクティブ)
cpu_add [CPU → FPGA] : CPUからのアドレス信号 (26bit)
cpu_wr_enbn [CPU → FPGA] : CPUからの書き込み要求信号 (Lowアクティブ)
cpu_wr_data [CPU → FPGA] : CPUからの書き込みデータ (32bit)
cpu_rd_reqn [CPU → FPGA] : CPUからの読み出し要求信号 (Lowアクティブ)
cpu_rd_enbn [CPU ← FPGA] : CPUへの読み出しデータ有効信号 (Lowアクティブ)
cpu_rd_data [CPU ← FPGA] : CPUへの読み出しデータ (32bit)
Vivado®ロジックアナライザーの準備
Vivado®ロジックアナライザーのWaveformにキャプチャする信号をならべて基数を設定します(デフォルトはHEXになっています)。
今回キャプチャする信号は、次の内容です。
なお、Waveformに表示されている信号名は今回テストベンチでは使用しませんが、HDLでは文字の扱いに柔軟性がないため、表示は短くしておいた方が無難です。
信号名を右クリック → Name → Short
出典 : Vivado® ML Edition 2020.2 Hardware Manger画面
波形のキャプチャ
トリガー条件を設定し、テストベンチで使用する波形のキャプチャを実行します。
今回は1024クロック分をキャプチャしています。
キャプチャ波形は次のようになります。
・波形全体
はじめに書き込みアクセスがあり、そのあとに読み出しアクセスが続けて行われています。
出典 : Vivado® ML Edition 2020.2 Hardware Manger Dashboard画面
・はじめの書き込みと読み出し部分のアップ
出典 : Vivado® ML Edition 2020.2 Hardware Manger Dashboard画面
CSV形式での保存
希望する波形のキャプチャができましたら保存します。
File → Export → Export ILA Data を実行します。
出典 : Vivado® ML Edition 2020.2 Hardware Manger Dashboard画面
ダイアログで保存するILA・フォーマット・パスとファイル名を聞いてきますので設定します。今回はフォーマットを「CSV」に設定して保存します。
出典 : Vivado® ML Edition 2020.2 Hardware Manger Dashboard画面
CSV入力ファイルのサンプル
先ほど保存したCSVファイルの中身はこのようになっています。
見やすくするためにフィールド幅を変えて表示していますが、実際はデータとカンマの間にスペースは入っていません。
出典 : Vivado® ML Edition 2020.2 Export ILA Data File
左から3つのフィールドは次の内容になります。
- 「Sample in Buffer」はキャプチャしたときの全体のクロック数です
- 「Sample in Window」は画面分割キャプチャをしたときの分割内でのクロック数です
- 「TRIGGER」は1の所がトリガーのかかった場所になります
左から4つ目以降のフィールドはキャプチャした信号になります。
実行サンプル
以下がTEXTIOを使ってCSVファイルのデータを読み出すテストベンチのサンプルになります。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_textio.all; -- ファイルを扱うためのライブラリ呼び出し
use std.textio.all; -- ファイルを扱うためのライブラリ呼び出し
entity tb_textio_vhdl is
generic (
infile1 : string := "iladata.csv" -- 読み込むファイルのパスとファイル名
);
port (
clk : in std_logic;
rst : in std_logic;
cpu_cs : out std_logic; -- CPUからのチップセレクト
cpu_add : out std_logic_vector(25 downto 0); -- CPUからのアドレス
cpu_wr_enbn : out std_logic; -- CPUからの書き込み要求
cpu_wr_data : out std_logic_vector(31 downto 0); -- CPUからの書き込みデータ
cpu_rd_reqn : out std_logic; -- CPUからの読み出し要求
sim_rd_enbn : in std_logic; -- CPUへの読み出しデータ有効
sim_rd_data : in std_logic_vector(31 downto 0) -- CPUへの読み出しデータ
);
end tb_textio_vhdl;
architecture rtl of tb_textio_vhdl is
file indata1 : text is in infile1; -- VHDL 1987 Syntax
-- file indata1 : text open read_mode is infile1; -- VHDL 1993 Syntax
-- signal fread : std_logic; -- VHDL 2002/2008 Syntax
signal mask_cnt : std_logic_vector(1 downto 0); -- 信号名・基数情報行を読み飛ばすためのカウンタ
signal sib : integer range 0 to 66536;
signal add : std_logic_vector(25 downto 0);
signal csn : std_logic;
signal wren : std_logic;
signal wrdt : std_logic_vector(31 downto 0);
signal rreq : std_logic;
signal rden : std_logic;
signal rddt : std_logic_vector(31 downto 0);
signal end_of_file : std_logic; -- ファイルの読み込み終了フラグ
signal cpu_rd_enbn : std_logic; -- CPUへの読み出しデータ有効
signal cpu_rd_data : std_logic_vector(31 downto 0); -- CPUへの読み出しデータ
signal d_sim_rd_enbn : std_logic;
signal match_rd_data : string(1 to 2) := " "; -- 実機動作とシミュレーションの差分確認フラグ
begin
process(clk,rst)
-- file indata1 : text; -- VHDL 2002/2008 Syntax
variable L : line; -- ライン宣言
variable MARK1 : character := ','; -- 区切り文字識別用
variable v_sib : integer range 0 to 66536 := 0; -- Sample in Buffer (このテストベンチでは確認だけに使用します)
variable v_siw : integer range 0 to 66536 := 0; -- Sample in Window (このテストベンチでは値は使用しません)
variable v_trig : std_logic; -- TRIGGER (このテストベンチでは値は使用しません)
variable v_add : std_logic_vector(27 downto 0); -- CPUからのアドレス
variable v_csn : std_logic; -- CPUからのチップセレクト
variable v_wren : std_logic; -- CPUからの書き込みデータ有効
variable v_wrdt : std_logic_vector(31 downto 0); -- CPUからの書き込みデータ
variable v_rreq : std_logic; -- CPUからの読み出し要求
variable v_rden : std_logic; -- CPUへの読み出しデータ有効
variable v_rddt : std_logic_vector(31 downto 0); -- CPUへの読み出しデータ
begin
if (rst = '1') then
-- fread <= '1'; -- VHDL 2002/2008 Syntax
mask_cnt <= "00";
end_of_file <= '0';
sib <= 0;
add <= (others => '0');
csn <= '1';
wren <= '1';
wrdt <= (others => '0');
rreq <= '1';
rden <= '1';
rddt <= (others => '0');
elsif (CLK'event and CLK = '1') then
-- if (fread = '1') then -- VHDL 2002/2008 Syntax
-- file_open (indata1, infile1, READ_MODE); -- VHDL 2002/2008 Syntax
-- fread <= '0'; -- VHDL 2002/2008 Syntax
-- else -- VHDL 2002/2008 Syntax
if (end_of_file = '0') then -- ファイルの最後でなければ入力ファイルを読み込み
if (not endfile(indata1)) then -- 読み込みファイルが EOF = true でなければ実行
readline(indata1,L) ; -- file宣言した入力ファイルから1ライン読み込み
if (mask_cnt /= "11") then -- csvファイルの最初の2行を読み飛ばす
mask_cnt <= mask_cnt + '1';
else
mask_cnt <= mask_cnt;
end if;
if (mask_cnt = "11") then
-- CSVファイルの信号並びに合わせる
-- VIVADO ロジックアナライザーで基数をHEXに設定した場合には"hread"を使用する
read (L,v_sib ); -- Sample in Bufferを読み込み
read (L,MARK1 ); -- 区切り読み込み(カンマ)
read (L,v_siw ); -- Sample in Windowを読み込み
read (L,MARK1 );
read (L,v_trig); -- TRIGGERを読み込み
read (L,MARK1 );
hread(L,v_add ); -- アドレスをHEXで28bit読み込み
read (L,MARK1 );
hread(L,v_rddt); -- 読み出しデータをHEXで32bit読み込み
read (L,MARK1 );
hread(L,v_wrdt); -- 書き込みデータをHEXで32bit読み込み
read (L,MARK1 );
read (L,v_csn ); -- チップセレクトを読み込み
read (L,MARK1 );
read (L,v_rden); -- 読み出しデータ有効を読み込み
read (L,MARK1 );
read (L,v_rreq); -- 読み出し要求を読み込み
read (L,MARK1 );
read (L,v_wren); -- 書き込みデータ有効を読み込み
-- ファイルから読み込んだ値を各信号に代入
sib <= v_sib;
add <= v_add(25 downto 0); -- 不要な上位2bitを削除
csn <= v_csn;
wren <= v_wren;
wrdt <= v_wrdt;
rreq <= v_rreq;
rden <= v_rden;
rddt <= v_rddt;
end if;
else
-- file_close (indata1); -- VHDL 2002/2008 Syntax
end_of_file <= '1'; -- ファイルの読み出し終了
end if;
end if;
-- end if; -- VHDL 2002/2008 Syntax
end if;
end process;
cpu_add <= add;
cpu_cs <= csn;
cpu_wr_enbn <= wren;
cpu_wr_data <= wrdt;
cpu_rd_reqn <= rreq;
cpu_rd_enbn <= rden;
cpu_rd_data <= rddt;
-- 実機動作とシミュレーションを比較
process(CLK) begin
if (CLK'event and CLK = '1') then
d_sim_rd_enbn <= sim_rd_enbn;
end if;
end process;
match_rd_data <= "- " when ((d_sim_rd_enbn or rreq) = '1') else
"OK" when (sim_rd_data = cpu_rd_data) else
"NG";
end rtl;
シミュレーション実行結果
シミュレーションを実行し、CPUモデルから見た(CVSファイルを読み出した)結果は次のようになります。
※波形の色は筆者が一部変更しています。
※sib 信号は基数をunsignedに設定しています。
・波形全体
出典 : ModelSim® SE-64 2021.3 Wave画面
・はじめの書き込みと読み出し部分のアップ
出典 : ModelSim® SE-64 2021.3 Wave画面
Vivado®ロジックアナライザーでキャプチャした波形と同じようになっていることがわかるかと思います。
おわりに
今回はバスの動きをすべてキャプチャして再現させましたが、例えばバーストで流れてくるデータだけをキャプチャしてそれをシミュレーションで利用するなど、いろいろなことに応用できるかと思います。
最後までご覧いただきましてありがとうございました。
このブログは「FPGA設計ブログ一覧」の
2. シミュレーションのひとつです。