Вы находитесь на странице: 1из 23

(-) Нет ответа

(!) Обратить внимание


(?) Требует проверки
+ Проверено
Не уверен / Хрен Знает / Самое главное / Отсебятина
Обычный текст Ctrl+Alt+0
!! Убедительная просьба !!
Если копируете огромные полотнища текста, выделяйте самое главное цветом,
иначе на экзамене замучаетесь ответы выискивать
Verilog
+ 1. ESL уровень проектирования. TLM-модели.
ESL – это уровень уровень описания описания моделей, который который по абстракции
находится над RTL уровнем и применяется для проектирования hardware и software. К этому уровню
относятся относятся поведенческие (до деления на HW/SW) и архитектурные модели цифровых
устройств.

Преимущества ESL:
● повышение уровня абстракции представления системы;
● возможность возможность использования использования более высокого высокого уровня для
reuse-проектов;
● поддержка непрерывной цепи проектирования, начиная с верхнего абстрактного уровня

Основы методологии TLM


Основной концепцией TLM является создание модели уровня детализации достаточной для
решения отдельной задачи проектирования компонентов системы.
Системная архитектурная модель (SAM) - эта модель, которая является средством коммуникации
между группами проектировщиков алгоритмов, программного обеспечения и аппаратуры.

+ 2. Обзор языков проектирования SoC


SystemVerilog – первый язык описания и верификации аппаратуры (HDVL), который является
расширением стандарта IEEE 1364 Verilog-2001 [25] и позволяет значительно повысить
производительность проектирования состоящих из большого числа вентилей, с большой
нагруженностью шины проектов. Стандарт : IEEE Std. 1800-2005 SystemVerilog (Accellera).
SystemVerilog предназначен главным образом для создания непрерывного процесса проектированя
SoC, начиная от поведения и заканчивая GDSII-описанием. Тем не менее SystemVerilog также
поддерживает создание TL-моделей. Такое совпадение свойств верификации между SystemC и
SystemVerilog является основой для связей между системным уровнем и реализацией кристалла.
SystemVerilog’sDirect Programming Interface (DPI) позволяет вызывать функции C/C++/SystemC и
наоборот, выполнять совместное моделирование (рис. 1.5) Verilog-моделей с SystemVerilog и SystemC
блоками. SystemVerilog поддерживает полную среду верификации, используя Constraint Random
Generation, Assertion Based Verification и Coverage Driven Verification [24].
Он может применен для HW-проектирования и верификации; SystemVerilog может быть частью
среды Verilog or VHDL TestBench (TB), частью проекта или внешнего модуля. Например, проектировщик
может использовать возможностности Random Generation, включив некоторые из свойств SystemVerilog
Random в текущем TB без необходимости целой среды верификации. Таким же образом инженеры
верификации могут включить некоторые ассерции, как часть полного симулятора кристалла, для
верификации правильности шины или протоколов.

VHDL – это аббревиатура от английского выражения VHSIC Hardware Description Language. В свою
очередь, VHSIC происходит от названия программы Very High Speed Integrated Circuit (высокоскоростные
интегральные схемы). Эта программа, финансированная Министерством Обороны США, ставила своей
целью развитие нового поколения высокоскоростных интегральных схем. Первая версия языка была
представлена в 1985 г. Впоследствии он был передан IEEE для стандартизации. В 1987 г. язык был
утвержден как стандарт IEEE 1076–1987. Через пять лет он был рассмотрен повторно, в результате чего
новая версия 1076-93 [25] содержит ряд дополнительных возможностей.
Следующие версии стандарта были выпущены в 2000 и 2002 годах [26].
VHDL может быть использован для создания функциональных и RTL-моделей, пользуется
популярностью среди специалистов по автоматизированному проектированию (CAD) электронных
систем [27-39]. Для синтеза был разработан пакет IEEE 1164. На практике каждый крупный
производитель систем автоматизированного проектирования поддерживает VHDL.

Verilog – язык описания аппаратуры, разработан в 1985 г. Филиппом Мурби (Philip Moorby) [40],
нуждавшимся в простом, наглядном и эффективном способе для описания цифровых схем,
моделирования и анализа их функционирования. Язык становится собственностью Gateway Design
Automatiion, а затем Cadence Design Systems. Первый стандартVerilog появляется IEEE в 1995 г .
Последнее обновление языка выполнено в 2005 г. [42]. Verilog имеет такую же, а может и большую,
популярность, как и VHDL, широко используется в промышленности при проектировании ASIC-устройств.

+ 3. История создания языка Verilog, классификация моделей в Verilog.


● 1984 -1985 гг. Филип Мурби (Philip Moorby) разрабатывает язык Verilog, который принадлежит
фирме Gateway Design Automatiion
● 1985-1987гг. Рост популярности Verilog.
● 1990г. Фирма Cadence покупает Gateway и делает язык Verilog общедоступным
● 1993г. 85% всех ASIC-проектов разрабатывается с помощью Verilog
● 1995г. Создается IEEE-1364-стандарт языка Verilog
● 2000г. Более 10000работчиков SUN, Apple и Motorola работают на Verilog
● 2001г. Стандарт 1364- 2001 “Verilog- 2001”.
В Verilog существует 3 вида моделей:
● Вентильная
● Поведенческая
● Dataflow
● транзисторная
+ 4. Классификация типов данных языка Verilog, их значения, область применения,
массивы, векторы.
Verilog содержит два базовых типа данных: wire и reg.
Оба эти типа могут принимать 4 возможные значения при симуляции Verilog программы: 0, 1, X, Z.
Х — «неизвестное значение». Это значение используется только для симуляции, в реальной
аппаратуре будет 0 или 1.
Z — «состояние высокого сопротивления», то есть отсутствие сигнала.
В Verilog используются следующие типы данных:
● Регистровый класс
○ reg [range] list_of_identifiers;
○ integer list_of_identifiers; // 32 разряда, знак.
○ real list_of_identifiers;
○ time list_of_identifiers; // 64 разряда, беззнак
○ realtime list_of_identifiers;
● Класс цепи
○ wire/tri – линия
○ wand/triand и wor/trior – линии с И и ИЛИ элементом
○ supply0, supply1, tri0, tri1, trireg – описание элементов низкого уровня

+ 5. Системные задачи и функции для управления процессом моделирования и


вывода сообщений.
Формат записи(начинаются с $)
● display, write - Вывод информации на монитор
● fdisplay, fwrite - Запись информации в файл
● strobe, fstrobe - Вывод информации на монитор/запись данных
● monitor, fmonitor - Вывод информации на монитор, запись информации в файл
● time, realtime - Текущее время симуляции
● finish - Выход из режима симуляции
● stop - Останов в режиме симуляции
● setup - Установить проверку времени
● hold, width - Установить проверку по времени для параметров hold/width
● setuphold - Установить проверку по времени для параметров hold/setup
● readmemb, readmemh - Читает память данными из файла симуляционного паттерна
● sreadmemb, sreadmemh - Загружает память данными из файла симуляционного паттерна
● getpattern - Обработка файла симуляционного паттерна
● history - Распечатать историю выданных команд
● save, restart, incsave - Сохранение, перезапуск, частичное сохранение
● scale - Подстройка параметров временной шкалы по параметрам из другого модуля
● scope - Переключение на соответствующий уровень иерархии
● showscopes - Полный список поименованных блоков, заданий, модулей
● showvars - Показать переменные

+ 6. Вентильные Verilog-модели.
Модели вентильного уровня задаются логическими элементами и соединениями между ними.
Данный вид моделей не содержит задержек. Вентильный уровень – это наиболее низкий из
возможных в языке Verilog уровней абстракции. При разработке моделей на этом уровне
проектировщик оперирует такими понятиями, как МОП-транзистор, КМОП-транзистор и т.п. [7; 19; 22].
Средства синтеза, разработанные для интегральных микросхем FPGA-типа, не позволяют синтезировать
логические цепи на базе моделей вентильного уровня. В то же время такие модели полезны для
понимания и исследования физических процессов, протекающих в цифровых цепях.

