5. Выражения и Операторы Verilog HDL

В этом пункте описываются операторы и операнды, доступные в Verilog HDL, и то, как использовать их для формирования выражений.
Содержание

Выражение — это конструкция, объединяющая операнды с операторами для получения результата, который является функцией значений операндов и семантического значения оператора. Любой легальный операнд, например, net bit- select, без какого-либо оператора считается выражением. Везде, где в операторе Verilog HDL требуется значение, можно использовать выражение.

Некоторые конструкции утверждений требуют, чтобы выражение было константным выражением. Операнды константного выражения состоят из константных чисел, строк, параметров, константных битовых и частичных выборок параметров, константных вызовов функций (см. 10.4.5) и только вызовов константных системных функций; но они могут использовать любой из операторов, определенных в таблице 5-1.

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

Типы данных reg, integer, time, real и realtime являются переменными типами данных. Описания, относящиеся к использованию переменных, относятся ко всем этим типам данных.

Операнд может быть одним из следующих:

  • Константное число (в том числе real) или строка
  • Параметр (включая локальные и заданные параметры)
  • Битовая или частичная выборка параметров (не real) (включая локальные и заданные параметры)
  • Сеть(провода)
  • Битовая или частичная выборка сетей(проводов)
  • Переменные reg, integer или time
  • Битовая или частичная выборка переменных reg, integer или time
  • Переменные real или realtime
  • Элемент массива
  • Битовая или частичная выборка элементов массива (не real)
  • Вызов определяемый пользователем или системой функции, которая возвращает любое из вышеперечисленных значений

5.1 Операторы

Символы для операторов Verilog HDL аналогичны символам языка программирования C. В таблице 5-1 перечислены эти операторы.

Таблица 5-1 Таблица операторов Verilog HDL
ОператорТип оператора
{} {{}}Конкатенация, репликация
унарный + унарный —Унарные операторы
+ — * / **Арифметические
%Модуль
> >= < <=Реляционные
!Логическое отрицание
&&Логический и
||Логический или
==Логическое равенство
!=Логическое неравенство
===Эквивалентность
!==Неравенств
~Побитовое отрицание
&Побитовая и
|Побитовое или
^Побитовое исключающее или
^~ или ~^Побитовая эквивалентность
&Редуцированный и
~&Редуцированный не и
|Редуцированный или
~|Редуцированный не и
^Редуцированный xor
~^ или ^~Редуцированный xnor
<<Логический сдвиг влево
>>Логический сдвиг вправо
<<<Арифметический сдвиг влево
>>>Арифметический сдвиг вправо
? :Условный

5.1.1. Операторы с вещественными операндами

Операторы, приведенные в таблице 5-2, являются разрешенные при применении к вещественным операндам. Все остальные операторы считаются незаконными при использовании с вещественными операндами.

Результатом использования логических или реляционных операторов над вещественными числами является однобитное скалярное значение.

Таблица 5-2 Разрешенные операторы для использования в вещественных выражениях
ОператорТип оператора
унарный + унарный —Унарные операторы
+ — * / **Арифметические
> >= < <=Реляционные
! && ||Логические
== !=Логическое равенство
?:Условный

В таблице 5-3 перечислены операторы, которые не должны использоваться для работы с вещественными числами.

Таблица 5-3 Операторы, недопустимые для вещественных выражений
ОператорНаименование оператора
{} {{}}Конкатенировать, реплицировать
%Модуль
=== !==Равенство типов
~ & | ^ ^~ ~^Побитовая
^ ^~ ~^ & ~& | ~|Реляционные
<< >> <<< >>>Сдвиги

Более подробную информацию об использовании вещественных чисел см. в разделе 4.8.1.

5.1.2 Старшинство операторов

Порядок старшинства операторов Verilog показан в таблице 5-4.

Операторы, показанные в одной строке в таблице 5-4, имеют одинаковый приоритет. Строки расположены в порядке убывания старшинства операторов. Например, *, / и % имеют одинаковый приоритет, который выше, чем у двоичных операторов + и .

Все операторы должны ассоциироваться слева направо, за исключением условного оператора, который должен ассоциироваться справа налево. Ассоциативность относится к порядку, в котором оцениваются операторы с одинаковым старшинством. Так, в следующем примере B прибавляется к A, а затем C вычитается из результата A+B.
A + B - C
Если операторы различаются по старшинству, то сначала связываются операторы с более высоким старшинством. В следующем примере B делится на C (деление имеет более высокий приоритет, чем сложение), а затем результат прибавляется к A.
A + B / C
Круглые скобки можно использовать для изменения старшинства оператора.
(A + B) / C // не то же самое, что A + B / C
Таблица 5-4. Правила старшинства для операторов
ОператорыПриоритет
+ — ! ~ & ~& | ~| ^ ~^ ^~ (унарный)Наивысший приоритет
**
* / %
+ — (бинарный)
<< >> <<< >>>
< <= > >=
== != === !==
& (бинарный)
^ ^~ ~^ (двоичный)
| (двоичный)
&&
||
?: (условный оператор)
{} {{}}Наименьший приоритет

5.1.3 Использование целых чисел в выражениях

Целые числа можно использовать в качестве операндов в выражениях. Целое число может быть выражено как

  • Неразмерное, небазированное целое число (например, 12)
  • Неразмерное целое число с основанием (например, ‘d12, ‘sd12)
  • Целое число, имеющее размер (например, 16’d12, 16’sd12)

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

Например:

В этом примере показаны четыре способа записи выражения «минус 12, деленное на 3». Обратите внимание, что -12 и -‘d12 оба оцениваются одной и той же двухкомпонентной битовой схемой, но в выражении -‘d12 теряет свою идентичность как знаковое отрицательное число.
integer IntA; IntA = -12 / 3; // Результат -4. IntA = -'d 12 / 3; //Результат1431655761.IntA = - 'sd 12 / 3; // Результат -4. IntA = -4'sd 12 / 3; // -4'sd12 - это отрицательное 4-битное значение // количество 1100, которое равно -4. -(-4) = 4. // Результат равен 1.

