コンパイル時に FSM ステート エンコーディングをエクスポートする VHDL コードをインプリメントしました。これはザイリンクスの ChipScope で読み取ることができます。この機能は、Xilinx ISE 14.7、iSim 14.7、Mentor Graphic の QuestaSim 10.2c でテストされています。私のデザインは、アルテラ FPGA の代替トップレベルでも合成できますが、Quartus II には問題があるようreturn line.all;
です。
Quartus II (14.0) エラー メッセージ:
- エラー (10351): sata_PhysicalLayer.vhdl (504) での VHDL サブプログラム本体エラー: 関数 "dbg_GenerateEncodings" が常に値を返すとは限らない
- エラー (10346): debug.vhdl(47) での VHDL エラー: 正式なポートまたはパラメーター「エンコーディング」には、実際の値またはデフォルト値が必要です
- エラー (10657): sata_PhysicalLayer.vhdl(514) での VHDL サブプログラム エラー: サブプログラム "dbg_ExportEncoding" への呼び出しを作成できませんでした
以下では、私のコードについて説明します。
VHDL コード
この設計では、3 つの関数を使用して FSM 状態エンコーディングをエクスポートします。
- 現在のローカル FSM ステートをバイナリ値としてエンコード -> dbg_EncodeState
(この関数の結果は ILA ポートに接続されます) - ローカル FSM のすべての状態をセミコロンで区切られた文字列に変換します -> dbg_GenerateEncodings
- この文字列をフォーマットし、その要素をトークン ファイルに書き込みます -> dbg_ExportEncoding
(この関数はパッケージにあります)
FSM 宣言:
TYPE T_STATE IS (
ST_HOST_RESET,
ST_HOST_SEND_COMRESET,
ST_HOST_SEND_COMRESET_WAIT,
[...]
ST_HOST_SEND_ALIGN,
ST_HOST_TIMEOUT,
ST_HOST_LINK_OK
);
-- OOB-Statemachine
SIGNAL State : T_STATE := ST_HOST_RESET;
SIGNAL NextState : T_STATE;
ローカル関数 - エンティティ関数ごと:
function dbg_EncodeState(st : T_STATE) return STD_LOGIC_VECTOR is
begin
return to_slv(T_STATE'pos(st), log2ceilnz(T_STATE'pos(T_STATE'high) + 1));
end function;
function dbg_GenerateEncodings return string is
variable l : STD.TextIO.line;
begin
for i in T_STATE loop
STD.TextIO.write(l, str_replace(T_STATE'image(i), "st_host_", ""));
STD.TextIO.write(l, ';');
end loop;
return l.all;
end function;
グローバル関数 - debug.pkg.vhdl で定義:
impure function dbg_ExportEncoding(Name : STRING; encodings : string; tokenFileName : STRING) return BOOLEAN is
file tokenFile : TEXT open WRITE_MODE is tokenFileName;
variable cnt, base : integer;
variable l : line;
begin
report "Exporting encoding of '" & Name & "' to '" & tokenFileName & "'..." severity note;
report "dbg_ExportEncoding: '" & encodings & "'" severity note;
-- write file header
write(l, "# Encoding file for '" & Name & "'"); writeline(tokenFile, l);
write(l, "#"); writeline(tokenFile, l);
write(l, "# ChipScope Token File Version"); writeline(tokenFile, l);
write(l, "@FILE_VERSION=1.0.0"); writeline(tokenFile, l);
write(l, "#"); writeline(tokenFile, l);
write(l, "# Default token value"); writeline(tokenFile, l);
write(l, "@DEFAULT_TOKEN="); writeline(tokenFile, l);
write(l, "#"); writeline(tokenFile, l);
-- write state entires
cnt := 0;
base := encodings'left;
for i in encodings'range loop
if encodings(i) = ';' then
-- Leave the str_trim call in!
-- Otherwise, the new parser of ISE 14.7 fails to slice properly.
write(l, str_trim(encodings(base to i-1)));
write(l, character'('='));
write(l, raw_format_nat_hex(cnt));
writeline(tokenFile, l);
cnt := cnt + 1;
base := i+1;
end if;
end loop;
file_close(tokenFile);
return true;
end function;
コードの最後の部分は、エクスポート関数を呼び出すエンティティ内のダミー定数です。
CONSTANT test : boolean := dbg_ExportEncoding("OOBControl (Host)", dbg_GenerateEncodings, MY_PROJECT_DIR & "CSP/FSM_OOB_Host.tok");
使用される補助機能:
- log2ceilnz(x) は、x シンボルをバイナリでエンコードするために必要なビットを計算します。
- to_slv はすべてを std_logic_vector に変換します。この場合、slv への整数
- str_replace は文字列を文字列に置き換えます
- str_trim は、str'low から最初に出現する NUL までの文字列を返します。
- raw_format_nat_hex は、自然から 16 進文字列にフォーマットします
追記事項:
すべての vhdl ファイルは VHDL-2008 としてマークされています。
私の質問:
- Quartus 環境で line.all を使用した経験のある人はいますか?
- 回避策はありますか?
- 一定の長さの文字列を使用せずにエクスポート タスクを達成するためのより良い解決策はありますか?
回避策:
関数 dbg_GenerateEncodings を生成ステートメントでラップしました。
genXilinx : if (VENDOR = VENDOR_XILINX) generate
function dbg_GenerateEncodings return string is
[...]
constant test : boolean := dbg_ExportEncoding("OOBControl (Host)", dbg_GenerateEncodings, MY_PROJECT_DIR & "CSP/FSM_OOB_Host.tok");
begin
end generate;
XST とは対照的に、Quartus は生成ブロック内の関数をチェックしません。