+ 7. Dataflow-модели в Verilog
Dataflow - это более высокий уровень описания моделей по сравнению с вентильным. Dataflow
модели - описывают процесс изменения данных при их передаче между регистрами.
Основной конструкцией такого уровня моделей является оператор непрерывного назначения
assign (continuous assignment). Данный оператор всегда активен, т.е. как только один из операндов(с
правой стороны) изменяет свое значение, вычисляется новое значение выражения. Синтаксис:
assign [drive_strength] [delay] net_value = expression {,net_value =
expression};
где net_value - скалярная или векторная величина класса net (цепь) или конкатенация этих
элементов, где не допускается применение переменных класса register.

В выражении expression могут быть использованы операнды классов net и register, или вызов
функции.
● assign out=i1&i2;
● assign addr[15:0]=addr1[15:0]^addr2[15:0];
● assign {c_out, sum[3:0]}=a[3:0]+b[3:0]+c_in;
В Verilog имеется возможность выполнять декларацию линии в одном операторе и присваивать
ей значение:
● Обычная форма
wire out;
assign out = i1 & i2;
● Упрощенная форма
wire out = i1 & i2;
+ 8. Поведенческие модели в Verilog
Поведенческие модели – это модели высокого уровня, которые описывают алгоритм
функционирования устройства без детализации на логические вентили или пути передач данных.
Строятся на базе операторов initial и always.
Verilog содержит два вида блоков, которые могут производить вычисления: «initial»-блок и
«always»-блок.
● «initial»-блок определяет, какие действия должны быть сделаны при старте программы. Этот
блок не является синтезирующим и обычно используется для тестирования.

● Блок “always” используется для задания действий, которые будут выполняться периодически
или при определенных уровнях сигнала.

+ 9. Управление процессом выполнения операторов в Verilog (условный оператор,


операторы выбора, циклы).
Лучше своими словами описать
Условный оператор предназначен для организации ветвящихся структур в поведенческих блоках
(always и initial). Его синтаксис представлен ниже:
if (Логическое_Выражение)
begin
// Блок_операторов_1
end
else
begin
// Блок_операторов_2
end
Если Логическое_Выражение равно «ИСТИНА», то выполняется Блок_операторов_1, в противном
случае – выполняется Блок_операторов_2. Следует помнить, что в языке Verilog, подобно языку Си,
логическое значение «ИСТИНА» соответствует 1, а логическое значение «ЛОЖЬ» соответствует 0. Таким
образом, существует возможность в записи условного оператора вместо логических выражений
использовать арифметические выражения. В этом случае Блок_операторов_2 выполняется, если
результатом вычисления арифметического выражения будет 0, при любом другом результате
вычисления арифметического выражения (не обязательно 1) будет выполняться Блок_операторов_1.

Синтаксис оператора выбора case в языке Verilog представлен ниже:


case (Выражение)
Альтернатива1: Оператор1;
Альтернатива2: Оператор2;
Альтернатива3: Оператор3;
...
default: Оператор_по_умолчанию;
end case;
Все Операторы могут представлять собой как простые единичные операторы, так и сложные
операторы (последовательности простых операторов, заключенные в операторные скобки begin ... end
или fork ... join). Альтернативы могут включать несколько значений того же типа данных, что и
Выражение, перечисленных через запятую. При выполнении оператора выбора case производится
сравнение Выражения с Альтернативами в порядке их следования. Для первой встретившейся
Альтернативы, включающей значение, совпадающее со значением Выражения, выполняется
соответствующий оператор или блок операторов, а последующие альтернативы при этом игнорируются.
Если Выражение не входит ни в одну из Альтернатив, то выполняется Оператор_по_умолчанию.
Кроме базового оператора выбора case, в языке Verilog представлены также две его модификации
casex и casez. Если в Альтернативе оператора casex присутствует значение разряда x, то этот разряд
интерпретируется как отсоединенный разряд и значение данного разряда в Выражении игнорируется.
Аналогичным образом функционирует оператор casez, но значение x, определяющее отсоединенные
разряды в альтернативах, заменяется значением z.

Циклические операторы языка Verilog размещаются внутри поведенческих блоков initial и always.
Цикл «пока» в языке Verilog описывается ключевым словом while. Синтаксис:
while (Логическое_Выражение)
Оператор_Тело_Цикла;
Тело цикла будет выполняться, пока выполняется условие. Если условие становится ложным, то
выполнение цикла, прекращается. Очевидно, что тело корректного цикла «пока» обязательно должно
содержать изменение хотя бы одного сигнала, входящего в Условие_Выхода. В противном случае от
итерации к итерации значение условия не будет изменяться и цикл становится бесконечным.
Исключение составляют случаи, когда Условие_Выхода привязано к внешнему источнику событий
(например, содержит входной порт модуля либо сигнал, драйвером которого является другой процесс,
либо ссылку на временные параметры).
Цикл с параметром общего вида описывается при помощи ключевого слова for. При описании
устанавливаются:
● начальное значение параметра;
● условие выхода из цикла;
● оператор блокирующего присваивания, задающий изменение параметра на каждой итерации.
for ( Начальное_Значение_Параметра; Условие_Выхода; Изменение_Параметра)
begin
Тело_Цикла;
end
Следует также заметить, что в языке Verilog, как и в языке Си, разрешается изменение параметра
внутри тела цикла.
Кроме цикла for, в языке Verilog представлена еще одна форма цикла с параметром – цикл repeat.
Цикл repeat используется в тех случаях, если необходимо выполнить тело цикла определенное
фиксированное число раз. Формальный синтаксис цикла repeat приведен ниже:
repeat (Число_Итераций)
begin
Тело_Цикла;
end
При поведенческом описании оборудования бесконечный цикл является очень полезной и
распространенной конструкцией, так как прекращение основного цикла работы устройства обычно
осуществляется отключением его от сети питания, что является внешним воздействием по отношению к
устройству. Бесконечный цикл начинается ключевым словом forever, его формальный синтаксис
представлен ниже:
forever
Тело_Цикла;
При использовании бесконечных циклов следует обращать внимание на наличие в теле цикла
какого-либо временного управления.
Бесконечный цикл, как и любой другой цикл, можно искусственно прервать при помощи
оператора disable.

+ 10. Блокирующие и неблокирующие операторы, внутриоператорный контроль.


В языке Verilog представлено 2 типа операторов присваивания, различающихся механизмом
установки нового значения сигнала: блокирующий оператор присваивания и неблокирующий оператор
присваивания. Операторы присваивания, использующиеся в поведенческих конструкциях, т.е. в блоках
always, initial и в теле процедур или функций, в языке Verilog называют процедурными (в отличие от
оператора assign, который является элементом структурной модели устройства).
Процедурное присваивание может использоваться для изменения значений сигналов типа reg,
integer, real, time, а также элементов памяти.
Кроме того, допускается изменение значений отдельных битов либо диапазонов битов в сигналах
перечисленных типов, например:
reg01[6:3] = 4'b1010;
Операторы блокирующего присваивания обозначаются литералом « = » и выполняются в том
порядке, в котором они определены в блоке последовательных операторов (initial или always). До
окончательного выполнения оператора блокирующего присваивания (т.е. до момента изменения
сигнала) выполнение последовательных операторов, следующих за рассматриваемым,
приостанавливается («блокируется»)
Очевидно, что рассмотренное в предыдущем разделе блокирующее присваивание не позволяет
осуществлять параллельные вычисления внутри одного поведенческого блока. Параллельность
вычислений достигается использованием неблокирующего оператора присваивания, который не
останавливает работу программы до своего окончательного выполнения. Неблокирующее
присваивание задается парой символов <=.

+ 11. Операторы assign/deassign и force/release