5.1.4 Порядок оценки выражений

Операторы должны следовать правилам ассоциативности при оценке выражения, как описано в пункте 5.1.2. Однако, если конечный результат выражения может быть определен заранее, все выражение не обязательно оценивать. Это называется замыканием оценки выражения.

Например:
reg regA, regB, regC, result; result = regA & (regB | regC);

Если известно, что regA равен нулю, то результат выражения можно определить как нулевой без оценки подвыражения regB | regC.

5.1.5 Арифметические операторы

Двоичные арифметические операторы приведены в таблице 5-5.

Таблица 5-5 Определение арифметических операторов
Синтаксис арифметических операторовКомментарий к синтаксису
a + bа плюс б
a — ba минус b
a * ba умноженное на b
a / ba, деленное на b
a % ba по модулю b
a ** ba в степени b

При целочисленном делении любая дробная часть должна быть усечена до нуля. Для операторов деления или модуляции, если второй операнд — ноль, то все значение результата должно быть x. Оператор модуляции (например, y % z) дает остаток, когда первый операнд делится на второй, и, таким образом, равен нулю, когда z делит y ровно. Результат операции по модулю принимает знак первого операнда.

Если один из операндов оператора электропитания является вещественным, то тип результата должен быть вещественным. Результат оператора электропитания не определен, если первый операнд равен нулю, а второй операнд неположителен или если первый операнд отрицателен, а второй операнд не является интегральным значением.

Если ни один из операндов оператора электропитания не является вещественным, то тип результата определяется в соответствии с пунктами 5.4.1 и 5.5.1. Значение результата равно ‘bx, если первый операнд равен нулю, а второй отрицателен. Значение результата равно 1, если второй операнд равен нулю.

Во всех случаях второй операнд оператора электропитания должен рассматриваться как самоопределяющийся. Эти утверждения проиллюстрированы в таблице 5-6.

Таблица 5-6 Правила работы оператора электропитания
op1 это
op2 это
< -1-1ноль1> 1
положительныйop1 ** op2op2 нечетный ->-1
op2 четный ->1
01op1 ** op2
ноль11111
отрицательный0op2 нечетный ->-1
op2 четный ->1
‘bx10

Унарные арифметические операторы имеют приоритет перед двоичными операторами. Унарные операторы приведены в таблице 5-7.

Таблица 5-7 Унарные операторы определены
Синтаксис унарных операторовКомментарий к синтаксису
+mУнарный плюс m (то же, что m)
-mУнарный минус m

Для арифметических операторов, если любое значение бита операнда является неизвестным значением x или высокоимпедансным значением z, то все значение результата должно быть x.

Например:

В таблице 5-8 приведены примеры некоторых операций с модулем и мощностью.

Таблица 5-8 Примеры операторов модуля и мощности
ВыражениеРезультатКомментарии
10 % 3110/3 дает остаток, равный 1.
11 % 3211/3 дает остаток 2.
12 % 3012/3 не дает никакого остатка.
-10 % 3-1Результат принимает знак первого операнда.
11 % -32Результат принимает знак первого операнда
-4’d12 % 31-4’d12 рассматривается как большое положительное число, которое при делении на 3 оставляет остаток 1.
3 ** 293 * 3
2 ** 382 * 2 * 2
2 ** 01Все, что до нулевой экспоненты, равно 1.
0 ** 01Ноль по нулевой экспоненте также равен 1.
2.0 ** -3’sb10.52.0 — является вещественным, дающая вещественную взаимность.
2 ** -3 ‘sb102 ** -1 = 1/2. Целочисленное деление усекается до нуля.
0 ** -1‘bx0 ** -1 = 1/0. Целочисленное деление на ноль — это ‘bx.
9 ** 0.53.0Действительный квадратный корень.
9.0 ** (1/2)1.0Целочисленное деление усекает экспоненту до нуля.
-3.0 ** 2.09.0Определено, так как вещественное значение 2.0 все еще является интегральным значением.

5.1.6 Арифметические выражения с регистрами и целыми числами

Значение, присвоенное переменной reg или net, рассматривается как беззнаковое значение, если только переменная reg или net не была явно объявлена как знаковая. Значение, присвоенное переменной integer, real или realtime, должно рассматриваться как знаковое. Значение, присвоенное time переменной, рассматривается как беззнаковое.

Знаковые значения, за исключением тех, которые присваиваются переменным real и realtime, должны использовать двухкомпонентное представление.

Значения, присваиваемые переменным real и realtime, должны использовать представление с плавающей точкой. Преобразования между знаковыми и беззнаковыми значениями должны сохранять то же представление битов; меняется только интерпретация.

В таблице 5-9 перечислено, как арифметические операторы интерпретируют каждый тип данных.

Таблица 5-9 Интерпретация типов данных арифметическими операторами
Тип данныхИнтерпретация
unsigned netБеззнаковый
signed netЗнаковый, двойное дополнение
unsigned regБеззнаковый
signed regЗнаковый, двойное дополнение
integerЗнаковый, двойное дополнение
timeБеззнаковый
real, realtimeЗнаковый, с плавающей запятой

Например:

