Преимущества ESL:
● повышение уровня абстракции представления системы;
● возможность возможность использования использования более высокого высокого уровня для
reuse-проектов;
● поддержка непрерывной цепи проектирования, начиная с верхнего абстрактного уровня
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-устройств.
+ 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” используется для задания действий, которые будут выполняться периодически
или при определенных уровнях сигнала.
Циклические операторы языка Verilog размещаются внутри поведенческих блоков initial и always.
Цикл «пока» в языке Verilog описывается ключевым словом while. Синтаксис:
while (Логическое_Выражение)
Оператор_Тело_Цикла;
Тело цикла будет выполняться, пока выполняется условие. Если условие становится ложным, то
выполнение цикла, прекращается. Очевидно, что тело корректного цикла «пока» обязательно должно
содержать изменение хотя бы одного сигнала, входящего в Условие_Выхода. В противном случае от
итерации к итерации значение условия не будет изменяться и цикл становится бесконечным.
Исключение составляют случаи, когда Условие_Выхода привязано к внешнему источнику событий
(например, содержит входной порт модуля либо сигнал, драйвером которого является другой процесс,
либо ссылку на временные параметры).
Цикл с параметром общего вида описывается при помощи ключевого слова for. При описании
устанавливаются:
● начальное значение параметра;
● условие выхода из цикла;
● оператор блокирующего присваивания, задающий изменение параметра на каждой итерации.
for ( Начальное_Значение_Параметра; Условие_Выхода; Изменение_Параметра)
begin
Тело_Цикла;
end
Следует также заметить, что в языке Verilog, как и в языке Си, разрешается изменение параметра
внутри тела цикла.
Кроме цикла for, в языке Verilog представлена еще одна форма цикла с параметром – цикл repeat.
Цикл repeat используется в тех случаях, если необходимо выполнить тело цикла определенное
фиксированное число раз. Формальный синтаксис цикла repeat приведен ниже:
repeat (Число_Итераций)
begin
Тело_Цикла;
end
При поведенческом описании оборудования бесконечный цикл является очень полезной и
распространенной конструкцией, так как прекращение основного цикла работы устройства обычно
осуществляется отключением его от сети питания, что является внешним воздействием по отношению к
устройству. Бесконечный цикл начинается ключевым словом forever, его формальный синтаксис
представлен ниже:
forever
Тело_Цикла;
При использовании бесконечных циклов следует обращать внимание на наличие в теле цикла
какого-либо временного управления.
Бесконечный цикл, как и любой другой цикл, можно искусственно прервать при помощи
оператора disable.
Упакованные структуры используются, когда базовые биты представляют численные структуры или когда
выполняется попытка экономии памяти. Например, можно упаковать вместе несколько битовых полей для
формирования единого регистра. Можно упаковать вместе код команды opcode и поля операндов, получив, таким
образом, единую инструкцию для процессора.
неупакованные массивы (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 в двух или более словах).
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}; // безразмерная очередь,
// инициализируется пятью элементами
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
В отличие от обычного блока 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.
Все сигналы в списке чувствительности должны быть записаны с указанием фронта posedge или negedge.
Событийный контроль внутри блока не допускается.
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
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
module top;
SBus s[1:4] (); // создание 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
Запись wait fork приведет к тому что вызывающий процесс будет блокирован пока все
подпроцессы не завершат выполнение.
Механизмы конфигурации
● 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.