assign/deassign
Процедурный оператор непрерывного назначения имеет следующий формат:
assign variable = expression;
Когда симулятор встречает в коде процедурного блока данный оператор, то он отвергает любые
другие процедурные назначения переменной variable и выполняет присваивание значения выражения
expression переменной variable.
В отличие от обычного оператора непрерывного назначения действие процедурного оператора
непрерывного назначения может быть отменено с помощью оператора deassign.
Формат оператора
deassign: deassign variable;
Оператор deassign отменяет действие ранее встретившегося в коде процедурного оператора
непрерывного назначения assign в отношении переменной variable.

Процедурные операторы force и release


Процедурный оператор force имеет следующий формат:
force net_or_variable = expression;
Данный оператор позволяет в процедурном блоке присвоить значение выражения expression
любого типа переменной или сети слева от знака равенства («=»). При этом отвергаются любые другие
назначения переменной.
Оператор release отменяет действие оператора force. Оператор release имеет следующий формат:
release net_or_variable;

(?) 12. Реализация подпрограмм в Verilog. Задачи(Task) и функции(function).


Язык Verilog включает два типа независимых фрагментов кода (подпрограмм), обеспечивающих
возможность реализовать декомпозицию программы: функции (function) и задачи (task):

Задачи (task) предназначены для выполнения каких-либо общих процедур в нескольких


различных местах описания и разбиения больших участков кода на малые. Из приведенного далее
примера можно видеть, что по синтаксису и способу описания интерфейса задачи подобны модулям:
task <идентификатор задачи>; <описание интерфейса>; begin
<процедурные присваивания/операторы>;
end endtask
Функции (function). Для создания подпрограммы-функции необходимо воспользоваться парой
ключевых слов function и endfunction. Описание функции может размещаться в произвольном месте
модуля, вызывающего данную функцию. Обязательным условием объявления функции в языке Verilog
является наличие хотя бы одного входного параметра (аргумента). Для определения возвращаемого
функцией результата следует разместить в ее теле оператор присваивания, в котором имя изменяемого
сигнала совпадает с именем текущей функции:
function <тип результата> <идентификатор функции>; <перечень входных параметров>;
//должен присутствовать как минимум один входной параметр begin
<процедурные присваивания/операторы>; //определение возвращаемого функцией результата
<идентификатор функции> = <возвращаемый результат>; end
endfunction

+ 13. Библиотека PLI. Структура и область применения.


Программный интерфейс PLI (рис. 8.1) используется для:
– создания дополнительных системных задач и функций: задач мониторинга, генерации тестов,
отладки фрагментов программы;
– построения различных программных приложений таких как трансляторы, анализ временных
параметров;
– получения информации о проекте: иерархия, связи;
– специальных и пользовательских форм управления выводом информации;
– создания подпрограмм, формирующих тестовые последовательности;
– создания любого основанного на Verilog программного приложения.
PLI позволяет пользователю читать и модифицировать структуры внутренних данных, получать
доступ к среде моделирования.
Проектировщик пишет собственную пользовательскую системную задачу, применяя PLI-
подпрограммы. Она подключается к программе моделирования, которая обрабатывает ссылку на
задачу, зная место расположения соответствующей функции на языке Си.

(-) 14. Синтез цифровых схем на основе языков описания аппаратуры.


(-) 15. Особенности синтеза типов данных Verilog
(-) 16. Синтез последовательностных устройств.
(-) 17. Особенности синтеза блокирующих и неблокирующих операторов. Влияние
блокирующих операторов на появление триггеров.
(-) 18. Этапы процесса имплементации при реализации моделей на CPLD и FPGA.
(-) 19. Временные параметры комбинационных и последовательностных элементов. Время
установки и хранения.
(-) 20. Вычисление максимальной рабочей частоты устройства на основе временных
характеристик его компонентов.
+ 21. Модели задержек в Verilog.
В Verilog существует несколько видов задержек.
● Распределенная задержка(distributed delay)
● Сосредоточенная задержка (lumped delay)
● Задержка сигнала между выводами (pin-to-pin delay) или задержка пути (path delay)

21.1 Распределенная задержка


Распределенную задержку описывают, основываясь на отдельных задержках элементов.
Распределенная модель может быть построена путем присвоения задержек вентилям или в
операторах assign.
● and #5 a1 (e, a, b); nand #7 a2 (f, c, d); or #4 a3 (out, e, f);
● assign #5 e = a & b; assign #7 f = ~(c & d); assign #4 out = e | f; endmodule
Ниже приведен пример схемы с распределенной задержкой.

21.2. Сосредоточенная задержка


Сосредоточенную задержку задают через задержки выходных вентилей модуля (вентилей,
непосредственно подключенных к выходу), которым присваиваются максимальные задержки всех
путей к выходу.

module M (output out, input a, b, c, d);


wire e, f;
and a1 (e, a, b);
nand a2 (f, c, d); or #11 a3 (out, e, f);
endmodule

Ниже приведен пример схемы с распределенной задержкой.

21.3 Задержка сигнала между выводами или задержка пути


Данная задержка представляет собой время прохождения сигнала от входа до выхода.
Задержку сигнала между выводами часто получают из документации.
Хотя такая задержка является очень детальной, для больших схем она является
предпочтительней, чем распределенная задержка, поскольку проектировщику достаточно знать только
входные и выходные контакты схемы без ее внутренней структуры.
Последняя может представлять собой описание вентильного, dataflow, поведенческого уровней
или являться комбинацией различных стилей, но описание задержки остается неизменным.

22. Конструкция specify для описания временных параметров в Verilog.


Задержка пути в Verilog описывается с помощью конструкции specify и endspecify. Операторы
внутри этого блока являются описательными и выполняют следующие задачи:
1) Описывают задержку между выводами;
2) Выполняют проверку временных параметров в схеме;
3) Определяют константы specparam.

(-) 23. Системные задачи для анализа временных параметров Verilog-моделей.


SystemVerilog
(?) 24. Новые типы данных в SV, logic, типы данных с двумя состояниями.
В SystemVerilog введены следующие новые типы данных:
1) С двумя состояниями (ключевое слово bit): лучшая производительность, минимизация использования памяти;
2) Очереди (Queues), динамические и ассоциативные массивы (dynamic и associative arrays), автоматическая память
(automatic storage): минимизация использования памяти, встроенная поддержка поиска и сортировки;
3) Объединения (Unions) и пакеты (packed): предлагают множественное представление одних и тех же данных;
4) Классы и структуры (Classes и structures): поддерживают структуры абстрактных данных;
5) Строки (Strings): встроенная поддержка строк;
6) Типы перечисления (Enumerated types): упрощение записи и анализа кода;

(?) 25. Типы перечисления в SV.


Перечисление - это тип данных, который представляет собой ограниченное множество специальных имен, таких
как команды или состояния автомата. Использование таких типов упрощает чтение кода.
Простейшая декларация типа перечисления содержит список имен и одну или несколько переменных. Таким
образом, создается тип данных без имени.
enum {RED, BLUE, GREEN} color;

(?) 26. Сложные типы данных: упакованные и неупакованные структуры.


SystemVerilog предоставляет возможность управлять способом сохранения данных в памяти, используя
упакованные структуры. Упакованные структуры хранятся как непрерывное множество битов без
дополнительного неиспользуемого пространства. Приведенная в предыдущих примерах структура struct содержит
три значения и следовательно занимает три длинных слова, даже если реально достаточно трех байт. Чтобы
сэкономить память, можно преобразовать структуру в упакованную.
typedef struct packed {bit [7:0] r, g, b;} pixel_p_s;
pixel_p_s my_pixel;

Упакованные структуры используются, когда базовые биты представляют численные структуры или когда
выполняется попытка экономии памяти. Например, можно упаковать вместе несколько битовых полей для
формирования единого регистра. Можно упаковать вместе код команды opcode и поля операндов, получив, таким
образом, единую инструкцию для процессора.

(?) 27. Сложные типы данных: объединения (union).