В следующем примере показаны различные способы деления «минус двенадцать на три» — с использованием в выражениях integer и reg типов данных.
integer intA; reg [15:0] regA; reg signed [15:0] regS; intA = -4'd12; regA = intA / 3; // результат выражения равен -4, // intA - целочисленный тип данных, regA - 65532 regA = -4'd12; // regA равен 65524 intA = regA / 3; // результат выражения равен 21841, // regA - тип данных reg intA = -4'd12 / 3; // результат выражения равен 1431655761. // -4'd12 фактически является 32-битным типом данных reg regA = -12 / 3; // результат выражения равен -4, -12 эффективно // целочисленный тип данных. regA - 65532 regS = -12 / 3; // результат выражения -4. regS -знаковый regS = - 4'sd12 / 3; // результат выражения - 1. -4'sd12 на самом деле 4. // По правилам целочисленного деления получается 4/3==1.

5.1.7 Реляционные операторы

В таблице 5-10 перечислены и определены реляционные операторы.

Таблица 5-10 Определения реляционных операторов
Синтаксис оператораКомментарий
a < ba меньше b
a > ba больше b
a <= ba меньше или равно b
a >= ba больше или равно b

Выражение, использующее эти реляционные операторы, должно давать скалярное значение 0, если указанное отношение ложно, или значение 1, если оно истинно. Если один из операндов реляционного оператора содержит неизвестное (x) или высокоимпедансное (z) значение, то результатом будет 1-битное неизвестное значение (x).

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

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

Если один из операндов является вещественным, то другой операнд должен быть преобразован в эквивалентное вещественное значение, а выражение интерпретируется как сравнение между вещественными значениями.

Все реляционные операторы должны иметь одинаковый приоритет. Реляционные операторы имеют более низкий приоритет, чем арифметические операторы.

Например:

Следующие примеры иллюстрируют последствия этого правила приоритета:
a < foo - 1 //это выражение такое же, как a < (foo - 1) // это выражение, но ... foo - (1 < a) //это не то же самое, что foo - 1 < a // это выражение

Когда оценивается foo — (1 < a), сначала оценивается реляционное выражение, а затем из foo вычитается либо ноль, либо единица. Когда вычисляется foo — 1 < a, значение операнда foo уменьшается на единицу, а затем сравнивается с a.

5.1.8 Операторы равенства

Операторы равенства имеют более низкий приоритет, чем реляционные операторы. В таблице 5-11 перечислены и определены операторы равенства.

Таблица 5-11-Определения операторов равенства
ОператорЗначение операции
a === ba равно b, включая x и z
a !== ba не равно b, включая x и z
a == ba равно b, результат может быть неизвестен
a != ba не равно b, результат может быть неизвестен

Все четыре оператора равенства должны иметь одинаковый приоритет. Эти четыре оператора сравнивают операнды бит за битом. Как и в случае с реляционными операторами, результат должен быть равен 0, если сравнение не удалось, и 1, если удалось.

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

Если один из операндов является вещественным, то другой операнд должен быть преобразован в эквивалентное вещественное значение, а выражение интерпретируется как сравнение между вещественными значениями.

Для операторов логического равенства и логического неравенства (== и !=), если из-за неизвестных или высокоимпедансных битов в операндах отношение неоднозначно, то результатом должно быть 1-битное неизвестное значение (x).

Для операторов case equality и case inequality (=== и !==) сравнение выполняется так же, как и в процедурном операторе case (см. 9.5). Биты, которые являются x или z, должны быть включены в сравнение и должны совпадать, чтобы результат считался равным. Результатом этих операторов всегда должно быть известное значение, либо 1, либо 0.

5.1.9 Логические операторы

Операторы logical and (&&) и logical or (||) являются логическими связками. Результатом оценки логического сравнения является 1 (определяется как истина), 0 (определяется как ложь) или, если результат неоднозначен, неизвестное значение (x). Приоритет && больше, чем у ||, и оба они ниже, чем реляционные операторы и операторы равенства.

Третьим логическим оператором является унарный логический оператор отрицания (!). Оператор отрицания преобразует ненулевой или истинный операнд в 0, а нулевой или ложный операнд в 1. Неоднозначное истинностное значение остается в виде x.

Например:

Пример 1 — Если регистр alpha имеет целочисленное значение 237, а beta имеет значение ноль, то следующие примеры выполняются так, как описано:
regA = alpha && beta; //regA устанавливается в 0 regB = alpha || beta; // regB устанавливается в 1
Пример 2. Следующее выражение выполняет логическое и из трех подвыражений без использования круглых скобок:
a < size-1 && b != c && index != lastone
Однако для удобства чтения рекомендуется использовать круглые скобки, чтобы очень четко показать предполагаемый приоритет, как в следующей переработке этого примера:
(a < size-1) && (b != c) && (index != lastone)
Пример 3 частое использование ! в конструкциях, подобных следующей:
if (!inword)
В некоторых случаях предыдущая конструкция имеет больше смысла для читающего код, чем эта эквивалентная конструкция:
if (inword == 0)

5.1.10 Побитовые операторы

Побитовые операторы должны выполнять побитовые манипуляции с операндами; то есть оператор должен объединить бит в одном операнде с соответствующим битом в другом операнде, чтобы вычислить 1 бит для результата. Логические таблицы с 5-12 по 5-16 показывают результаты для каждого возможного вычисления.

Таблица 5-12-Двоичный и поразрядный оператор and
Оператор &(and)Значение 0Значение 1Значение xЗначение z
Значение 00000
Значение 101xx
Значение x0xxx
Значение z0xxx
Таблица 5-13-Битовый двоичный оператор or
Оператор |(or)Значение 0Значение 1Значение xЗначение z
Значение 001xx
Значение 11111
Значение xx1xx
Значение zx1xx
Таблица 5-14 Двоичный поразрядный оператор исключающее or
Оператор ^(исключающее or)Значение 0Значение 1Значение xЗначение z
Значение 001xx
Значение 110xx
Значение xxxxx
Значение zxxxx
Таблица 5-15 Битовый двоичный исключающий оператор nor
Оператор ^~ ~^(nor)Значение 0Значение 1Значение xЗначение z
Значение 010xx
Значение 101xx
Значение xxxxx
Значение zxxxx
Таблица 5-16 Битовый унарный оператор отрицания ~
Оператор ~(отрицания)Результат
Значение 01
Значение 10
Значение xx
Значение zx

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

