Идентификаторы,ключевые слова, системные имена

VERILOG

Язык VERILOG был разработан в 1985 г. одной из корпораций США и позд­нее утвержден институтом электроинженеров США (IEEE) — стандарт IEEE 1364 в 1994 г. [2]. В приложении 2 дано краткое описание его подмножества. В отличие от VHDL, который строго типизирован и синтаксически напоминает языки ADA и PASCAL, VERILOG базируется на С, имеет меньше встроенных возможностей саморасширения, но зато более прост в реализации (более простой и быстрый компилятор), имеет более развитый интерфейс с языком Си и лаконичен, что по­зволяет уменьшить объем описаний схем примерно в полтора раза по сравнению с VHDL. В настоящее время принят вариант нового стандарта IEEE 1364—2001 (VERILOG-2001), который, в частности, включил в себя ряд стилистических средств, сближающих его с VHDL [15] (см. приложение 2). Тем не менее остается впечатление елки, на которую все время добавляют новые украшения, не имея возможности убрать ненужные старые. Ниже VERILOG-2000 означает то же, что и VERILOG-2001.

Идентификаторы,ключевые слова, системные имена

Идентификаторы, ключевые слова и системные имена строятся по одним и тем же правилам, поэтому они и объединены в данный параграф. Общие правила следующие:

• Идентификаторы не должны совпадать с ключевыми словами;

• Идентификаторы не могут начинаться с символов ($) или ( ‘- ап остроф);

• Идентификатор не может начинаться с цифры;

• Длина идентификатора по стандарту не ограничена, но может ограничиваться в конкретном компиляторе;

• Ключевые слова всегда пишутся строчными буквами;

• Системные имена начинаются с символа ($);

• Директивы компилятора начинаются с символа (‘ - апостроф);

• Компилятор различает строчные и прописные буквы.

X, z, Z и. щ

Идентифищпоры

Идентификаторы используются в языке verilog в качестве символических имен для обозначения переменных, констант, модулей, функций, задач и т.д. и могут
использоваться для обозначения этих объектов в любом месте описания в любом месте описания.

Идентификатор представляет собой последовательность из букв, цифр, символов из букв, цифр, символов

доллара ($) и символов подчеркивания (_) с учётом изложенных выше правил.

Числа

Числа или иначе константы могут определяться в десятичном, шестнадцатеричном, восьмеричном или двоичном форматах. В языке Verilog предусмотрены две формы для записи чисел. Первая форма представляет собой простое десятичное число как последовательность цифр от 0 до 9 и опционально может предварятся символами плюса или минуса. Вторая форма представления чисел имеет следующий формат:

<size><baseformat<number>