В аппаратуре одни и те же данные, объединенные в регистры, могут иметь различные значения и форматы для
обрабатывающего их устройства. Например, через один и тот же регистр могут передаваться как команды, так и
данные. В примере (листинг 2.2) целое i и вещественное f числа хранятся в одном и том же месте.
Листинг 2.2. Примеры объединений
// Использование typedef для создания объединений
typedef union { int i; real f; } num_u;
num_u un;
un.f = 0.0; // установка значений в формате с плавающей точкой

// Переменная, имеющая тип объединения


union {
int i;
int unsigned u;
} data;
...
data.i = -5;
$display("data is %d", data.i);
data.u = -5;
$display("now data is %d", data.u);
typedef union { // typed union
int i;
int unsigned u;
} data_t;
data_t a, b; // две переменные типа data_t

(?) 28. Упакованные и неупакованные массивы.


Упакованные массивы – непрерывные последовательности битов, которые не имеют неиспользуемых
пространств, в отличие от неупакованных массивов.
Упакованные массивы – это удобный способ деления векторов на поля, доступ к которым становится возможным,
через индексы массива. Если упакованный массив объявляется как signed, то он рассматривается как один вектор
с левым старшим битом в виде знака.

неупакованные массивы (unpacked array). В примере создаются два двумерных массива целых чисел размером 8х4.
Последний элемент массива array2 устанавливается в 1. Многомерные массива были введены в Verilog-2001,
новшеством является возможность компактной декларации.
int array2 [0:7][0:3]; // Подробная декларация
int array3 [8][4]; // Компактная декларация
array2[7][3] = 1; // Установка значения последнего
// элемента массива
bit [63:0] d_array [1:128]; // Массив векторов
shortreal cosines [0:89]; // Массив вещественных чисел of floats
typedef enum {Mo, Tu, We, Th, Fr, Sa, Su} Week;
Week Year [1:52]; // Массив элементов типа Week

Каждый элемент в SystemVerilog сохраняется в виде длинного слова (32-bit). Таким образом, byte, shortint и int
сохраняются в одном длинном слове longword, в то время как longint – в двух. (Симулятор часто сохраняет
четырехзначные типы, такие как logic и integer в двух или более словах).

(?) 29. Динамические массивы, очереди.


Динамические массивы декларируются без указания их длинны с пустыми скобками []. Для выделения памяти под
массив используется оператор new[]. Если указать дополнительное имя в операторе new[], то значение будет
копироваться в новый элемент (листинг 16.13.).
Листинг 16.13. Использование динамических массивов
int dyn[], d2[]; // Пустой динамический массив

initial begin
dyn = new[5]; // Выделение памяти для 5 элементов
foreach (dyn[j])
dyn[j] = j; // Инициализация элементов
d2 = dyn; // Копирование динамического массива
d2[0] = 5; // Изменение копии
$display(dyn[0],d2[0]); // Вывод обоих значений (0 и 5)
dyn = new[20](dyn); // Увеличение размера и копирование
dyn = new[100]; // Выделение памяти для 100 новых
// элементов. Старые значения при этом будут потеряны
dyn.delete; // Удаление всех элементов
end

Очередь - Новый тип данных. Упрощает процесс поиска и сортировки в структурах. Такой же быстрый, как и
массивы с фиксированной длиной; многообразен как связанный список. Подобно динамическим массивам
очереди могут увеличиваться и уменьшаться в размере во время моделирования, также можно легко добавлять и
удалять любые элементы, как это показано в следующем примере. Декларируется как массив, но с
использованием символа доллара $ (листинг 2.16). Размер массива может быть указан, но это необязательно.
Очередь может сохранять данные типа данных, которые он получил в момент декларации очереди
int q1 [$]; //пустая очередь, без указания размера
int q2 [$] = {1,2,3,5,8}; // безразмерная очередь,
// инициализируется пятью элементами

typedef struct {int a, b; bit flag} packet_t;


packet_t q3 [$:16]; //очередь размером в 16 элементов

Листинг 2.16. Операции над очередями


int j = 1, b[$] = {3,4}, q[$] = {0,2,5}; // {0,2,5} Инициализация очереди

initial begin
q.insert(1, j); // {0,1,2,5}, помещает 1 перед 2
q.insert(3, b); // {0,1,2,3,4,5}, помещает значение b[] после 2
q.delete(1); // {0,2,3,4,5} , удаляет элемент с индексом 1
// Следующие операторы самые быстрые
q.push_front(6); // {6,0,2,3,4,5}, добавляет элемент в начало списка
j = q.pop_back; // {6,0,2,3,4} j = 5
q.push_back(8); // {6,0,2,3,4,8}, добавляет элемент в конец списка
j = q.pop_front; // {0,2,3,4,8} j = 6
foreach (q[i])
$display(q[i]);
end

(?) 30. Ассоциативные массивы.


Для хранения в памяти больших объемов данных SystemVerilog предлагает ассоциативные массивы, сохраняющие
входы для разреженных матриц. На рис.16.5 представлен массив, сохраняющий информацию в позициях 0:3, 42,
1000, 4521, 200 000. Для создания его модели при использовании ассоциативных массивов потребуется
значительно меньше памяти, чем если бы это был для массив с фиксированной и динамической длинной из
200 001 элементов.

Рис. 2.6. Пример ассоциативного массива


Синтаксис декларации ассоциативного массива:
data_type array_id [index_type];

(?) 31. Новые процедурные блоки в SV.


Чтобы исключить неоднозначность блока always, в SystemVerilog добавлены три его специальных версии:
always_comb, always_latch и always_ff.

В отличие от обычного блока always, блок always_comb не требует указания специального списка чувствительности.
Он создается автоматически и в него включаются все переменные, значение которых читается в процедурном
блоке, за исключением тех, что объявлены в нем. В следующем примере оператор always_comb будет выполняться
при каждом изменении переменных a или b.
always_comb
if (!mode)
y = a + b;
else
y = a - b;

Второй специализированный оператор always - always_latch. Это процедурный блок, моделирующий триггер-
защелку.
always_latch
if (enable) q <= d;

Пример с листинга 3.3 использует always_latch. 5-битовый счетчик, выполняющий счет от 0 до 31. Вход ready
контролирует начало выполнения счета. Вход ready имеет значение 1 короткий период времени. Поэтому, когда
ready переключается в 1, модель сохраняет это значение для внутреннего сигнала enable. Защелка сохраняет
значение 1, пока счетчик не достигнет значения 31, и затем выполняется очищение сигнала enable, не давая
счетчику выполняться снова, до следующего поступления сигнала ready.

Блоки, описывающие последовательностную логику могут моделироваться с помощью always_ff.


always_ff @(posedge clock, negedge resetN)
if (!resetN) q <= 0;
else q <= d;

Все сигналы в списке чувствительности должны быть записаны с указанием фронта posedge или negedge.
Событийный контроль внутри блока не допускается.

(-) 32. Структурные модели: соединение портов. Псевдонимы цепей.


(-) 33. Интерфейсы.Modport.
(-) 34. Методология верификации с применением управляемого ограничениями
псевдослучайного генерирования тестов.
(-) 35. Многоуровневая среда верификации.
(-) 36. Программы. Этапы моделирования систем в SV.
(-) 37. Блок синхронизации. Описание событий через блок синхронизации.
(-) 38. Создание и использование классов с псевдослучайным генерированием значений полей.
(-) 39. Создание и использование ограничений для псевдослучайного генерирования
значений. Условные ограничения, выбор значений из массива, приоритеты значений.
(-) 40. Псевдослучайное генерирование значений: управление блоками ограничений.

(+) 41. Методы определения полноты тестирования. Виды coverage.


