В данной статье показаны некоторые нововведения языка SystemVerilog в области организации данных по сравнению с Verilog-2001 для синтезируемого подмножества языка.
История SystemVerilog довольна длина и туманна. Начавшись после принятия стандарта Verilog-95, она вылилась в Verilog-2001. Однако язык не слишком подходил для верификации, инженеры использовании языки семейства «E» — VERA, Testbuilder. В современном виде SystemVerilog появился после 2005 года. Сейчас средства синтеза и моделирование такие как Quartus II, ISE, ModelSim/QuestaSim уверенно поддерживают SystemVerilog. Стандарт называется IEEE 1800-2012.
Прим. Эта статья давно написана, но не опубликована. Надеюсь будет полезна начинающим.
SystemVerilog привнес в мир Verilog много новых интересны конструкций:
- C-lile синтаксис
- ООП Структуры,
- очереди,
- динамические массивы,
- перечисления
- Приведения типов
- Контроль поведения программы с помощью foreach, return, break, continue и т.д
- Semaphores, mailboxes.
- Интерфейсы
- Assertions
Универсальный тип logic.
Теперь нет нужны выбирать между reg и wire, всюду используется logic. Синтезатор сам решить что надо сделать (привет signal из VHDL).
Инициализация типов.
В SystemVerilog стали доступны улучшенные возможности инициализации типов. Теперь не надо писать
SystemVerilog Code:
reg [63:0] data = 64'hFFFFFFFFFFFFFFFF;
Можно сделать просто так:
SystemVerilog Code:
reg [63:0] data = '1;
Запись data = '0 инициализируем вектор нулями, а data = 'bz — третьим состоянием
Перечисляемые типы.
Наконец-то state машину можно описать вот так
SystemVerilog Code:
enum {WAITE, LOAD, STORE} State, NextState; always_ff @(posedge clock, negedge resetN) if (!resetN) State <= WAITE; else State <= NextState; always_comb begin case (State) WAITE: NextState = LOAD; LOAD: NextState = STORE; STORE: NextState = WAITE; endcase end
Кроме того, перечисляемому типу можно присваивать значения:
SystemVerilog Code:
enum {ONE = 1,FIVE = 5,TEN = 10 } state;
По умолчанию перечисляемому типу ставится в соответствие значение int. Однако, можно написать и вот так
// перечисляемы тип с шириной 1 бит.
// может принимать только два состояний
SystemVerilog Code:
enum bit {TRUE, FALSE} Boolean; // перечисляемы тип с шириной 2 бита. // может принимать четыре состояния enum logic [1:0] {WAITE, LOAD, READY} state;
Для печати значения имени перечисляемого типа используется следующая конструкция:
SystemVerilog Code:
$display("nCurrent state is %s (%b)", State.name);
Струкруты
Объявить структуры можно следующим способом:
SystemVerilog Code:
struct { int a, b; // 32-bit variables opcode_t opcode; // user-defined type logic [23:0] address; // 24-bit variable bit error; // 1-bit 2-state var. } Instruction_Word;
Для структур поддерживается объявление typedef
SystemVerilog Code:
typedef struct { // structure definition logic [31:0] a, b; logic [ 7:0] opcode; logic [23:0] address; } instruction_word_t; instruction_word_t IW; // structure allocation
По умолчанию структура представляется как unpacked. Ключевое слово packed позволяет быть структуре запакованной.
SystemVerilog Code:
struct packed { logic valid; logic [ 7:0] tag; logic [31:0] data; } data_word;
В данном виде она представляется как вектор. Поэтому возможны такие конструкции
SystemVerilog Code:
data_word.tag = 8’hf0; data_word[39:32] = 8’hf0; // делаем тоже самое
Объединения union
Объединения это значение памяти которое может хранить разные типы данных, но одновременно только одно.
Синтаксис полностью C-like.
SystemVerilog Code:
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);
Наибольший практический интерес представляют packed unions. В них для представления разных типов используемся фиксированное число бит.
Информация, записанная через один тип, может быть считана в другом виде (другом типе).
Например:
SystemVerilog Code:
typedef struct packed { logic [15:0] source_address; logic [15:0] destination_address; logic [23:0] data; logic [ 7:0] opcode; } data_packet_t; union packed { data_packet_t packet; // packed structure logic [7:0][7:0] bytes; // packed array } dreg;
Так как объединение упаковано, то информация выровнена, поэтому данные записанные через logic[7:0] можно считать через data_packet_t
SystemVerilog Code:
initial begin logic [15:0] src, dst; for (i = 0; i <= N; i = i + 1) begin dreg.bytes[i] <= byte_in; //store as bytes end src = dreg.source_address; dst = dreg.destination_address; end
Packed Array
SystemVerilog позволяет создавать мультиразмерные упакованные массивы
SystemVerilog Code:
logic [3:0][7:0] data; // 2-D packed array logic [1:0][3:0][7:0] data; // 3-D packed array
Стандарт IEEE определяем как эти элемент должны хранится в памяти. Например для описания
SystemVerilog Code:
logic [3:0][7:0] data; // 2-D packed array
Поскольку массив хранится в памяти как вектор, то допустимо использовать все теже операции что и над векторами
SystemVerilog Code:
logic [3:0][15:0] a, b, result; // packed arrays result = (a << 1) + b;
Доступ к вектору может быть как поэлементным, так и включая целую размерность(и). Так называемы срез массива.
SystemVerilog Code:
logic [1:0][1:0][7:0] a; // 3-D packed array a[1][1][0] = 1’b0; // присваиваем один бит массиву a = 32’hF1A3C5E7; // записываем сразу массив целиком a[1][0][3:0] = 4’hF; // доступ к части массивы a[0] = 16’hFACE; // доступ к срезу
Для копирования содержимого одного массива в другой можно использовать прямой доступ или по срезам
SystemVerilog Code:
bit [1:0][15:0] a; //32х битный вектор, элемент bit только 0 или 1 logic [3:0][7:0] b; //32х битный вектор, элемент logic O,1,Z,X logic [15:0] c; // 16ти битный вектор logic [39:0] d; // 40 битный вектор b = a; // присвоение 32х битного массива 32х битному массиву c = a; // старшие 16 бит будут обрезаны d = a; // старшие 8 бит будут нулями
Список литературы
1. www.asic-world.com/systemverilog
2. «SystemVerilog For Design Second Edition» by Stuart Sutherland
Автор: covsh