5.1.11 Операторы редукции

Унарные операторы редукции должны выполнять побитовую операцию над одним операндом для получения однобитового результата. Для операторов reduction and, reduction or и reduction xor первый шаг операции должен применять оператор между первым битом операнда и вторым, используя логические таблицы 5-175-19. На втором и последующих шагах оператор применяется между 1-битным результатом предыдущего шага и следующим битом операнда с использованием той же логической таблицы. Для операторов reduction nand, reduction nor и reduction xnor результат вычисляется путем инвертирования результата операций reduction and, reduction or и reduction xor соответственно.

Например:

Таблица 5-17 Редукция унарного оператора &(and)
&(reduction and)Значение 0Значение 1Значение xЗначение z
Значение 00000
Значение 101xx
Значение x0xxx
Значение z0xxx
Таблица 5-18 Редукция унарного оператора or
|(reduction or)Значение 0Значение 1Значение xЗначение z
Значение 001xx
Значение 11111
Значение xx1xx
Значение zx1xx
Таблица 5-19 Редукция унарного оператора исключающего or
^(reduction исключающее or)Значение 0Значение 1Значение xЗначение z
Значение 001xx
Значение 110xx
Значение xxxxx
Значение zxxxx

Например:

В таблице 5-20 показаны результаты применения операторов сокращения к различным операндам.

Таблица 5-20-Результаты операций унарного сокращения
Операнд&~&|~|^~^Комментарии
4’b0000010101Биты не установлены
4’b1111101001Все биты установлены
4’b0110011001Четное количество установленных битов
4’b1000011010Нечетное количество установленных битов

5.1.12 Операторы сдвига

Существует два типа операторов сдвига: логические операторы сдвига, << и >>, и арифметические операторы сдвига, <<< и >>>. Операторы сдвига влево, << и <<<, сдвигают свой левый операнд влево на число на количество битовых позиций, заданных правым операндом. В обоих случаях освободившиеся битовые позиции должны быть заполнены нулями. Операторы сдвига вправо, >> и >>>, сдвигают свой левый операнд вправо на количество битовых позиций, заданных правым операндом. Логический сдвиг вправо должен заполнить освободившиеся битовые позиции нулями. Арифметический сдвиг вправо должен заполнить освободившиеся битовые позиции нулями, если тип результата беззнаковый. Он должен заполнить освободившиеся битовые позиции значением старшего (т.е. знакового) бита левого операнда, если тип результата знаковый. Если правый операнд имеет значение x или z, то результат будет неизвестен. Правый операнд всегда рассматривается как беззнаковое число и не влияет на знаковость результата. Знаковость результата определяется левым операндом и остатком выражения, как описано в пункте 5.5.1.

Например:

Пример 1. В этом примере результату reg присваивается двоичное значение 0100, которое представляет собой 0001, сдвинутое на две левые позиции и заполненное нулями.
module shift; reg [3:0] start, result; initial begin start = 1; result = (start << 2); end endmodule
Пример 2. В этом примере результату reg присваивается двоичное значение 1110, которое на 1000 сдвигается на две правые позиции и заполняется знаком.
module ashift; reg signed [3:0] start, result; initial begin start = 4'b1000; result = (start >>> 2); end endmodule

5.1.13 Условный оператор

Условный оператор, также известный как тернарный оператор, должен быть право-ассоциативным и должен быть построен с использованием трех операндов, разделенных двумя операторами в формате, приведенном в Синтаксисе 5-1.

conditional_expression ::= expression1 ? { attribute_instance } expression2 : expression3 expression1 ::= expression expression2 ::= expression expression3 ::= expression
Синтаксис 5-1-Синтаксис для условного оператора

Оценка условного оператора должна начинаться с логического сравнения равенства (см. 5.1.8) expression1 с нулем, называемого условием. Если условие равно false (0), то expression3 оценивается и используется как результат условного выражения. Если условие оценивается как true (1), то expression2 оценивается и используется в качестве результата. Если условие оценивается в неоднозначное значение (x или z), то оцениваются оба expression2 и expression3, и их результаты объединяются, бит за битом, с использованием таблицы 5-21 для вычисления окончательного результата, если только expression2 или expression3 не является вещественным, в этом случае результатом будет 0. Если длины expression2 и expression3 различны, то более короткий операнд должен быть удлинен до соответствия более длинному и заполнен нулями слева (старший конец).

Таблица 5-21-Результаты условий смешения для условного оператора
Условный оператор ?:Значение 0Значение 1Значение xЗначение z
Значение 00xxx
Значение 1x1xx
Значение xxxxx
Значение zxxxx

Например:

Следующий пример трехсостоятельной выходной шины иллюстрирует распространенное использование условного оператора:
wire [15:0] busa = drive_busa ? data : 16'bz;

Шина под названием data подается на шину busa, когда drive_busa равен 1. Если drive_busa неизвестен, то на шину busa подается неизвестное значение. В противном случае шина busa не передается.

5.1.14 Конкатенации

Конкатенация — это результат объединения битов, полученных в результате одного или нескольких выражений. Конкатенация должна быть выражена с помощью символов скобок { и }, при этом запятые разделяют выражения внутри.

Неразмерные константные числа не должны допускаться в конкатенациях. Это связано с тем, что размер каждого операнда в конкатенации необходим для вычисления полного размера конкатенации.

Например:

В этом примере конкатенируются четыре выражения:
{a, b[3:0], w, 3'b101} //Это эквивалентно следующему примеру: {a, b[3], b[2], b[1], b[0], w, 1'b1, 1'b0, 1'b1}

