Я реализовал некоторый код VHDL для экспорта кодировок состояний FSM во время компиляции, которые могут быть прочитаны Xilinx ChipScope. Эта функциональность протестирована с Xilinx ISE 14.7, iSim 14.7 и QuestaSim 10.2c от Mentor Graphic. Мой проект может быть синтезирован с альтернативным верхним уровнем для ПЛИС Altera, но у Quartus II, похоже, есть проблема с return line.all;
.
Сообщения об ошибках Quartus II (14.0):
- Ошибка (10351): ошибка тела подпрограммы VHDL в sata_PhysicalLayer.vhdl (504): функция «dbg_GenerateEncodings» не всегда возвращает значение
- Ошибка (10346): ошибка VHDL в debug.vhdl (47): формальный порт или параметр «кодировки» должны иметь фактическое значение или значение по умолчанию.
- Ошибка (10657): Ошибка подпрограммы VHDL в sata_PhysicalLayer.vhdl (514): не удалось разработать вызов подпрограммы «dbg_ExportEncoding»
Далее я опишу свой код.
Код VHDL
В проекте используются 3 функции для экспорта кодировок состояний конечного автомата:
- кодировать текущее локальное состояние конечного автомата как двоичное значение -> dbg_EncodeState
(результат этой функции подключается к портам ILA) - преобразовать все состояния локального конечного автомата в строку, разделенную точкой с запятой -> 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 форматирует натуральное число в шестнадцатеричную строку
Дополнительные примечания:
Все файлы vhdl помечены как VHDL-2008.
Мои вопросы:
- Есть ли у кого-нибудь опыт работы с line.all в среде Quartus?
- Есть ли обходной путь?
- Есть ли лучшее решение для выполнения задачи экспорта без использования строк постоянной длины?
Обойти:
Я заключил свою функцию 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 не проверяет функции внутри блока генерации.