К функциональной верификации относят большое количество ресурсов необходимых для
проектирования и подтверждения правильности функционирования сложных систем. Оценка покрытия
используется в качестве руководства для выбора целей тестирования, и позволяет определить в
процентах, какая часть объектов была протестирована.
Существует два типа метрик покрытия:1) code coverage - автоматически формируется на основе
кода проекта и 2) functional coverage …
Покрытие кода code coverage оценивает полноту тестирования с точки зрения проверки
операторов, описывающих модель устройства.
Функциональное покрытие использует пользовательскую метрику, определяющую, какая часть
спецификации проекта, указанной в плане тестирования, была проверена. Используется для измерения,
какая часть интересуемого сценария, исключительных ситуаций, инвариантов спецификации или других
соответствующих проекту условий – указанных в качестве свойств в плане тестирования – были оценены
на правильность функционирования и протестированы.
Ключевые аспекты функционального покрытия:
● определяются пользователем и не могут быть автоматически получены из кода проекта.
● основываются на спецификации проекта и поэтому не зависят от реального кода модели или
структуры.
Поскольку свойства функционального покрытия полностью определяются пользователем, то
требуют на это больше усилий. Также требуется структурный подход к верификации. Хотя
функциональное покрытие сокращает в целом работу по верификации и повышает производительность
и качество проектирования, его недостатки могут помещать его применению.
SystemVerilog предлагает конструкции, упрощающие создание спецификации для
функционального покрытия модели, которые эффективно обрабатываются программами
моделирования SystemVerilog, что позволяет осуществлять анализ данных о покрытии, повышая тем
самым скорость разработки качественного теста. Улучшенное множество тестов может выполнять
тестирование работы устройства в исключительных ситуациях и по требуемому сценарию.
Конструкции функционального покрытия в SystemVerilog осуществляют следующие действия:
● Сбор информации о покрытии переменных и выражений, а также о перекрестном покрытии
между ними.
● Автоматическое или пользовательское создание корзин покрытия
● Фильтрацию условий на нескольких уровнях
● Использование событий и последовательностей для автоматического переключения сбора
значений (sampling) покрытия
● Покрытие вызовов процедур и очередей.
● Управление и регулирование формирования покрытия с помощью директивы
(+) 42. Создание и использование covergroup.
Конструкция covergroup наследует спецификацию модели покрытия. Спецификация covergroup
может включать следующие компоненты:
● События синхронизации, которые определяют моменты считывания значений для точек
● Множество точек покрытия (coverage points)
● Перекрестное покрытие между точками покрытия
● Необязательные формальные аргументы
● Опции покрытия
Конструкция covergroup является определенным пользователем типом. После декларации она
может иметь несколько копий, которые могут быть реализованы в различных контекстах. Конструкция
covergroup может быть записана в пакете, модуле, программе, интерфейсе или классе.
Синтаксис декларации covergroup:
covergroup covergroup_identifier [ ( [ tf_port_list ] ) ] [ coverage_event ] ;
{ coverage_spec_or_option }
endgroup [ : covergroup_identifier ]

coverage_spec_or_option ::=
{attribute_instance} coverage_spec | {attribute_instance} coverage_option ;

coverage_option ::=
option.member_identifier = expression | type_option.member_identifier = expression

coverage_spec ::=
cover_point | cover_cross

coverage_event ::=
clocking_event | @@( block_event_expression )
block_event_expression ::=
block_event_expression or block_event_expression | begin hierarchical_btf_identifier
| end hierarchical_btf_identifier

Синтаксис реализации объекта covergroup:


covergroup_variable_identifier = new [ ( list_of_arguments ) ]
Идентификатор, связанный с декларацией covergroup, определяет имя модели покрытия.
Используя это имя, может быть создано произвольное число копий моделей покрытия. Например,
covergroup cg;
...
endgroup

cg cg_inst = new;
В предложенном примере определена модель покрытия covergroup с именем cg. С помощью
оператора new создана cg_inst копия cg.
Конструкция covergroup может содержать список необязательных аргументов, допускается
выполнять оператор new для всех допустимых типов аргументов. Актуальные аргументы вычисляются
после выполнения оператора new. Аргумент ref позволяет различать переменные, наблюдаемые
каждой копией covergroup. Входные аргументы передают значения в оператор new.
Если указано событие синхронизации, то оно определяет моменты времени для сбора значений с
точек покрытия. В противном случае, пользователь должен задать синхронизацию с помощью
процедурных операторов. Это можно выполнить через встроенный метод sample(). Опция strobe может
быть использована для изменения моментов считывания данных. Когда опция strobe не установлена,
значения точек покрытия считываются по событию экземпляра модели покрытия. Если событие
синхронизации встречается несколько раз за время моделирования, то значения точек покрытия
должны быть также прочитаны несколько раз.
(-) 43. Точки покрытия, перекрестное покрытие, корзины значений для покрытия.
Конструкция cross в SystemVerilog позволяет комбинировать значения двух или более точек
покрытия в группу. Оператор cross допускает только точки покрытия или простые имена переменных.
Если необходимо использовать выражения, иерархические имена или переменные, следует описать
для них метку с помощью coverpoint, а затем уже использовать эту метку в операторе cross.
В примере 17.28 создаются точки покрытия для tr.kind и tr.point. Затем эти точки используются для
создания условий перекрестного покрытия для всех возможных комбинаций. Для точки покрытия kind
SystemVerilog создаст 16 корзин (auto[0]...auto[15]), для точки покрытия port – 8 корзин(auto[0]...auto[7]).
Тогда для перекрестного покрытия этих двух точек будет создано 128(8х16) корзин (<auto[0], auto [0]>,
<auto[0], auto [1]>, …).
Листинг 17.28 Базовое перекрестное покрытие
class Transaction;
rand bit [3:0] kind;
rand bit [2:0] port;
endclass

Transaction tr;

covergroup CovPort;
kind: coverpoint tr.kind; // Создания точки покрытия kind
port: coverpoint tr.port // Создания точки покрытия port
cross kind, port; // Пересечение kind и port
endgroup
Случайный testbench создает 200 транзакций и формирует отчет о покрытии. Обратите внимание,
даже если были генерируются все возможные значения для kind и port, около 1/8 части всех возможных
комбинаций не было достигнуто.

Для сбора данных используются специальные корзины. Информация заносится в них в процессе
моделирования, затем на основе собранной информации формируются статистические данные.
Отдельные корзины
Для вычисления покрытия в точке, необходимо определить общее число возможных значений,
которые называются доменом. Для одной корзины это может быть одно значение или несколько.
Покрытие равняется числу собранных данных, разделенному на количество корзин в домене.
Точка покрытия, которая является 3-битовой переменной, имеет 0:7 доменов и обычно делится на
8 корзин. Если во время моделирования в семь корзин заносятся значения, отчет будет – 7/8 или 87.5%
покрытия в данной точке. Все такие точки объединяются для того, чтобы показать покрытие всей
группы, и затем все группы комбинируются для определения процентных значений покрытия для базы
данных моделирования.
Создание корзин автоматически.
SystemVerilog автоматически создает корзины для точек покрытия. Для всех значений имеющих N-
разрядов, возможно 2N возможных значений. Таким образом, для 3-разрядного порта будет 8
возможных значений.
Ограничения числа создаваемых автоматически корзин
Опция auto_bin_max группы покрытия описывает максимальное число автоматически
создаваемых корзин. По умолчанию, 64. Опция auto_bin_max задает значение корзин только для точек
покрытия coverpoint и не оказывается влияния на количество корзин, задаваемых для перекрестного
покрытия cross.
Если домен значений точки покрытия переменной или выражения больше описанных в опции
SystemVerilog делит диапазон между корзинами. Например, 16-битовая переменная имеет 65 536
возможных значений, таким образом, каждой из 64 корзин будет соответствовать 1024 значения.
В реальности этот подход может оказаться непрактичным. Лучше ограничить возможное число
корзин до 8-16 или явно указывать число возможных корзин. В примере (листинг 17.11) параметр
auto_bin_max устанавливается равным 2. Входной порт имеет размер 3 разряда, что соответствует 8-ми
возможным значениям. Первой корзине соответствуют 4 младших, а второй – 4 старших значения.
Листинг 17.11 Использование опции auto_bin_max
covergroup CovPort;
coverpoint tr.port
{ options.auto_bin_max = 2;} // Значения переменной tr.port делится на 2 корзины
endgroup