Оператор, который может быть применен только к конкатенациям является репликацией, которая выражается конкатенацией, которой предшествует неотрицательное, не x и не z, то есть константное выражение, называемое константой репликации, заключенное в скобки, и которое указывает на объединение такого количества копий конкатенация. В отличие от обычных конкатенаций, выражения, содержащие репликации, не должны появляться в левой части присваивания и не должны быть связаны с портами input или output.

В этом примере w повторяется четыре раза.
{4{w}} // This yields the same value as {w, w, w, w}
В следующих примерах показаны неправильные репликации:
{1'bz{1'b0}} // нельзя {1'bx{1'b0}} // нельзя
Следующий пример иллюстрирует репликацию, вложенную в конкатенацию:
{b, {3{a, b}}} // This yields the same value as // {b, a, b, a, b, a, b}

Операция репликации может иметь константу репликации со значением ноль. Это полезно в параметризованном коде. Репликация с нулевой константой репликации считается имеющей нулевой размер и игнорируется. Такая репликация должна появляться только внутри конкатенации, в которой хотя бы один из операндов конкатенации имеет положительный размер.

Например:
parameter P = 32; // Следующее является законным для всех P от 1 до 32 assign b[31:0] = { {32-P{1’b1}}, a[P-1:0] } ; // Следующее действие незаконно для P=32, потому что нуль // репликация появляется отдельно в конкатенации assign c[31:0] = { {{32-P{1’b1}}}, a[P-1:0] } // Следующее является незаконным для P=32 initial $displayb({32-P{1’b1}}, a[P-1:0]);

5.2 Операнды

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

Если требуется один бит векторной сети, векторного reg, integer, time переменной или параметра, то должен использоваться операнд bit-select(битовая выборка). Для ссылки на группу соседних битов в векторной сетке, векторном reg, integer или time переменной или параметре используется операнд part-select(частичная выборка).

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

5.2.1 Битовая и частичная выборка адресации вектора

Битовая выборка(bit-select) извлекает определенный бит из векторной сети, векторных переменных reg, integer, time или параметра. Бит может быть адресован с помощью выражения. Если битовая выборка находится вне границ адреса или битовая выборка равна x или z, то значение, возвращаемое ссылкой, будет x. Битовая выборка или частичная выборка скаляра или переменной или параметра типа real или realtime будет недопустимой.

Несколько смежных битов в векторной сети, векторных переменных reg, integer или time или параметре могут быть адресованы и известны как частичная выборка(part-select). Существует два типа выбора частей: константный выбор частей и индексированный выбор частей. Константный part-select вектора reg или net задается следующим синтаксисом:
vect[msb_expr:lsb_expr]

И msb_expr, и lsb_expr должны быть константными целочисленными выражениями. Первое выражение должно адресовать более значимый бит, чем второе выражение.

Индексированный part-select векторной сети, векторного reg, integer, time переменной или параметра задается с помощью следующего синтаксиса:
reg [15:0] big_vect; reg [0:15] little_vect; big_vect[lsb_base_expr +: width_expr] little_vect[msb_base_expr +: width_expr] big_vect[msb_base_expr -: width_expr] little_vect[lsb_base_expr -: width_expr]

msb_base_expr и lsb_base_expr должны быть целочисленными выражениями, а width_expr должно быть положительным константным целочисленным выражением. lsb_base_expr и msb_base_expr могут изменяться во время выполнения. Первые два примера выбирают биты, начиная с основания и по возрастанию диапазона битов. Количество выбранных битов равно выражению width. Во вторых двух примерах выбираются биты, начиная с основания и по убыванию битового диапазона.

Частичная выборка любого типа, которая адресует диапазон битов, полностью выходящих за границы адреса сети, переменных reg, integer, time или параметра, или частичная выборка, которая является x или z, при чтении возвращает значение x и не влияет на сохраненные данные при записи. Частичная выборка, частично выходящая за пределы диапазона, при чтении возвращает значение x для битов, находящихся вне диапазона, а при записи влияет только на биты, находящиеся в диапазоне.

Например:
reg [31: 0] big_vect; reg [0 :31] little_vect; reg [63: 0] dword; integer sel; big_vect[ 0 +: 8] // == big_vect[ 7 : 0] big_vect[15 -: 8] // == big_vect[15 : 8] little_vect[ 0 +: 8] // == little_vect[0 : 7] little_vect[15 -: 8] // == little_vect[8 :15] dword[8*sel +: 8] // переменная part-select с фиксированной шириной

Например:

Пример 1. В следующем примере указывается один бит вектора acc, к которому обращается операнд индекс:
acc[index]
Фактический бит, к которому обращается адрес, частично определяется объявлением acc. Например, каждое из объявлений acc, показанных в следующем примере, приводит к тому, что определенное значение index обращается к разным битам:
reg [15:0] acc; reg [2:17] acc;
Пример 2. Следующий пример и следующие за ним пункты иллюстрируют принципы битовой адресации. Код объявляет 8-битный reg с именем vect и инициализирует его значением 4. В списке описано, как можно адресовать отдельные биты этого вектора.
reg [7:0] vect; vect = 4; // заполняет vect шаблоном 00000100 // msb - бит 7, lsb - бит 0
  • Если значение addr равно 2, то vect[addr] возвращает 1.
  • Если значение addr выходит за границы, то vect[addr] возвращает x.
  • Если addr равен 0, 1 или от 3 до 7, vect[addr] возвращает 0.
  • vect[3:0] возвращает биты 0100.
  • vect[5:1] возвращает биты 00010.
  • vect[выражение, возвращающее x] возвращает x.
  • vect[выражение, возвращающее z] возвращает x.
  • Если любой бит addr равен x или z, то значение addr равно x.

