Вывод отладочной информации в консоль и в файл в Verilog
Очень часто возникает необходимость вывести во время симуляции Verilog-овского файла отладочную информацию на консоль, либо в файл.
Для этого служат системные функции $display
, $write
, $strobe
, $monitor
, а также их аналоги для записи в файл.
$display
выводит на экран указанную строку, после чего добавляет перевод строки. $write
делает то же самое, но без добавления перевода строки. $monitor
осуществляет вывод в консоль при изменении значения любой из указанных в выводе переменных. $strobe
выводит значение в конце временного интервала.
При написании используется C-подобный синтаксис, с модификаторами формата выводимого значения:
Код Verilog:$display("display a:%h b:%h @ %0t", a, b, $time);
%d | Десятичное значение | ||||||||||||||||||||||||
%b | Двоичное значение | ||||||||||||||||||||||||
%h | Шестнадцатиричное значение | ||||||||||||||||||||||||
%o | Восьмиричное значение | ||||||||||||||||||||||||
%c | Символ | ||||||||||||||||||||||||
%f | Число с плавающей запятой | ||||||||||||||||||||||||
%v |
Тип цепи
|
||||||||||||||||||||||||
%m | Имя в иерархии | ||||||||||||||||||||||||
%s | Строка | ||||||||||||||||||||||||
%t | Время |
Сразу оговорюсь: данные функции являются несинтезируемыми, поэтому возможность их использования в синтезируемом файле определяется средой, в которой Вы работаете (например Xilinx ISE "переваривает" их, а вот Altera Quartus - нет). Другая ситуация с файловыми аналогами этих функций. При их применении в ситезируемом модуле среда будет ругаться (еще на уровне открытия файла.
Запись в файл
Для открытия файла служит функции $fopen (имя файла)
, для закрытия - $fclose (имя файла)
.
При открытии файла можно использовать знакомые программистам на C конструкции, указывающие права при открытии: "w"
- на запись, "r"
- на чтение, "r+"
- на чтение и запись, "a"
- на дополнение. К каждому из модификаторов можно добавить "b"
, например "wb"
, указав, что файл является бинарным (хотя в случае с Верилогом в этом нет особого смысла). Впрочем, существуют варианты функции, явно указываюшие на права открытия, например $fopenr
- открыть на чтение.
Запись в файл осуществляется функциями $fdisplay
, $fwrite
, $fstrobe
, $fmonitor
, которые работают аналогично их "консольным" аналогам.
Для чтения памяти существуют функции $readmemb ("файл", идентификатор памяти [,стартовый адрес[,конечный адрес]])
и $readmemh ("файл", идентификатор памяти [,стартовый адрес[,конечный адрес]])
.
Примеры использования этих функций:
Код Verilog:integer file ; reg a, b, c; initial begin file = $fopen("data.dat","wb"); a = b & c ; $fdisplay(file, "Выходные данные: %b", a) ; $fclose(file) ; end
Код Verilog:reg [3:0] memory [15:0] ; initial begin $readmemb("data.bin", memory) ; end
Сразу хочу оговориться: в Verilog не предусмотрена запись бинарного файла (хотя чтение есть). Некоторые предлагают использовать модификатор типа данных %u
. Этот метод работает, но:
- Не во всех средах, например Xilinx ISim этот тип не понимает
- Запись происходит в 32-битном формате, что неудобно для записи 16-битных и 8-битных данных.
Лично я для себя использую такой "лайфхак": я пишу символ с кодом байта который хочу записать:
Код Verilog:$fwrite(foutb,"%c",data[15:8]); $fwrite(foutb,"%c",data[7:0]);
Чтение из файла
С чтением из файла все не так просто... Вроде и функций достаточно, но вот работают они... Например, fread
у меня отказался работать как в Altera Quartus II, так и в Xilinx ISE. Говорил про неверный дескриптор файла при попытке чтения (в Xilinx ISE). Пришлось использовать fgetc
.
Чтение форматированного текста (sscanf
парсит строку, а не читает файл):
Код Verilog:integer file, count; count = $fscanf(file, format, args); count = $sscanf(string, format, args);
Поиск конца файла:
Код Verilog:integer file; reg eof; eof = $feof(file);
Чтение одиночного символа:
Код Verilog:integer file, char; char = $fgetc(file);
Вернуть символ в файловый буфер (при следуещем чтении символ будет прочитан повторно, возвращает символ в случае успеха, и EOF в случае ошибки):
Код Verilog:integer file; reg [7:0] char, r; r = $ungetc(char, file);
Прочитать строку:
Код Verilog:integer file, r; reg [n*8-1:0] string; r = $fgets(string, file);
Узнать позицию в файле:
Код Verilog:integer file, position; position = $ftell(file);
Установить позицию в файле:
Код Verilog:`define SEEK_SET 0 `define SEEK_CUR 1 `define SEEK_END 2 integer file, offset, position, r; r = $fseek(file, 0, `SEEK_SET); /* Начало*/ r = $fseek(file, 0, `SEEK_CUR); /* Нет эффекта */ r = $fseek(file, 0, `SEEK_END); /* Конец файла */ r = $fseek(file, position, `SEEK_SET); /* Предыдущее значение */
Чтение бинарных данных:
Код Verilog:integer r, file, start, count; reg [15:0] mem[0:10], r16; r = $fread(file, mem[0], start, count); r = $fread(file, r16);
Оставьте свой комментарий
Войдите, чтобы оставлять комментарии
Оставить комментарий как гость