// Пример отчета моделирования


Bin # hits at least
==================================
auto[0:3] 15 1
auto[4:7] 17 1
==================================
Пример 17.11 использует опцию auto_bin_max для одной точки покрытия. Эта опция может быть
использована для целой группы.
Листинг 17.13 Использование опции auto_bin_max для всех точек покрытия
covergroup CovPort;
options.auto_bin_max = 2; // Оказывает влияние на переменные port и data
coverpoint tr.port;
coverpoint tr.data;
endgroup

(+) 44. Последовательности (Sequence).


SystemVerilog предоставляет возможность описания специфических последовательных
выражений или последовательностей булевых выражений с явными временными взаимоотношениями
между ними. Для определения совпадения последовательностей, булевы выражения вычисляются в
каждой последовательной точке считывания значений, определяемой синхросигналом, связанным с
последовательностью.
Простейшее последовательное поведение является линейными. Линейная последовательность -
это конечный список булевых выражений SystemVerilog в линейном порядке возрастания времени.
Говорят, что линейная последовательность имела место на конечном интервале следующих друг за
другом синхрособытий, если первое логическое выражение принимает значение «истина» на первом
синхрособытии, второе логическое выражение получает значение «истина» при поступлении второго
синхрособытия, и так далее, вплоть до последнего логического выражения, которое должно принять
значение «истина» на последнем синхрособытии. Примером простой линейной последовательности
является булево выражение. Его присутствие на указанном синхрособытии означает, что оно принимает
в значение «истина» в данный момент времени.
Более сложное последовательное поведение в SystemVerilog описывается с помощью
последовательностей (sequence). Последовательность – это упорядоченная совокупность булевых
выражений, которые включают множество нулей, конечное или бесконечно число линейных
последовательностей. Если хотя бы одна из линейных последовательностей, входящих во множество,
имеет место в конечном интервале последовательных синхрособытий, то считается, что
последовательность произошла на данном интервале времени.
Базовое выражение последовательности: «за a на следующем синхротакте следует b» на
SystemVerilog может иметь вид:
a ##1 b
В этом примере, «##1» обозначает задержку длиной в один синхротакт между последующим
булевым выражением.
В SystemVerilog, каждый элемент последовательности может быть либо булевым выражением,
либо другой последовательностью. В терминах последовательности, булево выражение – это
упрощенный вырожденный случай последовательности длиной в 1. Таким образом, выражение
конкатенации последовательностей
s1 ##1 s2
обозначает, что последовательность s2 начинается на синхротакт после завершения
последовательности s1, как это изображено на рис 10.1. Для перекрывающихся последовательностей
s1 ##0 s2

(+) 45. Свойства(Property)


Во многих случаях последовательности позволяют описывать поведение системы. Задавать
проверку поведения можно с помощью свойств. Кроме того, свойства позволяют инвертировать смысл
последовательности (т.е. последовательность не должна случиться), отключить вычисление
последовательности, или применить последовательность к другим событиям.
Для определения свойств используется следующий синтаксис:
// Декларация свойств
property name [ ( formal_item {, formal_item } ) ] ;
{ assertion_variable_declaration }
property_spec ;
endproperty [:name]
Описание свойств состоит из последовательностей или импликации последовательностей и
других свойств.
property_spec ::=
[clocking_event] [disable iff( expression )] [ not ] property_expr
property_expr ::= sequence_expr | implication_expr
Определение свойств выполняется в границах property-endproperty, и поддерживают
формальные аргументы и аргумент, передающий точное поведение последовательности.
Например:
property p1;
@(posedge clk) disable iff (test) not abort_seq;
endproperty
Оператор not инвертирует смысл последовательности abort_seq, таким образом, выражение
будет иметь значение «ложь» при появлении последовательности abort_seq. Выражение disable iff
отключает вычисление последовательности, если и только, если сигнал test=1. Обратите внимание на
повторное использование ключевых слов disable и iff, которые применяются в других конструкциях
SystemVerilog. Это свойство должно интерпретироваться как «пока сигнал test=0, проверять отсутствие
появления последовательности abort_seq».
Другая полезная поведенческая концепция – «это исключается» (that of implication). Пусть
необходимо проверить появление последовательности, но только после появления init_seq. Такое
свойство может быть описано следующим образом:
@(posedge clk) init_seq |=> abort_seq;
где |=> неперекрывающийся оператор импликации. Это выражение свойств утверждает, что
каждая успешно завершенная последовательность init_seq первого операнда подразумевает, что
последовательность abort_seq из второго операнда начнется на следующем синхротакте. Для каждого
такта, в котором успешное завершение последовательности первого операнда не присутствует,
последовательность второго операнда не будет вычислена и свойство рассматривается как «истина».
Свойство определяет поведение проекта. Свойство может быть использовано для верификации,
как спецификация предположения, проверка или покрытие. Для того чтобы использовать поведение
для верификации, используются операторы assert, assume, или cover. Декларация свойства само по себе
не производит результат.
Свойства property, как и последовательности, декларируется с необязательными формальными
аргументам. Когда свойство вычисляется, то в него передаются фактические аргументы. Механизм
передачи аргументов в свойства такой же, как и для передачи аргументов в последовательность.
Последовательность получает расширение с реальными аргументами, заменяющими формальные
аргументы.
Результат вычисления свойств либо «истина», либо «ложь». Существует семь видов свойств:
последовательность (sequence), отрицание (negation), дизъюнкция(disjunction), конъюнкция
(conjunction), if...else, импликация (implication) и создание копии (instantiation).
а) свойство-последовательность является последовательностью, вычисляемой в значение
«истина», если и только если существует непустое совпадение последовательности.
Последовательность, которая допускает пустое совпадение не разрешается для свойств. Поскольку
совпадение существует, если и только если существует первое совпадение. Вычисление такого свойства
- полное трансформирования его sequence_expr в first_match (sequence_expr). Как только первое
совпадение sequence_expr обнаруживается, вычисление свойства рассматривается как «истина» и нет
необходимости в поиске других совпадение.
б) Свойство-отрицание, имеет вид
not property_expr
При каждой попытке вычисления свойств вычисляется property_expr. Ключевое слово not
обозначает, что при вычислении свойства возвращается противоположное значение для property_expr.
Таким образом, если property_expr примет значение «истина», то not property_expr соответствует
значению «ложь», и если property_expr оценивается как «ложь», то not property_expr будет «истина».
c) Дизъюнкция свойств имеет вид
property_expr1 or property_expr2
Свойство соответствует значению «истина» если и только если как минимум одно из свойств
property_expr1 и property_expr2 «истина».
d) Конъюнкция свойств имеет форму
property_expr1 and property_expr2
Свойство оценивается как «истина», если и только если свойства property_expr1 и property_expr2
имеют значение «истина»
e) Свойство « if...else» имеет форму
if (expression_or_dist) property_expr1
или
if (expression_or_dist) property_expr1 else property_expr2
Свойство в первом случае оценивается как «истина», если и только если либо expression_or_dist
принимает значение «ложь», либо property_expr1 – «истина». Во втором случае свойство возвращает
значение истина, когда либо expression_or_dist и property_expr1 возвращают значение «истина», либо
expression_or_dist вычисляется в «ложь», а property_expr2 – «истина».
f) Свойство-импликанта имеет форму
sequence_expr |-> property_expr
или
sequence_expr |=> property_expr

(+) 46. Прямые и параллельные ассерции.