Индексы частичного выбора, которые оцениваются как x или z, могут быть отмечены как ошибка времени компиляции.

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

Перевод Официального Стандарта Verilog HDL

5.2.2 Адресация массивов и памяти

Объявление массивов и памяти (одномерных массивов reg) рассматривается в разделе 4.9. В этом подпункте рассматривается адресация массивов.

Например:

В следующем примере объявляется память из 1024 восьмибитных слов:

reg [7:0] mem_name[0:1023];
Синтаксис для адреса памяти состоит из имени памяти и выражения для адреса, заданного в следующем формате:
mem_name[addr_expr]
Addr_expr может быть любым целочисленным выражением; поэтому перенаправления памяти могут быть указаны в одном выражении. Следующий пример иллюстрирует перенаправление памяти:
mem_name[mem_name[3]]

В этом примере mem_name[3] обращается к третьему слову памяти, называемой mem_name. Значение в третьем слове — это индекс в mem_name, который используется адресом памяти mem_name[mem_name[3]]. Как и в случае с битовым выбором, границы адреса, указанные в объявлении памяти, определяют эффект выражения адреса. Если индекс находится вне границ адреса или если любой бит в адресе равен x или z, то значением ссылки будет x.

Например:

В следующем примере объявляется массив 256 на 256 на 256 восьмибитных элементов и массив 256 на 256 на 8 однобитных элементов:

reg [7:0] twod_array[0:255][0:255]; wire threed_array[0:255][0:255][0:7];
Синтаксис для доступа к массиву должен состоять из имени памяти или массива и целочисленного выражения для каждого адресуемого измерения:
twod_array[addr_expr][addr_expr] threed_array[addr_expr][addr_expr][addr_expr].

Как и раньше, addr_expr может быть любым целочисленным выражением. Массив twod_array получает доступ к целому 8-битному вектору, а массив threed_array — к одному биту трехмерного массива.

Чтобы выразить битовую или частичную выборку элементов массива, сначала должно быть выбрано нужное слово путем указания адреса для каждого измерения. После выбора битовая выборка и частичная выборка адресуются так же, как и битовая выборка и частичная выборка сетей и регистров(см. 5.2.1).

Например:
twod_array[14][1][3:0] // доступ к младшим 4 битам слова twod_array[1][3][6] // доступ к биту 6 слова twod_array[1][3][sel] // использование переменной bit- select threed_array[14][1][3:0] // нелегально

5.2.3 Строки

Строковые операнды должны рассматриваться как постоянные числа, состоящие из последовательности 8-битных кодов ASCII, по одному на символ. Любой оператор Verilog HDL может манипулировать строковыми операндами. Оператор должен вести себя так, как если бы вся строка была одним числовым значением.

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

Например:

В следующем примере объявляется строковая переменная, достаточно большая для хранения 14 символов, и ей присваивается значение. Затем пример манипулирует строкой с помощью оператора конкатенации.
module string_test; reg [8*14:1] stringvar; initial begin stringvar = "Hello world"; $display("%s is stored as %h", stringvar, stringvar); stringvar = {stringvar,"!!!"}; $display("%s is stored as %h", stringvar, stringvar); end endmodule
Результатом моделирования приведенного выше описания является
Hello world хранится как 00000048656c6c6f20776f726c64 Hello world!!! хранится как 48656c6c6f20776f726c64212121

5.2.3.1 Строковые операции

Общие строковые операции копирования, конкатенации и сравнения поддерживаются операторами Verilog HDL. Копирование обеспечивается простым присваиванием. Конкатенация обеспечивается оператором конкатенации. Сравнение обеспечивается операторами равенства.

При манипулировании строковыми значениями в векторных регистров, регистры должны быть не менее 8*n бит (где n — количество символов ASCII), чтобы сохранить 8-битный код ASCII.

5.2.3.2 Подстановка значений строк и потенциальные проблемы

Когда строки присваиваются переменным, хранимые значения должны быть заполнены слева нулями. Набивка может повлиять на результаты операций сравнения и конкатенации. Операторы сравнения и конкатенации не должны различать нули, полученные в результате заполнения, и исходные символы строки (\0, ASCII NUL).

Например:

Следующий пример иллюстрирует потенциальную проблему:
reg [8*10:1] s1, s2; initial begin s1 = "Hello"; s2 = " world!"; if ({s1,s2} == "Hello world!") $display("strings are equal"); end
Сравнение в этом примере не удается, потому что во время присваивания строковые переменные заполняются, как показано в следующем примере:
s1 = 000000000048656c6c6f s2 = 00000020776f726c6421
Конкатенация s1 и s2 включает нулевую прокладку, в результате чего получается следующее значение:
000000000048656c6c6f00000020776f726c6421

5.2.3.3 Работа с нулевой строкой

Нулевая строка («») считается эквивалентной ASCII NUL («0»), которая имеет значение ноль (0), что отличается от строки «0».

5.3 Выражения минимальной, типичной и максимальной задержки

Выражения задержки в Verilog HDL могут быть заданы в виде трех выражений, разделенных двоеточиями и заключенных в круглые скобки. Это предназначено для представления минимального, типичного и максимального значений — именно в таком порядке. Синтаксис приведен в Синтаксисе 5-2.

constant_expression ::= constant_primary | unary_operator { attribute_instance } constant_primary | constant_expression binary_operator { attribute_instance } constant_expression | constant_expression ? { attribute_instance } constant_expression constant_expression constant_mintypmax_expression ::= constant_expression | constant_expression : constant_expression : constant_expression expression ::= primary | unary_operator { attribute_instance } primary | expression binary_operator { attribute_instance } expression | conditional_expression mintypmax_expression ::= expression | expression : expression : expression constant_primary ::= number | parameter_identifier [ [ constant_range_expression ] ] | specparam_identifier [ [ constant_range_expression ] ] | constant_concatenation | constant_multiple_concatenation | constant_function_call | constant_system_function_call | ( constant_mintypmax_expression ) | string primary ::= number | hierarchical_identifier [ { [ expression ] } [ range_expression ] ] | concatenation | multiple_concatenation | function_call | system_function_call | ( mintypmax_expression ) | string
Синтаксис 5-2-Синтаксис для выражения min:typ:max

