- 5.1 Операторы
- 5.1.1. Операторы с вещественными операндами
- 5.1.2 Старшинство операторов
- 5.1.3 Использование целых чисел в выражениях
- 5.1.4 Порядок оценки выражений
- 5.1.5 Арифметические операторы
- 5.1.6 Арифметические выражения с регистрами и целыми числами
- 5.1.7 Реляционные операторы
- 5.1.8 Операторы равенства
- 5.1.9 Логические операторы
- 5.1.10 Побитовые операторы
- 5.1.11 Операторы редукции
- 5.1.12 Операторы сдвига
- 5.1.13 Условный оператор
- 5.1.14 Конкатенации
- 5.2 Операнды
- 5.2.1 Битовая и частичная выборка адресации вектора
- 5.2.2 Адресация массивов и памяти
- 5.2.3 Строки
- 5.2.3.1 Строковые операции
- 5.2.3.2 Подстановка значений строк и потенциальные проблемы
- 5.2.3.3 Работа с нулевой строкой
- 5.3 Выражения минимальной, типичной и максимальной задержки
- 5.4 Битовая длина выражения
- 5.4.1 Правила для битовой длины выражения
- 5.4.2 Пример проблем битовой длины выражения
- 5.4.3 Пример самоопределяющихся выражений
- 5.5 Знаковые выражения
- 5.5.1 Правила для типов выражений
- 5.5.2 Шаги для оценки выражения
- 5.5.3 Шаги для оценки присваивания
- 5.5.4 Работа с X и Z в знаковых выражениях
- 5.6 Присваивания и усечение
Выражение — это конструкция, объединяющая операнды с операторами для получения результата, который является функцией значений операндов и семантического значения оператора. Любой легальный операнд, например, 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 перечислены эти операторы.
Оператор | Тип оператора |
---|---|
{} {{}} | Конкатенация, репликация |
унарный + унарный — | Унарные операторы |
+ — * / ** | Арифметические |
% | Модуль |
> >= < <= | Реляционные |
! | Логическое отрицание |
&& | Логический и |
|| | Логический или |
== | Логическое равенство |
!= | Логическое неравенство |
=== | Эквивалентность |
!== | Неравенств |
~ | Побитовое отрицание |
& | Побитовая и |
| | Побитовое или |
^ | Побитовое исключающее или |
^~ или ~^ | Побитовая эквивалентность |
& | Редуцированный и |
~& | Редуцированный не и |
| | Редуцированный или |
~| | Редуцированный не и |
^ | Редуцированный xor |
~^ или ^~ | Редуцированный xnor |
<< | Логический сдвиг влево |
>> | Логический сдвиг вправо |
<<< | Арифметический сдвиг влево |
>>> | Арифметический сдвиг вправо |
? : | Условный |
5.1.1. Операторы с вещественными операндами
Операторы, приведенные в таблице 5-2, являются разрешенные при применении к вещественным операндам. Все остальные операторы считаются незаконными при использовании с вещественными операндами.
Результатом использования логических или реляционных операторов над вещественными числами является однобитное скалярное значение.
Оператор | Тип оператора |
---|---|
унарный + унарный — | Унарные операторы |
+ — * / ** | Арифметические |
> >= < <= | Реляционные |
! && || | Логические |
== != | Логическое равенство |
?: | Условный |
В таблице 5-3 перечислены операторы, которые не должны использоваться для работы с вещественными числами.
Оператор | Наименование оператора |
---|---|
{} {{}} | Конкатенировать, реплицировать |
% | Модуль |
=== !== | Равенство типов |
~ & | ^ ^~ ~^ | Побитовая |
^ ^~ ~^ & ~& | ~| | Реляционные |
<< >> <<< >>> | Сдвиги |
Более подробную информацию об использовании вещественных чисел см. в разделе 4.8.1.
5.1.2 Старшинство операторов
Порядок старшинства операторов Verilog показан в таблице 5-4.
Операторы, показанные в одной строке в таблице 5-4, имеют одинаковый приоритет. Строки расположены в порядке убывания старшинства операторов. Например, *, / и % имеют одинаковый приоритет, который выше, чем у двоичных операторов + и —.
A + B - C
A + B / C
(A + B) / C // не то же самое, что A + B / C
Операторы | Приоритет |
---|---|
+ — ! ~ & ~& | ~| ^ ~^ ^~ (унарный) | Наивысший приоритет |
** | |
* / % | |
+ — (бинарный) | |
<< >> <<< >>> | |
< <= > >= | |
== != === !== | |
& (бинарный) | |
^ ^~ ~^ (двоичный) | |
| (двоичный) | |
&& | |
|| | |
?: (условный оператор) | |
{} {{}} | Наименьший приоритет |
5.1.3 Использование целых чисел в выражениях
Целые числа можно использовать в качестве операндов в выражениях. Целое число может быть выражено как
- Неразмерное, небазированное целое число (например, 12)
- Неразмерное целое число с основанием (например, ‘d12, ‘sd12)
- Целое число, имеющее размер (например, 16’d12, 16’sd12)
Отрицательное значение для целого числа без спецификатора основания интерпретируется иначе, чем для целого числа со спецификатором основания. Целое число без спецификатора основания интерпретируется как знаковое значение в двухкомпонентной форме. Целое число с беззнаковым спецификатором основания интерпретируется как беззнаковое значение.
Например:
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.
Синтаксис арифметических операторов | Комментарий к синтаксису |
---|---|
a + b | а плюс б |
a — b | a минус b |
a * b | a умноженное на b |
a / b | a, деленное на b |
a % b | a по модулю b |
a ** b | a в степени b |
При целочисленном делении любая дробная часть должна быть усечена до нуля. Для операторов деления или модуляции, если второй операнд — ноль, то все значение результата должно быть x. Оператор модуляции (например, y % z) дает остаток, когда первый операнд делится на второй, и, таким образом, равен нулю, когда z делит y ровно. Результат операции по модулю принимает знак первого операнда.
Если один из операндов оператора электропитания является вещественным, то тип результата должен быть вещественным. Результат оператора электропитания не определен, если первый операнд равен нулю, а второй операнд неположителен или если первый операнд отрицателен, а второй операнд не является интегральным значением.
Если ни один из операндов оператора электропитания не является вещественным, то тип результата определяется в соответствии с пунктами 5.4.1 и 5.5.1. Значение результата равно ‘bx, если первый операнд равен нулю, а второй отрицателен. Значение результата равно 1, если второй операнд равен нулю.
Во всех случаях второй операнд оператора электропитания должен рассматриваться как самоопределяющийся. Эти утверждения проиллюстрированы в таблице 5-6.
op1 это op2 это | < -1 | -1 | ноль | 1 | > 1 |
---|---|---|---|---|---|
положительный | op1 ** op2 | op2 нечетный ->-1 op2 четный ->1 | 0 | 1 | op1 ** op2 |
ноль | 1 | 1 | 1 | 1 | 1 |
отрицательный | 0 | op2 нечетный ->-1 op2 четный ->1 | ‘bx | 1 | 0 |
Унарные арифметические операторы имеют приоритет перед двоичными операторами. Унарные операторы приведены в таблице 5-7.
Синтаксис унарных операторов | Комментарий к синтаксису |
---|---|
+m | Унарный плюс m (то же, что m) |
-m | Унарный минус m |
Для арифметических операторов, если любое значение бита операнда является неизвестным значением x или высокоимпедансным значением z, то все значение результата должно быть x.
Например:
В таблице 5-8 приведены примеры некоторых операций с модулем и мощностью.
Выражение | Результат | Комментарии |
---|---|---|
10 % 3 | 1 | 10/3 дает остаток, равный 1. |
11 % 3 | 2 | 11/3 дает остаток 2. |
12 % 3 | 0 | 12/3 не дает никакого остатка. |
-10 % 3 | -1 | Результат принимает знак первого операнда. |
11 % -3 | 2 | Результат принимает знак первого операнда |
-4’d12 % 3 | 1 | -4’d12 рассматривается как большое положительное число, которое при делении на 3 оставляет остаток 1. |
3 ** 2 | 9 | 3 * 3 |
2 ** 3 | 8 | 2 * 2 * 2 |
2 ** 0 | 1 | Все, что до нулевой экспоненты, равно 1. |
0 ** 0 | 1 | Ноль по нулевой экспоненте также равен 1. |
2.0 ** -3’sb1 | 0.5 | 2.0 — является вещественным, дающая вещественную взаимность. |
2 ** -3 ‘sb1 | 0 | 2 ** -1 = 1/2. Целочисленное деление усекается до нуля. |
0 ** -1 | ‘bx | 0 ** -1 = 1/0. Целочисленное деление на ноль — это ‘bx. |
9 ** 0.5 | 3.0 | Действительный квадратный корень. |
9.0 ** (1/2) | 1.0 | Целочисленное деление усекает экспоненту до нуля. |
-3.0 ** 2.0 | 9.0 | Определено, так как вещественное значение 2.0 все еще является интегральным значением. |
5.1.6 Арифметические выражения с регистрами и целыми числами
Значение, присвоенное переменной reg или net, рассматривается как беззнаковое значение, если только переменная reg или net не была явно объявлена как знаковая. Значение, присвоенное переменной integer, real или realtime, должно рассматриваться как знаковое. Значение, присвоенное time переменной, рассматривается как беззнаковое.
Знаковые значения, за исключением тех, которые присваиваются переменным real и realtime, должны использовать двухкомпонентное представление.
Значения, присваиваемые переменным real и realtime, должны использовать представление с плавающей точкой. Преобразования между знаковыми и беззнаковыми значениями должны сохранять то же представление битов; меняется только интерпретация.
В таблице 5-9 перечислено, как арифметические операторы интерпретируют каждый тип данных.
Тип данных | Интерпретация |
---|---|
unsigned net | Беззнаковый |
signed net | Знаковый, двойное дополнение |
unsigned reg | Беззнаковый |
signed reg | Знаковый, двойное дополнение |
integer | Знаковый, двойное дополнение |
time | Беззнаковый |
real, realtime | Знаковый, с плавающей запятой |
Например:
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 перечислены и определены реляционные операторы.
Синтаксис оператора | Комментарий |
---|---|
a < b | a меньше b |
a > b | a больше b |
a <= b | a меньше или равно b |
a >= b | a больше или равно 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 перечислены и определены операторы равенства.
Оператор | Значение операции |
---|---|
a === b | a равно b, включая x и z |
a !== b | a не равно b, включая x и z |
a == b | a равно b, результат может быть неизвестен |
a != b | a не равно 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.
Например:
regA = alpha && beta; //regA устанавливается в 0
regB = alpha || beta; // regB устанавливается в 1
a < size-1 && b != c && index != lastone
(a < size-1) && (b != c) && (index != lastone)
if (!inword)
if (inword == 0)
5.1.10 Побитовые операторы
Побитовые операторы должны выполнять побитовые манипуляции с операндами; то есть оператор должен объединить бит в одном операнде с соответствующим битом в другом операнде, чтобы вычислить 1 бит для результата. Логические таблицы с 5-12 по 5-16 показывают результаты для каждого возможного вычисления.
Оператор &(and) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | 0 | 0 | 0 |
Значение 1 | 0 | 1 | x | x |
Значение x | 0 | x | x | x |
Значение z | 0 | x | x | x |
Оператор |(or) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | 1 | x | x |
Значение 1 | 1 | 1 | 1 | 1 |
Значение x | x | 1 | x | x |
Значение z | x | 1 | x | x |
Оператор ^(исключающее or) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | 1 | x | x |
Значение 1 | 1 | 0 | x | x |
Значение x | x | x | x | x |
Значение z | x | x | x | x |
Оператор ^~ ~^(nor) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 1 | 0 | x | x |
Значение 1 | 0 | 1 | x | x |
Значение x | x | x | x | x |
Значение z | x | x | x | x |
Оператор ~(отрицания) | Результат |
---|---|
Значение 0 | 1 |
Значение 1 | 0 |
Значение x | x |
Значение z | x |
Если операнды имеют неодинаковую длину бита, более короткий операнд заполняется нулями в позициях старшего бита.
5.1.11 Операторы редукции
Унарные операторы редукции должны выполнять побитовую операцию над одним операндом для получения однобитового результата. Для операторов reduction and, reduction or и reduction xor первый шаг операции должен применять оператор между первым битом операнда и вторым, используя логические таблицы 5-17 — 5-19. На втором и последующих шагах оператор применяется между 1-битным результатом предыдущего шага и следующим битом операнда с использованием той же логической таблицы. Для операторов reduction nand, reduction nor и reduction xnor результат вычисляется путем инвертирования результата операций reduction and, reduction or и reduction xor соответственно.
Например:
&(reduction and) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | 0 | 0 | 0 |
Значение 1 | 0 | 1 | x | x |
Значение x | 0 | x | x | x |
Значение z | 0 | x | x | x |
|(reduction or) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | 1 | x | x |
Значение 1 | 1 | 1 | 1 | 1 |
Значение x | x | 1 | x | x |
Значение z | x | 1 | x | x |
^(reduction исключающее or) | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | 1 | x | x |
Значение 1 | 1 | 0 | x | x |
Значение x | x | x | x | x |
Значение z | x | x | x | x |
Например:
В таблице 5-20 показаны результаты применения операторов сокращения к различным операндам.
Операнд | & | ~& | | | ~| | ^ | ~^ | Комментарии |
---|---|---|---|---|---|---|---|
4’b0000 | 0 | 1 | 0 | 1 | 0 | 1 | Биты не установлены |
4’b1111 | 1 | 0 | 1 | 0 | 0 | 1 | Все биты установлены |
4’b0110 | 0 | 1 | 1 | 0 | 0 | 1 | Четное количество установленных битов |
4’b1000 | 0 | 1 | 1 | 0 | 1 | 0 | Нечетное количество установленных битов |
5.1.12 Операторы сдвига
Существует два типа операторов сдвига: логические операторы сдвига, << и >>, и арифметические операторы сдвига, <<< и >>>. Операторы сдвига влево, << и <<<, сдвигают свой левый операнд влево на число на количество битовых позиций, заданных правым операндом. В обоих случаях освободившиеся битовые позиции должны быть заполнены нулями. Операторы сдвига вправо, >> и >>>, сдвигают свой левый операнд вправо на количество битовых позиций, заданных правым операндом. Логический сдвиг вправо должен заполнить освободившиеся битовые позиции нулями. Арифметический сдвиг вправо должен заполнить освободившиеся битовые позиции нулями, если тип результата беззнаковый. Он должен заполнить освободившиеся битовые позиции значением старшего (т.е. знакового) бита левого операнда, если тип результата знаковый. Если правый операнд имеет значение x или z, то результат будет неизвестен. Правый операнд всегда рассматривается как беззнаковое число и не влияет на знаковость результата. Знаковость результата определяется левым операндом и остатком выражения, как описано в пункте 5.5.1.
Например:
module shift;
reg [3:0] start, result;
initial begin
start = 1;
result = (start << 2);
end
endmodule
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.8) expression1 с нулем, называемого условием. Если условие равно false (0), то expression3 оценивается и используется как результат условного выражения. Если условие оценивается как true (1), то expression2 оценивается и используется в качестве результата. Если условие оценивается в неоднозначное значение (x или z), то оцениваются оба expression2 и expression3, и их результаты объединяются, бит за битом, с использованием таблицы 5-21 для вычисления окончательного результата, если только expression2 или expression3 не является вещественным, в этом случае результатом будет 0. Если длины expression2 и expression3 различны, то более короткий операнд должен быть удлинен до соответствия более длинному и заполнен нулями слева (старший конец).
Условный оператор ?: | Значение 0 | Значение 1 | Значение x | Значение z |
---|---|---|---|---|
Значение 0 | 0 | x | x | x |
Значение 1 | x | 1 | x | x |
Значение x | x | x | x | x |
Значение z | x | x | x | x |
Например:
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.
{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 будет недопустимой.
vect[msb_expr:lsb_expr]
И msb_expr, и lsb_expr должны быть константными целочисленными выражениями. Первое выражение должно адресовать более значимый бит, чем второе выражение.
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 с фиксированной шириной
Например:
acc[index]
reg [15:0] acc;
reg [2:17] acc;
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]
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 может манипулировать строковыми операндами. Оператор должен вести себя так, как если бы вся строка была одним числовым значением.
Если переменная больше, чем требуется для хранения присваиваемого значения, содержимое после присваивания должно быть заполнено слева нулями. Это соответствует заполнению, которое происходит при присвоении нестроковых значений.
Например:
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
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
Модели Verilog HDL обычно задают три значения для выражений задержки. Эти три значения позволяют тестировать проект с минимальным, типичным или максимальным значением задержки.
Значения, выраженные в формате min:typ:max, можно использовать в выражениях. Формат min:typ:max можно использовать везде, где могут появляться выражения. Например:
(a:b:c) + (d:e:f)
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.
Умножение может быть выполнено без потери битов переполнения путем присвоения результата чему-либо достаточно широкому, чтобы вместить его.
Выражение | Битовая длина | Комментарии |
---|---|---|
Неразмерное постоянное число | То же, что и целое число | |
Размер постоянного числа | Размер постоянного числа | |
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 : k | max(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 бит вправо.
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
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