Файл стимула читается в тестовом стенде с помощью TEXTIO
Чтение значений сигнала из файла — это альтернативный способ создания стимулов для тестируемого устройства (DUT). Последовательность тестового стенда и синхронизация жестко запрограммированы в файле стимула, который считывается тестовым стендом VHDL построчно. Это позволяет вам легко изменить шаблон сигнала, который вы хотите подать на тестовый объект.
Иногда у вас есть очень специфический тестовый шаблон или последовательность событий, через которые вы хотите провести тестируемое устройство. Этого можно добиться, указав в файле ASCII значения сигналов, которые должен иметь каждый сигнал, а также относительное время моделирования, в которое они должны изменяться. Роль испытательного стенда VHDL в такой стратегии заключается в считывании данных из файла стимулов и применении значений на входах тестируемого устройства в нужное время.
Эта статья является второй в серии о доступе к файлам в VHDL. Мы рассмотрели, как читать шестнадцатеричные, восьмеричные и двоичные значения из файла в предыдущем сообщении в блоге, вернитесь и прочитайте его, если вы хотите узнать больше о чтении из файла с помощью TEXTIO
библиотека на VHDL.
Этот пост в блоге является частью серии статей об использовании библиотеки TEXTIO в VHDL. Прочтите другие статьи здесь:
Как инициализировать ОЗУ из файла с помощью TEXTIO
Растровое изображение файла BMP, прочитанное с помощью TEXTIO
Тестовый пример
Примером DUT будет мультиплексор с 4 входами (MUX), взятый из одной из моих предыдущих записей в блоге. Это стандартный асинхронный MUX 4-к-1 с шириной данных в один байт. Как это работает, не важно для этой статьи, потому что мы не собираемся проверять результаты, это просто для демонстрационных целей.
Объект MUX показан ниже.
entity mux_4 is port( -- Data in din_0 : in unsigned(7 downto 0); din_1 : in unsigned(7 downto 0); din_2 : in unsigned(7 downto 0); din_3 : in unsigned(7 downto 0); -- Selector sel : in unsigned(1 downto 0); -- Data out dout : out unsigned(7 downto 0)); end entity;
После импорта необходимых пакетов в верхней части файла VHDL мы переходим к объявлению входных сигналов, которые мы собираемся подключить к тестируемому устройству. Как видно из приведенного ниже списка, это схемы из объявления объекта MUX.
signal din_0 : unsigned(7 downto 0); signal din_1 : unsigned(7 downto 0); signal din_2 : unsigned(7 downto 0); signal din_3 : unsigned(7 downto 0); signal sel : unsigned(1 downto 0); signal dout : unsigned(7 downto 0);
Мы используем метод создания объекта для создания экземпляра MUX с меткой «DUT» в верхней части области архитектуры нашего тестового стенда. Сигналы объектов подключаются к сигналам локального тестового стенда с теми же именами, как показано в коде ниже.
DUT: entity work.mux_4(rtl) port map ( din_0 => din_0, din_1 => din_1, din_2 => din_2, din_3 => din_3, sel => sel, dout => dout );
Файл стимула
Файл стимула может иметь множество различных форматов, представленный здесь — это всего лишь пример, который я придумал во время написания этой статьи. Тем не менее, когда вы поймете, как я его создал, вы сможете изменить его в соответствии со своими потребностями.
В приведенном ниже листинге показан полный файл стимула, использованный в этом примере.
# Column description: # wait_time | sel | din_0 | din_1 | din_2 | din3 # Optional console printout 0 ns 0 AA BB CC DD # Setting initial values 10 ns 1 AA BB CC DD # Testing by changing the selector signal 10 ns 2 AA BB CC DD 10 ns 3 AA BB CC DD 10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs 10 ns 3 A2 B2 C2 D2 10 ns 3 A3 B3 C3 D3 10 ns 3 00 00 00 D2 # Changing all unselected inputs 10 ns 3 01 02 03 D2 10 ns 3 11 22 33 D2 1 ns 0 CC DD EE FF # Changing all inputs fast 1 ns 1 DD EE FF CC 1 ns 2 EE FF CC DD 1 ns 3 FF CC DD EE 10 ns 0 00 00 00 00 # Simulation stop
Давайте пока проигнорируем комментарии, они отмечены зеленым цветом и всегда начинаются с символа «#». Каждая строка представляет один временной шаг в моделировании. В каждой строке есть шесть столбцов команд, на самом деле семь столбцов текста, но первые два столбца относятся к одному и тому же элементу данных.
Текстовые столбцы один и два описывают значение времени, на которое симулятор должен приостановиться в этой строке перед применением значений, перечисленных в других столбцах. Таким образом, абсолютное время симуляции при выполнении команды относится к событию, описанному в предыдущей строке. Мы используем только 0, 1 или 10 наносекунд, но это может быть что угодно, 1000 наносекунд или 1000 часов (1000 hr
) в этом отношении.
Остальные пять текстовых столбцов описывают значения сигналов, которые должны подаваться на входы ИУ. Они задаются в виде шестнадцатеричных литералов, а порядок сигналов — sel
. , din_0
, din_1
, din_2
и, наконец, din_3
.
Теперь к комментариям. Есть два типа комментариев; однострочные комментарии и конечные комментарии. Наш испытательный стенд должен относиться к ним по-разному. Однострочные комментарии, например, в начале файла, будут игнорироваться. С другой стороны, завершающие комментарии должны выводиться на консоль симулятора. Мы можем использовать их, чтобы получить подсказки о том, что происходит во время моделирования.
Чтение файла стимула в VHDL
VHDL — не самый лучший язык для обработки текста, но он справляется со своей задачей. Поддержка динамических строк ограничена, и в ней отсутствуют удобные процедуры, например, для удаления или пропуска пробелов. Чтобы облегчить себе задачу, предположим, что файл со стимулами хорошо написан. Давайте позаботимся о том, чтобы всегда был один пробел между текстовыми элементами и один пробел между символом «#» и текстом комментария. Кроме того, в файле стимула нет лишних начальных или конечных пробелов.
PROC_SEQUENCER : process file text_file : text open read_mode is "stimulus.txt"; variable text_line : line; variable ok : boolean; variable char : character; variable wait_time : time; variable selector : sel'subtype; variable data : dout'subtype; begin
Декларативная область PROC_SEQUENCER
процедура показана выше. Во-первых, мы объявляем специальный file
объект, тип обработчика файла VHDL. Затем мы объявляем переменную типа line
. Это просто тип доступа к строке, указатель на динамически выделяемый строковый объект. ok
переменная логического типа предназначена для проверки успешности операций чтения. Наконец, мы объявляем четыре переменные char
, wait_time
, selector
и data
. Эти переменные предназначены для извлечения данных из каждого столбца из каждой строки текста.
while not endfile(text_file) loop readline(text_file, text_line); -- Skip empty lines and single-line comments if text_line.all'length = 0 or text_line.all(1) = '#' then next; end if;
В теле процесса мы переходим прямо в цикл while, который будет перебирать каждую строку текста в файле стимула. readline
процедура присваивает новую строку текста text_line
переменная на каждой итерации этого цикла. После прочтения строки мы проверяем, пуста ли строка и является ли первый символ «#», и в этом случае мы сразу же переходим к следующей строке, используя next
ключевое слово, чтобы пропустить итерацию цикла. Обратите внимание, что мы используем text_line.all
. чтобы получить доступ к строке внутри line
объект.
read(text_line, wait_time, ok); assert ok report "Read 'wait_time' failed for line: " & text_line.all severity failure; hread(text_line, selector, ok); assert ok report "Read 'sel' failed for line: " & text_line.all severity failure; sel <= selector; hread(text_line, data, ok); assert ok report "Read 'din_0' failed for line: " & text_line.all severity failure; din_0 <= data; hread(text_line, data, ok); assert ok report "Read 'din_1' failed for line: " & text_line.all severity failure; din_1 <= data; hread(text_line, data, ok); assert ok report "Read 'din_2' failed for line: " & text_line.all severity failure; din_2 <= data; hread(text_line, data, ok); assert ok report "Read 'din_3' failed for line: " & text_line.all severity failure; din_3 <= data;
Далее следует ряд чтений из text_line
объект. read
и hread
вызовы процедур пропускают начальные пробелы, поэтому нам не нужно выполнять фиктивные чтения для перемещения внутренней начальной позиции чтения внутри text_line
объект. Мы могли бы опустить операторы assert, но я хочу, чтобы симуляция останавливалась в случае сбоя чтения. По крайней мере, в ModelSim симуляция не останавливается автоматически, когда это происходит. Мы назначаем каждую успешно прочитанную переменную соответствующему сигналу тестируемого устройства, за исключением wait_time
переменная, которая не имеет соответствующего входа DUT.
wait for wait_time;
После присвоения значений сигналов ждем указанное время. Нажатие оператора ожидания приводит к тому, что запланированные значения сигнала становятся эффективными с тем же дельта-циклом.
-- Print trailing comment to console, if any read(text_line, char, ok); -- Skip expected newline read(text_line, char, ok); if char = '#' then read(text_line, char, ok); -- Skip expected newline report text_line.all; end if; end loop; finish; end process;
Наконец, когда программа выходит из состояния ожидания, мы ищем дополнительный комментарий в конце text_line
. объект. Любой комментарий выводится на консоль с помощью оператора report после того, как мы удалили символ «#» и следующий за ним пробел с помощью фиктивного чтения.
После обработки последней строки текста из файла стимула цикл while завершается. Есть VHDL-2008 finish
ключевое слово в конце процесса, отвечающее за остановку тестового стенда.
Вывод
Пример тестового стенда выводит текст, показанный ниже, на консоль симулятора при запуске в ModelSim. Мы видим, что это комментарии из файла stimulus. Напечатанные значения времени представляют собой накопленное время симуляции, основанное на задержках в наносекундах, которые были указаны в файле стимула.
# ** Note: Setting initial values # Time: 0 ns Iteration: 1 Instance: /file_stim_tb # ** Note: Testing by changing the selector signal # Time: 10 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Testing by changing all data inputs # Time: 40 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Changing all unselected inputs # Time: 70 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Changing all inputs fast # Time: 91 ns Iteration: 0 Instance: /file_stim_tbf # ** Note: Simulation stop # Time: 104 ns Iteration: 0 Instance: /file_stim_tb # Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98
Форма сигнала для моделирования показана ниже. Он показывает визуальное представление того, как значения из нашего файла стимулов применяются к сигналам в указанные моменты времени моделирования.
Заключительные мысли
Чтение стимулов тестового стенда из файла может быть полезным, если у вас есть очень специфический тестовый шаблон, который вам нужно применить. Весь тестовый стенд не должен контролироваться текстовым файлом, этот пример просто предназначен для демонстрации возможностей доступа к файлам в VHDL.
Однако одна вещь, которую мы не обсудили, — это проверка выходов тестируемого устройства. Наш пример тестового стенда вообще не проверяет выходные данные. Вы можете проверить поведение тестируемого устройства точно так же, как и в полном испытательном стенде VHDL, например, используя поведенческую модель для сравнения. Или вы можете изменить код и файл стимула, включив в него ожидаемые выходные значения. Какую бы стратегию вы ни выбрали, убедитесь, что вы создали испытательный стенд с самопроверкой и не полагаетесь на ручную проверку формы сигнала.
VHDL
- С# с использованием
- C Обработка файлов
- Класс файла Java
- Как инициализировать RAM из файла с помощью TEXTIO
- Как создать самопроверяющийся тестовый стенд
- Java BufferedReader:как читать файл в Java с примером
- Python JSON:кодировать (дампы), декодировать (загружать) и читать файл JSON
- Операции ввода-вывода файлов Verilog
- C — заголовочные файлы
- Что такое треугольный файл?