Модели Verilog HDL обычно задают три значения для выражений задержки. Эти три значения позволяют тестировать проект с минимальным, типичным или максимальным значением задержки.

Значения, выраженные в формате min:typ:max, можно использовать в выражениях. Формат min:typ:max можно использовать везде, где могут появляться выражения. Например:

Пример 1. В этом примере показано выражение, определяющее один триплет значений задержки. Минимальное значение — это сумма a+d; типичное значение — b+e; максимальное значение — c+f, как показано ниже:
(a:b:c) + (d:e:f)
Пример 2. В следующем примере показано типичное выражение, которое используется для указания значений формата min:typ:max:
val - (32'd50: 32'd75: 32'd100)

5.4 Битовая длина выражения

Контроль количества битов, используемых при оценке выражений, важен для достижения согласованных результатов. Некоторые ситуации имеют простое решение. Например, если для двух 16-битных регистров задана побитовая операция и, то результатом будет 16-битное значение.

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

Например, должно ли арифметическое сложение двух 16-битных значений выполнять оценку, используя 16 бит, или оценка должна использовать 17 бит, чтобы обеспечить возможное переполнение переноса? Ответ зависит от типа моделируемого устройства и от того, обрабатывает ли это устройство переполнение переноса. Verilog HDL использует длину битов операндов, чтобы определить, сколько битов использовать при оценке выражения. Правила длины битов приведены в разделе 5.4.1. В случае оператора сложения используется длина бита наибольшего операнда, включая левую часть присваивания.

Например:
reg [15:0] a, b; // 16-битные регистры reg [15:0] sumA; // 16-битный reg [16:0] sumB; // 17-битный reg sumA = a + b; // выражение оценивается по 16 битам sumB = a + b; // выражение оценивается по 17 битам

5.4.1 Правила для битовой длины выражения

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

Самоопределяющееся выражение — это выражение, в котором длина бита выражения определяется исключительно самим выражением — например, выражение, представляющее значение задержки.

Контекстно-детерминированное выражение — это выражение, в котором длина бита выражения определяется длиной бита выражения и тем фактом, что оно является частью другого выражения. Например, размер бита правого выражения присваивания зависит от него самого и размера левой части.

В таблице 5-22 показано, как форма выражения определяет длину битов результатов выражения. i, j и k представляют выражения операнда, а L(i) — длину бита операнда, представленного i.

Умножение может быть выполнено без потери битов переполнения путем присвоения результата чему-либо достаточно широкому, чтобы вместить его.

Таблица 5-22 Длины битов, полученные в результате самоопределяющихся выражений
ВыражениеБитовая длинаКомментарии
Неразмерное постоянное числоТо же, что и целое число
Размер постоянного числаРазмер постоянного числа
op j, где op — это: + — * / % & |^ ^~ ~^max(L(i),L(j))
op i, где op — это: + — ~L(i)
i op j, где op — это: === !== == != > >= < <=1 битРазмер операндов равен max(L(i),L(j)).
i op j, где op — это: && ||1 битВсе операнды определяются самостоятельно
op i, где op — это: & ~& | ~| ^ ~^ ^~ !1 битВсе операнды определяются самостоятельно
i op j, где op — это: >> << ** >>> <<<L(i)j самоопределяется
i ? j : kmax(L(j),L(k))i самоопределяется
{i,…,j}L(i)+…+L(j)Все операнды определяются самостоятельно
{i{j,…,k}}i * (L(j)+…+L(k))Все операнды определяются самостоятельно

5.4.2 Пример проблем битовой длины выражения

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

Учитывая следующие декларации:
reg [15:0] a, b, answer; // 16-битные регистры
намерение состоит в том, чтобы оценить выражение
answer = (a + b) >> 1; //не будет работать не корректно

где a и b должны быть сложены, что может привести к переполнению, а затем сдвинуты вправо на 1 бит, чтобы сохранить бит переноса в 16-битном ответе.

Однако возникает проблема, поскольку все операнды в выражении имеют 16-битную ширину. Поэтому выражение (a + b) дает промежуточный результат шириной всего 16 бит, теряя бит переноса до того, как оценка выполнит операцию сдвига на 1 бит вправо.

Решение заключается в том, чтобы заставить выражение (a + b) оцениваться с использованием как минимум 17 бит. Например, добавление к выражению целого значения 0 приведет к тому, что оценка будет производиться с использованием битового размера целых чисел. Следующий пример приведет к желаемому результату:
answer = (a + b + 0) >> 1; // будет работать не корректно
В следующем примере:
module bitlength(); reg [3:0] a,b,c; reg [4:0] d; initial begin a = 9; b = 8; c = 1; $display("answer = %b", c ? (a&b) : d); end endmodule
оператор \$display отобразит
answer = 01000

Само по себе выражение a&b имело бы длину бита 4, но поскольку оно находится в контексте условного выражения, которое использует максимальную длину бита, выражение a&b фактически имеет длину 5, длину d.

5.4.3 Пример самоопределяющихся выражений

reg [3:0] a; reg [5:0] b; reg [15:0] c; initial begin a = 4'hF; b = 6'hA; $display("a*b=%h", a*b);// expression size is self-determined c = {a**b}; // expression a**b is self-determined // due to concatenation operator {} $display("a**b=%h", c); c = a**b; // expression size is determined by c $display("c=%h", c); end
Выходные данные симулятора для данного примера:
a*b=16 // 'h96 был усечен до 'h16, так как размер выражения равен 6 a**b=1 // размер выражения равен 4 битам (размер a) c=ac61 // размер выражения равен 16 битам (размер c)

5.5 Знаковые выражения

Контроль знака выражения важен для достижения последовательных результатов. В дополнение к правилам, изложенным в пунктах с 5.5.1 по 5.5.4, для обработки приведения типов выражений должны использоваться две системные функции: $signed() и $unsigned(). Эти функции должны оценивать входное выражение и возвращать значение с тем же размером и значением входного выражения и типом, определенным функцией:

$signed — возвращаемое значение подписано

$unsigned — возвращаемое значение является беззнаковым

Например:
reg [7:0] regA, regB; reg signed [7:0] regS; regA = $unsigned(-4); // regA = 8'b11111100 regB = $unsigned(-4'sd4); // regB = 8'b00001100 regS = $signed(4'b1100); // regS =-4

5.5.1 Правила для типов выражений

Ниже приведены правила определения результирующего типа выражения:

  • Тип выражения зависит только от операндов. Он не зависит от левой части (если она есть).
  • Десятичные числа являются знаковыми.
  • Основанные числа являются беззнаковыми, за исключением случаев, когда в спецификаторе основания используется нотация s (как в «4’sd12»).
  • Результаты битового выбора являются беззнаковыми, независимо от операндов.
  • Результаты частичной выборки являются беззнаковыми, независимо от операндов, даже если частичная выборка определяет весь вектор.
reg [15:0] a; reg signed [7:0] b; initial a = b[7:0]; // b[7:0] является беззнаковым и поэтому имеет нулевое расширение
  • Результаты конкатенации являются беззнаковыми, независимо от операндов.
  • Результаты сравнения (1, 0) являются беззнаковыми, независимо от операндов.
  • Величины, преобразованные в целые числа с помощью коэрцитивности типов, являются знаковыми
  • Знак и размер любого самоопределяющегося операнда определяются самим операндом и не зависят от остатка выражения.
  • Для несамоопределяющихся операндов действуют следующие правила:
  • Если любой операнд вещественный, то и результат вещественный.
  • Если любой операнд является беззнаковым, результат будет беззнаковым, независимо от оператора.
  • Если все операнды знаковые, результат будет знаковый, независимо от оператора, за исключением случаев, когда указано иное.

5.5.2 Шаги для оценки выражения

Ниже перечислены шаги для оценки выражения:

  • Определите размер выражения, руководствуясь стандартными правилами определения размера выражения.
  • Определите знак выражения, используя правила, изложенные в пункте 5.5.1.
  • Передайте тип и размер выражения (или самоопределенного подвыражения) обратно вниз по контекстно-определенным операндам выражения. В общем случае любой контекстно-определенный операнд оператора должен иметь тот же тип и размер, что и результат оператора. Однако есть два исключения:
  • Если тип результата оператора является вещественным и если он имеет определяемый контекстом операнд, который не является вещественным, то этот операнд должен рассматриваться как самоопределяющийся. Затем преобразовываться в вещественный непосредственно перед применением оператора.
  • Реляционный оператор и оператор равенства имеют операнды, которые не являются ни полностью самоопределяемыми, ни полностью контекстно-определяемыми. Операнды должны воздействовать друг на друга так, как если бы они были контекстно-определенными операндами с типом результата и размером (максимальным из двух размеров операндов), определенным на их основе. Однако, фактический тип результата всегда должен быть 1-битным беззнаковым. Тип и размер операнда не зависят от остальной части выражения и наоборот.
  • Когда распространение достигает простого операнда, как определено в 5.2, то этот операнд должен быть преобразован к распространенному типу и размеру. Если операнд должен быть расширен, то он должен быть расширен по знаку, только если распространяемый тип является знаковым.

5.5.3 Шаги для оценки присваивания

Ниже перечислены шаги по оценке присваивания:

  • Определите размер правой части по стандартным правилам определения размера присваивания(см. 5.4).
  • При необходимости расширьте размер правой стороны, выполняя расширение знака тогда и только тогда, когда тип правой стороны знаковый.

5.5.4 Работа с X и Z в знаковых выражениях

Если знаковый операнд должен быть изменен на большую ширину знака и значение знакового бита равно X, то результирующее значение должно быть побитово заполнено Xs. Если знаковый бит значения равен Z, то результирующее значение должно быть побитно заполнено Zs. Если любой бит знакового значения равен X или Z, то в результате любой нелогической операции над значением все результирующее значение будет X, а тип будет соответствовать типу выражения.

5.6 Присваивания и усечение

Если ширина правой части выражения больше, чем ширина левой части в присваивании, MSBs правой части выражения всегда отбрасываются, чтобы соответствовать размеру левой части. Реализации не обязаны предупреждать или сообщать о каких-либо ошибках, связанных с несоответствием размера присваивания или усечением. Усечение знакового бита знакового выражения может изменить знак результата.

Например:
reg [5:0] a; reg signed [4:0] b; initial begin a = 8'hff; // После присваивания, a = 6'h3f b = 8'hff; // После присваивания, b = 5'h1f end
Например:
reg [0:5] a; reg signed [0:4] b, c; initial begin a = 8'sh8f; // После присваивания, a = 6'h0f b = 8'sh8f; // После присваивания, b = 5'h0f c = -113; // После присваивания, c = 15 // 1000_1111 = (-'h71 = -113) усекает до ('h0F = 15) end
Например:
reg [7:0] a; reg signed [7:0] b; reg signed [5:0] c, d; initial begin a = 8'hff; c = a; // После присваивания, c = 6'h3f b = -113; d = b; // После присваивания, d = 6'h0f end