DocsTech
/
VERILOG HDL
/

~ cd 5. выражения и операторы verilog hdl

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

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

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

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

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

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, деленное на 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

Индексы частичного выбора, которые оцениваются как 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 Правила для типов выражений

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

...
Копировать
reg [15:0] a;
reg signed [7:0] b;
initial
    a = b[7:0]; // b[7:0] является беззнаковым и поэтому имеет нулевое расширение

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

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

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

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

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
Главная
Курсы
Вебинары
3. Лексические правила(Синтаксис) Verilog HDL
4. Типы данных Verilog HDL
5. Выражения и Операторы Verilog HDL
6. Назначения (Assignments) в Verilog HDL
7. Моделирование на уровне вентилей и переключателей в Verilog HDL
8. Примитивы, объявляемые пользователем (UDP) Verilog HDL
9. Процедурные назначения. Поведенческое моделирование в Verilog HDL.
9. If, case for, while и repeat Verilog HDL
9. Initial, always, задержки, блоки Verilog HDL
10. Задачи(task) и функции (function) в Verilog HDL
11. Семантика планирования. Стек (stack) в Verilog HDL
12. Модули(module). Переопределение параметров(defparam).
12. Порты. Иерархические имена в Verilog HDL
12. Generate блоки Verilog HDL
12. Иерархические имена Verilog HDL
13. Конфигурирование содержимого конструкции
13. Использование библиотек. Конфигурирование содержимого конструкции в Verilog HDL
14. Specify блоки в Verilog HDL
15. Setup, hold, setuphold и recovery в Verilog HDL
15. Skew, period, width и nochange Verilog HDL
15. Проверка синхронизации сигналов в Verilog HDL
16. Бэканнотирование с использованием стандартного формата задержки (SDF) в Verilog HDL
17. Системные задачи и функции
17.2 Файлы. Запись и чтение файлов Verilog
17. Задачи временной шкалы, управления, PLA и стохастического анализа Verilog
$time, $stime и $realtime Verilog
17.8. Функции преобразования Verilog
17.9. Функции распределения вероятностей Verilog
17.10. Ввод командной строки. 17.11. Математические функции
18. Дамп файлы изменения значений (VCD)
18. Формат файла VCD расширенные и четырьмя состояниями
19. Директивы компилятора Verilog HDL
20. Обзор интерфейса языка программирования (PLI) Verilog
28. Зашифрованные оболочки
Закрыть