Прямые ассерции используются в процедурном коде в любом месте в конструкциях initial и
always.
Синтаксис прямых асерций:
assert ( expression ) [[ pass_stmt ] else fail_stmt ];
Выражение вычисляется сразу, при выполнении оператора. Операторы в ветвях pass и fail, если
они присутствуют, выполняются мгновенно после вычисления выражения.
Процедурный код testbench может проверять значения сигналов проекта, переменных и
выполнять необходимые действия, в случае обнаружения ошибки. Например, в проекте выполняется
проверка запроса шины request и ожидается, что ответ будет получен двумя тактами позже.
Тестирование этой ситуации можно выполнить с помощью оператора if.
// Проверка сигнала с помощью оператора if
bus.cb.request <= 1;
@bus.cb;
if (bus.cb.grant != 2’b01)
$display("Error, grant != 1");
// Остальная часть теста
Оператор ассерции более компактен, чем оператор if. При этом значение условия обратно,
записываемому в if. Другими словами, если условие имеет значение «истина», то выполнение ассерции
было успешно.
// Простая процедурная асерции
bus.cb.request <= 1;
@bus.cb;
a1: assert (bus.cb.grant == 2’b01);
// остальной код теста
Если сигнал grant получен правильно (grant=2'b01), работа теста будет продолжено. Иначе будет
выдано следующее сообщение.
"test.sv", 7: top.t1.a1: started at 55ns failed at 55ns
Offending '(bus.cb.grant == 2’b1)‘
Сообщение говорит, что в линии 7 файла test.sv, асерция top.t1.a1 начала выполнение в момент
55ns для проверки сигнала bus.cb.grant и сразу же обнаружила ошибку.
Процедурные асерции имеют ветви then- и else-, при необходимости, в них могут быть добавлены
операторы.
// Создание пользовательского сообщения об ошибке
a1: assert (bus.cb.grant == 2’b01)
else $error("Grant not asserted");
Если сигнал grant не имеет ожидаемого значения, то будет выведено соответствующее
сообщение.
"test.sv", 7: top.t1.a1: started at 55ns failed at 55ns
Offending '(bus.cb.grant == 2’b1)‘
Grant not asserted
SystemVerilog имеет четыре функции для вывода сообщений: $info, $warning, $error и $fatal,
которые могут быть использованы только в операторе ассерции. Можно использовать ветвь then для
записи количества успешных выполнений оператора ассерций.
// Создание пользовательского сообщения об ошибке
a1: assert (bus.cb.grant == 2’b01)
grants_received++; // Количество успешных выполненийt
else
$error("Grant not asserted");
Операторы прямых ассерций выполняют тестирование указанных условий, в момент своего
выполнения в процедурном коде. Выражение интерпретируется тем же способом, что и условие в
операторе if. Если значение выражения равно X, Z или 0, оно рассматривается, как «ложь» и ассерция
провалилась (fail), иначе – «истинна» и ассерция прошла (pass).
Оператор, связанный с успешным выполнением ассерции записывается первым, называется pass-
оператором и выполняется, если значение выражения имеет значение «истина». Pass-оператор может,
например, записывать число успешных проходов в файл отчета (log), но может вообще отсутствовать.
Если оператор для ветви успешного выполнения ассерций не указан, то никакие действия в этом случае
выполняться не будут. Оператор, ассоциирующийся с веткой else, называется fail-оператор и
выполняется, если значение выражения «ложь». Присутствие этого оператора также является
необязательным. Указанные действия выполняются мгновенно, после

(+) 47. Виртуальные интерфейсы.


Виртуальный интерфейс позволяет отделить абстрактные модели и тестовые программы от
реальных сигналов.
Использование виртуального интерфейса позволяет объектам testbench обращаться к объектам в
интерфейсе, используя указатели, вместо реального имени. Виртуальный интерфейс – это мост между
динамическим миром объектов и статическим миром модулей и интерфейсов.
Свойства виртуального интерфейса:
● Может использоваться для декларации аргументов функций и задач, наряду с другими типами
данных
● Должен быть инициализирован до его использования
● Значение по умолчанию виртуального интерфейса равно null
● Внутри виртуальных интерфейсов могут быть использованы процедурные присвоения,
непрерывные - нет
● Управлять данными класса net можно только через блок синхронизации
● Виртуальный интерфейс может быть свойством класса и инициализироваться в процедуре или
конструкторе.
Синтаксис
virtual [interface] interface_identifier [parameter_value_assignment]
[.modport_identifier] list_of_virtual_interface_decl ;
list_of_virtual_interface_decl ::=
variable_identifier [ = interface_instance_identifier ]
{ , variable_identifier [ = interface_instance_identifier ] }
Пример 1
Представляет использование виртуального интерфейса для создание связи между объектами
класса Transactor, управляющего транзакциями, и тестируемыми модулями devA и DevB (Листинг 1).
Листинг 1 - Создание и использование виртуального интерфейса
interface SBus; // Простой интерфейс шины
logic req, grant;
logic [7:0] addr, data;
endinterface
class SBusTransactor; // Класс транзакции SBus
virtual SBus bus; // виртуальный интерфейс типа SBus
function new( virtual SBus s );
bus = s; // инициализация виртуального интерфейса
endfunction
task request(); // Запрос шины
bus.req <= 1'b1;
endtask
task wait_for_bus(); // ожидание выделения шины
@(posedge bus.grant);
endtask
endclass
module devA( SBus s ) ... endmodule // устройства, использующие SBus
module devB( SBus s ) ... endmodule

module top;
SBus s[1:4] (); // создание 4 объектов интерфейса

devA a1( s[1] ); // подключение 4 устройств


devB b1( s[2] );
devA a2( s[3] );
devB b2( s[4] );

initial begin
SBusTransactor t[1:4]; // create 4 bus-transactors and bind
t[1] = new( s[1] );
t[2] = new( s[2] );
t[3] = new( s[3] );
t[4] = new( s[4] );
// test t[1:4]
end
endmodule

(+) 48. Управление потоками: семейство блоков fork-join


join. Родительский процесс блокируется, пока все порожденные
им процессы не завершат свое выполнение.
join_any. Родительский процесс блокируется, пока хотя бы один
любой указанный в нем процесс не завершит свое выполнение.
join none. Родительский процесс продолжает свое выполнение
параллельно с процессами порожденными в fork. Порожденные
процессы не начнут выполнение, пока родительский поток не
выполнит блокирующий оператор

Управление процессами. Wait fork Wait fork

Запись wait fork приведет к тому что вызывающий процесс будет блокирован пока все
подпроцессы не завершат выполнение.

Оператор disable fork


завершает выполнение всех потомков вызывающего процесса
Задача wait_device ожидает
готовность устройства и готовность устройства и возвращает адрес устройства. Когда первое
устройство становится становится доступным, то задача завершает свое выполнение и закрывает все
порожденные потоки.
UVM
(+) 49. Классификация компонентов в UVM: квазистатические, динамические.
Все компоненты UVM можно разделить на квазистатические и динамические. К
квазистатическим относят те, что формируют структуру среды верификации, которая создается
один раз в момент инициализации моделирования, например driver, monitor, scoreboard,
sequencer, agent, environment. Динамические компоненты, такие как транзакции и sequence, -
формируются и изменяются в течение процесса моделирования и представляют собой тестовые
последовательности, подаваемые на входы устройства, результаты моделирования, формируемые
устройствами.

(?) 50. Интерфейсные UVC, перечислить и привести характеристики.


Интерфейсные (iUVC). Такие компоненты подключаются непосредственно к DUT и
реализуют относящиеся к протоколам аспекты или используются как средства
программирования DUT.

(?) 51. Системные UVC, перечислить и дать характеристики.


System UVCs - могут использовать интерфейсные, модульные и другие системные
UVCs. Могут не иметь своих собственных агентов и использовать другие UVCs, формируя на
их основе среду верификации большего размера для целых систем, например cpu, мосты
(bridge), мобильные телефоны

(+) 52. Структура классов UVM. Базовый класс uvm_object.


Базовый класс для UVM классов данных и иерархии, и содержит основные методы
автоматизации работы с классами библиотеки UVM:
create, copy, pack/unpack, clone, compare, print, record, get_type, get_type_name, и др.
Используется для автоматической реализации методов необходимо выполнить
регистрацию класса и его полей. Для класса используются макросы:
`uvm_object_utils_begin(Type)
`uvm_object_utils_end
Они необходимы для :
- Реализации методов get_type_name() и create()
- Регистрирования типов
- Реализации статического метода get_type()
Макросы для полей класса :
`uvm_field_*(field_name, flag)
`uvm_field_enum(enum type, field name, flag)
где field_name - имя поля, enum type - имя типа перечисления, flag - флаг управления. Флаги
можно соединять через оператор | или or. Макросы регистрируют поля класса для
реализации функций: copy(), pack(), unpack(), clone(), compare(), print() или record().
Функция new должна начинаться с пункци super.new(name). PS. С
`uvm_object_utils_begin в классе обязательно указывать описание функции new.

(+) 53. Класс uvm_component. Фазы подготовки и выполнения модели.


Базовый класс для создания UVC.
Конструктор new()
function new(string name, uvm_component parent)
В отличие от объекта, метод new класса компонента вторым аргументом
получает ссылку на компонент родителя. Кроме этого класс содержит функции,
отображающие различные стадии моделирования и позволяют пользователям
подключаться к этим точкам.
1. build_phase(). Создает дочерние компоненты и их конфигурация. Должна
начинаться с команды super.build().
2. connect_phase(). Устанавливаются связи между компонентами, создаются
TLM соединения.
3..end_of_elaboration_phase(). Завершающая настройка testbench,
выполняется проверка связей между компонентами и инициализация.
4. start_of_simulation_phase(). Подготовка DUT к моделированию
5. run_phase(). Фаза моделирования DUT.
6. extract_phase(). Извлечение данных из различных точек среды
верификации (assert и coverage).
7. check_phase(). Проверка всех неожиданных условий в среде верификации,
состояний регистров, Работа scoreboard.
8. report_phase(). Вывод сообщений о результатах моделирования
9. final_phase() - Завершение моделирования Также класс содержит функции:
get_parent(), get_full_name(), get_child(). Метод run_test() вызывает старт
моделирования.
Получить ссылку на компонент верхнего уровня в среде верификации:
uvm_top.find()
uvm_top.find_all()
Хранит глобальную конфигурацию

(+) 54. Механизмы конфигурации среды верификации и ее компонентов в UVM.

Механизмы конфигурации
● Factory
● Config db(Configuration)
Базовый класс для UVM классов данных и иерархии, и содержит основные методы
автоматизации работы с классами библиотеки UVM. Его наследники uvm_sequence_item
описывает транзакцию, а uvm_sequence - последовательнось транзакций. Это так
называемая динамическая составляющая среды верификации. Все составляющие среду
верификации компоненты построены на основе класса uvm_component, который умеет
управлять фазами моделирования. Это статические элементы среды верификации.
Конфигурация среды верификации осуществляется с помощью классов uvm_resource_db и
uvm_config_db. Для моделирования состояния регистров и памяти в проекте
предназначены классы uvm_reg, uvm_reg_block, uvm_reg_file, uvm_reg_field и uvm_mem.

(+) 55. TLM-интерфейсы в UVM


TLM - моделирования уровня транзакций - это стиль моделирования для построения
абстрактных моделей компонентов и систем. TLM основан на транзакциях - объектах, которые
содержат различные относящиеся к протоколу данных для абстрактного представления
процессов нижнего уровня. TLM представляет семейство абстрактных уровней описания,
начиная с циклического уровня моделирования (cycle-accurate modeling).
Наиболее известные уровни TLM:
циклический(cycle-accurate),
с аппроксимированным временем(approximately-timed),
loosely-timed, без времени и token-level.

Преимущества использования TLM-интерфейсов


1) Более высокий уровень абстракции
2) Повторно используемое plug&play соединение
3) Надежность в использовании
4) Меньше кода
5) Легкость реализации
6) Более быстрое моделирование
7) Связь с SystemC
8) Могут быть использованы для разработки эталонных моделей

(+) 56. Sequence, sequencer, driver, agent.


UVM Sequence
Последовательность в UVM - это объект, определяющий процесс генерирования
тестовых последовательностей и не является частью иерархии компонентов.
Последовательность может быть временной и постоянной; может создаваться для одной
транзакции или генерировать стимулы во время всего моделирования; может
функционировать иерархически, когда один компонент sequence (родительский) вызывает
другой компонент sequence (дочерний). Для функционирования последовательности требуется
sequencer, один sequencer может управлять несколькими последовательностями.
UVM Sequencer
UVM Sequencer контролирует поток тестовых наборов (UVM Sequence
Item),генерируемый одним или несколькими последовательностями(UVM Sequence). Служит
арбитром для контроля за потоком транзакций от нескольких последовательностей.
UVM Driver
Драйвер эмулирует логику, управляющую DUT, он получает от секвенсора отдельные
транзакции (UVM Sequence Item) и передает их на интерфейс DUT. Таким образом драйвер
изменяет уровень абстракции, преобразуя транзакции(transaction-level) во входные сигналы
(pin-level). От включает TLM-порт, по которому тестовые наборы от секвенсора поступают в
драйвер, и подключается к интерфейсу DUT, для управления сигналами на его входах. Драйвер
и секвенсор формируют трафик на входах DUT, но они не применяются для оценки
функционального покрытия и выполнения формальной верификации (чекеров и ассерций), эти
задачи делегируются мониторам.
UVM Agent
Агент - это иерархический компонент, который группирует другие верификационные
компоненты, относящиеся к определенному интерфейсу DUT (рис 5). Типичный агент включает
секвенсер (UVM Sequencer) для управления потоком тестовых наборов, драйвер (UVM Driver)
для передачи сигналов на входы DUT и наблюдающий за интерфейсом монитор (UVM Monitor).
Также в агент могут входит другие компоненты, например, собирающие информацию о
покрытии, проверки протоколов, TLM-модели. В среде верификации может присутствовать
большее одного агента. Агенты конфигурируются как активные или пассивные. Активные -
генерируют тесты, пассивные - только наблюдают, и обычно включают только монитор.

(+) 57. UVM Factory.


Для целей верификации бывает удобно создавать одну общую структуру среды
верификации, а потом “на лету” заменять одни компоненты и данные на другие. Для этого в
методологии верификации адаптировали механизм фабрик(factory), существовавший до этого
в программировании. В UVM фабрики можно использовать только с классами, производными
от uvm_object и uvm_component.
Существует три базовых шага для применения factory:
1) Регистрация
2) Создание
3) Переопределение
Регистрация
Тип класса регистрируется для factory в момент своего создания. Для этого используются
предопределенные скрипты (которые уже были рассмотрены ранее).
`uvm_component_utils(class_type_name)
`uvm_object_utils(class_type_name)
для параметризируемых классов:
`uvm_component_param_utils(class_type_name#(params))
`uvm_object_param_utils(class_type_name #(params))
Регистрация необходим для переопределения по имени, переопределение по типу
может быть выполнена без регистрации.
Создание
Для создания объекта или компонента в UVM рекомендуется использовать статический
метод create() вместо new().
Синтаксис :
type_name::type_id::create(string name, uvm_component parent)
Функция create() возвращает объект класса type_name. Объект переопределяется
фабрикой, основываясь на контексте определяемым полным именем родителя. Аргумент
context, если он определен, заменяет контекст родителя. Новый объект будет иметь имя листа
и родителя. Классы, основанные на uvm_object, не требуют указывать второй аргумент.
Переопределение
Переопределять классы и объекты можно основывая на строки имени или типе класса.
Существует 4 метода для переопределения. Первые два меняют тип данных для
определенного объекта класса или группы объектов, если строка full_inst_path содержит
специальные символы. Различие между ними заключается в форме задания типа класса, через
ссылку (uvm_object_wrapper) или строку. Тип uvm_object_wrapper - абстрактный интерфейс к
созданным объектам. Вторая пара методов заменяет один типа класса на другой.

Оценить