Поле size содержит десятичные цифр и указывает разрядность константы в битах, это поле опционально и может опускаться в случаях если разрядность константы заранее определена (Допустим производится присвоение константного значения временной, разрядность которой задана при ее объявлении). Если разрядность не определена, то разрядность принимается по умолчанию равной 32 (32 в большинстве систем синтеза, в некоторых разрядность по умолчанию может отличаться). Второе поле base format содержит букву, определяющую формат представления числа (десятичный, двоичный ...). Эта буква предваряется символом одиночной кавычки ('). Формат представления определяется следующими буквами: d - десятичный; h - шестнадцатиричный; о - восьмеричный и b - двоичный. Допускается вводить эти буквы как прописными, так и строчными. Последнее поле number содержит цифры допустимые для выбранного формата: от 0 до 9 для десятичного формата; от 0 до 7 для восьмеричного; 0 и 1 для двоичного; от 0 до 9 и буквы а, Ь, с, d, е, f для шестнадцатеричного. Буквенные обозначения могут вводится как строчными, так и прописными буквами.

Числа имеющие знаковое представление предваряются опциональными символами плюса и минуса перед полем size, Эти символы перед полем number недопустимы. Запись -8’h5A эквивалентна записи –(8’h5A), а запись 8’h-5A вызовет синтаксическую ошибку.

Помимо указанных цифр в поле number могут присутствовать буквы x, X, z, Z и
символ (?) (В поле size они недопустимы). Буквы х и X обозначают неизвестное
(неопределенное) состоянии, т.е. состояние соответствующих битов неизвестно. Буквы
z и Z обозначают состояние высокого импеданса - z-состояние или отсутствие
источника (драйвера). Символ ? эквивалентен символу z и предназначен для лучшей
читабельности кода в случае когда, это состояние безразлично (don't-care). Существует

Возможность сокращать запись числа, например: 8’b1 будет эквивалентно записи 8’b11111111, но запись 8’b01 будет эквивалентна записи 8’b00000001. В силу того, что такие сокращенные записи могут мешать читабельности кода, употреблять их без

особой надобности не следует.

Для улучшения читабельности допускается ещё два приёма: допускается вставлять пробелы и символы табуляции между полями записи, например 8’hB6 можно записать как 8 ’h B6. Вставлять пробелы внутри поля number не допускается, но можно вставлять символ подчеркивания (_), для разбиения числа на некоторые группы. Примеры 83465 можно записать как 83_465; 8’b01100111 можно записать как 8’b0110_0111. Символ подчёркивания в поле size или перед полем number недопустим.

Введение в программирование на языке Verilog

Из вышесказанного следует что Verilog - язык описания цифровых схем. Познакомимся с базовыми типами источников сигнала используемыми в языке.

Пожалуй, было бы не плохо начать наше обсуждение с понятия сигнал (signal). Сигналы – это электрические импульсы, которые передаются по проводам (wire) между логическими элементами схемы. Провода переносят информацию не производя над ней никаких вычислений. В цифровой схеме сигналы важны для передачи двоичных данных.

Базовый тип источника сигнала в языке Verilog – это провод, wire. Таким образом, если у вас есть арифметическое или логическое выражение, вы можете ассоциировать результат выражения с именованным проводом и позже использовать его в других выражениях. Вот пример декларации однобитного провода в “программе” Verilog:

wire a;

Вы можете ему назначить другой сигнал, скажем сигнал “b”, вот так:

wire b;
assign a = b;

Или вы можете определить сигнал и сделать назначение ему одновременно в одном выражении:

wire a = b;

У вас могут быть провода передающие несколько бит:

wire [3:0] c; //это четыре провода

Провода передающие несколько бит информации называются “шина”, иногда “вектор”. Назначания к ним делаются так же:

wire [3:0] d;
assign c = d; //“подключение” одной шины к другой

Количество проводов в шине определяется любыми двумя целыми числами разделенными двоеточием внутри квадратных скобок.

wire [11:4] e; //восьмибитная шина
wire [0:255] f; //256-ти битная шина

Из шины можно выбрать некоторые нужные биты и назначить другому проводу:

wire g;
assign g = f[2]; //назначить сигналу “g” второй бит шины “f”

Кроме того, выбираемый из шины бит может определяться переменной:

wire [7:0] h;
wire i = f[h]; //назначить сигналу “i” бит номер “h” из шины “f”

Вы можете выбрать из сигнальной шины некоторый диапазон бит и назначить другой шине с тем же количеством бит:

wire [3:0] j = e[7:4];

Так же, в большинстве диалектов Verilog, вы можете определить массивы сигнальных шин:

wire [7:0] k [0:19]; //массив из двадцати 8-ми битных шин

Еще существует другой тип источника сигнала называемый регистр: reg. Его используют при поведенческом (behavioral) описании схемы. Если регистру постоянно присваивается значение комбинаторной (логической) функции, то он ведет себя точно как провод (wire). Если же регистру присваивается значение в синхронной логике, например по фронту сигнала тактовой частоты, то ему, в конечном счете, будет соответствовать физический D-триггер или группа D-триггеров. D-триггер – это логический элемент способный запоминать один бит информации. В англоязычных статьях D-триггер называют flipflop.

Регистры описываются так же как и провода:

reg [3:0] m;
reg [0:100] n;

Они могут использоваться так же, как и провода в правой части выражений, как операнды:

wire [1:0] p = m[2:1];

Вы можете определить массив регистров, которые обычно называют “память” (RAM):

reg [7:0] q [0:15]; //память из 16 слов, каждое по 8 бит

Еще один тип источника сигнала – это integer. Он похож на регистр reg, но всегда является 32х битным знаковым типом данных. Например, объявим:

integer loop_count;

Verilog позволяет группировать логику в блоки. Каждый блок логики называется “модулем” (module). Модули имеют входы и выходы, которые ведут себя как сигналы wire.

При описании модуля сперва перечисляют его порты (входы и выходы):

module my_module_name (port_a, port_b, w, y, z);

А затем описывают направление сигналов:

input port_a;
output [6:0] port_b;
input [0:4] w;
inout y; //двунаправленный сигнал, обычно используется

//только для внешних контактов микросхем

Позже мы увидим, что выход модуля может быть сразу декларирован как регистр reg, а не как провод wire:

output [3:0] z;
reg [3:0] z;

Еще проще можно сразу в описании модуля указать тип и направление сигналов:

module my_module
(
input wire port_a,
output wire [6:0]port_b,
input wire [0:4]w,
inout wire y,
output reg [3:0]z
);

Теперь можно использовать входные сигналы, как провода wire:

wire r = w[1];

Теперь можно делать постоянные назначения выходам, как функции от входов:

assign port_b = h[6:0];

В конце описания логики каждого модуля пишем слово endmodule.

module my_module_name (input wire a, input wire b, output wire c);
assign c = a & b;
endmodule

Последний тип источника сигнала, о котором мы поговорим на этом уроке – это постоянные сигналы или просто числа:

wire [12:0] s = 12; //32-х битное десятичное число, которое будет “обрезано” до 13 бит
wire [12:0] z = 13’d12; //13-ти битное десятичное число
wire [3:0] t = 4'b0101; //4-х битное двоичное число
wire [3:0] q = 8'hA5; //8-ми битное шестнадцатеричное число A5
wire [63:0] u = 64'hdeadbeefcafebabe; //64-х битное шестнадцатеричное число

Если точно не определить размер числа, то оно принимается по умолчанию 32-х разрядным. Это может быть проблемой при присвоении сигналам с большей разрядностью.

Числа – это числа. Они могут использоваться во всяких арифметических и логических выражениях. Например, можно прибавить 1 к вектору “aa”:

wire [3:0] aa;
wire [3:0] bb;
assign bb = aa + 1;

Синтаксис

Синтаксис операций Verilog похож на синтаксис операций языка С. Символы операций, их названия, а также применимость к вещественным переменным приведены в таблице 4.

Таблица 4

Символ Описание операции Применимость к real
{} Конкатенация Не допустимо
+ - * / Арифметические Допустимо
% Модуль Не допустимо
> >= < <= Отношения Допустимо
! Логическое отрицание Допустимо
&& Логическое И Допустимо
|| Логическое ИЛИ Допустимо
== Логическое равенство Допустимо
!= Логическое неравенство Допустимо
=== Идентичность Не допустимо
!=== Неидентичность Не допустимо
~ Побитовая инверсия Не допустимо
& Побитовое И Не допустимо
| Побитовое ИЛИ Не допустимо
^ Побитовое исключающее ИЛИ Не допустимо
{^~ ~^ Побитовая эквивалентность Не допустимо
& Редукционное И Не допустимо
~& Редукционное НЕ-И Не допустимо
| Редукционное ИЛИ Не допустимо
~| Редукционное НЕ-ИЛИ Не допустимо
^ Редукционное исключающее ИЛИ Не допустимо
~^ ^~ Редукционное НЕ исключающее ИЛИ Не допустимо
<< Сдвиг влево Не допустимо
>> Сдвиг вправо Не допустимо
<<< Циклический сдвиг влево Не допустимо
>>> Циклический сдвиг вправо Не допустимо
?: Условный оператор Допустимо

Теперь расположим операции Verilog в порядке убывания приоритета:

  • + - ! ~ (унарные) Наивысший приоритет
  • * / %
  • + - (бинарные)
  • << >> <<< >>>
  • < <= > >=
  • == != === !===
  • & ~&
  • | ~|
  • &&
  • ||
  • ?: Низший приоритет

Операции с равным приоритетом выполняются слева направо, за исключением ?: который выполняется справа налево.

Из полученных выше примеров попробуем описать на языке Verilog шифратор с 8 входами и 3-мя выходами.

СДНФ:

Y1=X1vX3vX5vX7

Y2=X2vX3vX6vX7

Y3=X4vX5vX6vX7

Зная СДНФ шифратора мы можем описать её на Verilog.

1-й способ:

module SHIFRATOR (input X1, input X2, input X3, input X4, input X5,input X6, input X7, output Y1, output Y2, output Y3);

assign Y1=X1|X3|X5|X7;

assign Y2=X2|X3|X6|X7;

assign Y3=X4|X5|X6|X7;

endmodule

2-й способ:

module SHIFRATOR (X1,X2,X3,X4,X5,X6,X7,Y1,Y2,Y3);

input X1,X2,X3,X4,X5,X6,X7;

output Y1,Y2,Y3;

assign Y1=X1|X3|X5|X7;

assign Y2=X2|X3|X6|X7;

assign Y3=X4|X5|X6|X7;

endmodule

Аналогичная ситуация будет и с четырехканальным мультиплексором, СДНФ которого:

Идентификаторы,ключевые слова, системные имена - student2.ru

1-й способ:

module MULTIPLEXOR (A0, A1, D0, D1, D2, D3, Y);

input A0, A1, D0, D1, D2, D3;

output Y;

assign Y=(D0&!A1&!A0)|(D1&A0)|(D2&A1&!A0)|(D3&A1&A0);

endmodule

2-й способ (описание мультиплексора через wire):

module MULTIPLEXOR (input A0, input A1, input D0, input D1, input D2, input D3,

output Y);

wire S1, S2, S3, S4, S5, S6;

NOT my_1_not ( .OUT(S1), .IN1(A0));

NOT my_2_not ( .OUT(S2), .IN1(A1));

AND3 my_1_and ( .OUT(S3), .IN1(S1), .IN2(S2), .IN3(D0));

AND2 my_2_and ( .OUT(S4), .IN1(A0), .IN2(D1));

AND3 my_3_and ( .OUT(S5), .IN1(S1), .IN2(A1), .IN3(D2));

AND3 my_4_and ( .OUT(S6), .IN1(A0), .IN2(A1), .IN3(D3));

OR4 my_or ( .OUT(Y), .IN1(S3), .IN2(S4), .IN3(S5), .IN4(S6));

endmodule

Наши рекомендации