3. Лексические правила(Синтаксис) Verilog HDL

В этом пункте описываются лексические лексемы, используемые в исходном тексте Verilog HDL, и их соглашения.
Содержание
Превью(обложка) видео для поста 3. Лексические правила(Синтаксис) Verilog HDL

3.1 Лексические единицы

Текстовые файлы исходных текстов Verilog HDL должны представлять собой поток лексических единиц. Лексическая единица должна состоять из одного или нескольких символов. Расположение лексем в исходном файле должно быть свободного формата, то есть пробелы и новые строки не должны быть синтаксически значимыми, кроме как разделителями лексем, за исключением экранированных идентификаторов (см. 3.7.1).

Типы лексических единиц в языке следующие:

  • Разделительные символы (white spaces)
  • Комментарий
  • Оператор
  • Число
  • Строка
  • Идентификатор
  • Ключевое слово

3.2 Разделительные символы (white spaces)

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

3.3 Комментарии

В Verilog HDL есть две формы комментариев. Однострочный комментарий начинается с двух символов // и заканчивается новой строкой. Блочный комментарий начинается с /* и заканчивается */. Блочные комментарии не должны быть вложенными. Маркер однострочного комментария // внутри блочного комментария не имеет какого-либо специального значения

3.4 Операторы

Операторы — это одно-, двух- или трехсимвольные последовательности, которые используются в выражениях. В пункте 5 рассматривается использование операторов в выражениях.

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

3.5 Числа

Числовые константы могут быть заданы как целочисленные (определены в разделе 3.5.1) или вещественные константы.

number ::= decimal_number | octal_number | binary_number | hex_number | real_number real_numbera ::= unsigned_number . unsigned_number | unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number exp ::= e | E decimal_number ::= unsigned_number | [ size ] decimal_base unsigned_number | [ size ] decimal_base x_digit { _ } | [ size ] decimal_base z_digit { _ } binary_number ::= [ size ] binary_base binary_value octal_number ::= [ size ] octal_base octal_value hex_number ::= [ size ] hex_base hex_value sign ::= + | - size ::= non_zero_unsigned_number non_zero_unsigned_numbera ::= non_zero_decimal_digit { _ | decimal_digit} unsigned_numbera ::= decimal_digit { _ | decimal_digit } binary_valuea ::= binary_digit { _ | binary_digit } octal_valuea ::= octal_digit { _ | octal_digit } hex_valuea ::= hex_digit { _ | hex_digit } decimal_basea ::= '[s|S]d | '[s|S]D binary_basea ::= '[s|S]b | '[s|S]B octal_basea::= '[s|S]o | '[s|S]O hex_basea ::= '[s|S]h | '[s|S]H non_zero_decimal_digit ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 decimal_digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 binary_digit ::= x_digit | z_digit | 0 | 1 octal_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 hex_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | A | B | C | D | E | F x_digit ::= x | X z_digit ::= z | Z | ?
Синтаксис 3.1 Синтаксис для целых и вещественных чисел

3.5.1 Целочисленные константы

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

Существует две формы для выражения целочисленных констант. Первая форма — это простое десятичное число, которое задается как последовательность цифр от 0 до 9, по выбору начинающаяся с унарного оператора плюс или минус. Вторая форма определяет константу с основанием, которая должна состоять максимум из трех лексем — необязательной константы размера, символа апострофа (, ASCII 0x27), за которым следует символ формата основания, и цифр, представляющих значение числа. Макрозамена этих трех лексем должна быть законной.

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

Второй маркер, base_format, должен состоять из нечувствительной к регистру буквы, указывающей основание для числа, опционально перед ней должен стоять одиночный символ s (или S) для указания знакового числа, перед которым ставится символ апострофа. Разрешенные спецификации оснований: d, D, h, H, o, O, b или B для десятичного, шестнадцатеричного, восьмеричного и двоичного оснований соответственно.

Символ апострофа и символ формата основания не должны разделяться пробелами.

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

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

Оператор плюс или минус, предшествующий константе размера, является унарным оператором плюс или минус. Оператор плюс или минус между базовым форматом и числом является недопустимым синтаксисом.

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

Символ x представляет неизвестное значение в шестнадцатеричной, восьмеричной и двоичной константах. Символ z представляет значение высокого импеданса. Обсуждение набора значений Verilog HDL см. в разделе 4.1. Символ x устанавливает 4 бита в неизвестное значение в шестнадцатеричном базисе, 3 бита в восьмеричном базисе и 1 бит в двоичном базисе. Аналогично, символ z устанавливает 4 бита, 3 бита и 1 бит, соответственно, в значение высокого импеданса.

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

Количество битов, составляющих безразмерное число (которое является простым десятичным числом или числом без спецификации размера), должно быть не менее 32. Безразмерные беззнаковые константы, где старший бит неизвестен (X или x) или трехсоставной (Z или z), должны быть расширены до размера выражения, содержащего константу.

В стандарте IEEE Std 1364-1995 в безразмерных константах, где старший бит неизвестен или имеет третье состояние, x или z были расширены только до 32 бит. Использование x и z при определении значения числа не зависит от регистра.

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

При использовании в числе символ вопросительного знака (?) является альтернативой символу z в Verilog HDL. Он устанавливает 4 бита на высокоимпедансное значение в шестнадцатеричных числах, 3 бита в восьмеричных и 1 бит в двоичных. Знак вопроса может использоваться для улучшения читаемости в случаях, когда значение высокого импеданса является условием «не заботиться». См. обсуждение casez и casex в разделе 9.5.1. Символ вопросительного знака также используется в таблицах состояний примитивов, определяемых пользователем (UDP). См. таблицу 8-1 в разделе 8.1.6.

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

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

Например:

Пример 1 — Безразмерные числовые константы
659 // - десятичное число 'h837FF // шестнадцатеричное число 'o7460 // восьмеричное число 4af // является недопустимым (шестнадцатеричный формат требует 'h)
Пример 2— Размерные числовые константы
4'b1001 // - 4-битное двоичное число 5'D3 // - 5-битное десятичное число 3'b01x // - трехбитовое число с наименьшим значением // значащий бит неизвестен 12'hx // это 12-битное неизвестное число 16'hz // - 16-битное высокоимпедансное число
Пример 3 — Использование знака с числовыми константами
8'd-6 // это незаконный синтаксис -8'd6 // это определяет дополнение двойки к 6, // хранится в 8 битах - эквивалентно -(8'd 6) 4'shf // это обозначает 4-битное число "1111", к // интерпретируется как число с дополнением 2, // или '-1'. Это эквивалентно -4'h 1 -4'sd15 //это эквивалентно -(-4'd 1), или '0001' 16'sd? // то же самое, что 16'sbz
Пример 4 — Автоматическое заполнения левого пространства
reg [11:0] a, b, c, d; initial begin a = 'h x; // yields xxx b = 'h 3x; // yields 03x c = 'h z3; // yields zz3 d = 'h 0z3; // yields 0z3 end reg [84:0] e, f, g; e = 'h5; // yields {82{1'b0},3'b101} f = 'hx; // yields {85{1'hx}} g = 'hz; // yields {85{1'hz}}
Пример 5 — Использование символа подчеркивания в числах
27_195_000 16'b0011_0101_0001_1111 32'h12ab_f001

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

Длина x и z по умолчанию такая же, как длина целого числа по умолчанию.

3.5.2 Вещественные константы

Вещественные числовые константы должны быть представлены в соответствии со стандартом IEEE Std 754-1985, стандартом IEEE для чисел двойной точности с плавающей точкой. Вещественные числа могут быть заданы как в десятичной системе счисления (например, 14,72), так и в научной системе счисления (например, 39e8, что означает 39, умноженное на 10 в восьмой степени). Вещественные числа, выраженные с десятичной точкой, должны иметь по крайней мере по одной цифре с каждой стороны десятичной точки.

Например:
1.2 0.1 2394.26331 1.2E12 1.30e-2 0.1e-0 23E10 29E-2 236.123_763_e-12
Приведенные ниже формы вещественных чисел являются невещественными , так как не имеют по крайней мере по одной цифре с каждой стороны десятичной точки:
.12 9. 4.E3 .2e-7

3.5.3 Преобразование

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

  • Действительные числа 35,7 и 35,5 при преобразовании в целое число становятся 36, а 35,2 в 35.
  • Преобразование -1,5 в целое число дает -2, преобразование 1,5 в целое число дает 2.

3.6 Строки

Строка — это последовательность символов, заключенная в двойные кавычки («») и содержащаяся в одной строке. Строки, используемые в качестве операндов в выражениях и присваиваниях, должны рассматриваться как беззнаковые целочисленные константы, представленные последовательностью 8-битных значений ASCII, причем одно 8-битное значение ASCII представляет один символ.

3.6.1 Объявление строковой переменной

Строковые переменные — это переменные типа reg (см. 4.2) с шириной, равной количеству символов в строке, умноженному на 8.

Например:

Для хранения 12-символьной строки «Hello world!» требуется reg 8 * 12, или 96 бит.
reg [8*12:1] stringvar; initial begin stringvar = "Hello world!"; end

3.6.2 Работа со строками

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

Например:
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

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

3.6.3 Специальные символы в строках

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

Таблица 3-1 — Указание специальных символов в строке
Спец. СимволыСимвол, создаваемый управляющей строкой
\nNewline character
\tTab character
\\\ character
» character
\dddA character specified in 1–3 octal digits (0 ≤ d ≤ 7). If less than three characters are used, the following character shall not be an octal digit.

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

Идентификатор используется для присвоения объекту уникального имени, чтобы на него можно было ссылаться. Идентификатор — это либо простой идентификатор, либо экранированный идентификатор (см. 3.7.1). Простой идентификатор представляет собой любую последовательность букв, цифр, знаков доллара ($) и подчеркивания (_).

Первый символ простого идентификатора не должен быть цифрой или $. Это может быть буква или знак подчеркивания. Идентификаторы должны быть чувствительны к регистру.

Например:
shiftreg_a busa_index error_condition merge_ab _bus3 n$657

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

3.7.1 Экранированные идентификаторы

Экранированные идентификаторы должны начинаться с символа обратной косой черты (\ и заканчиваться белым пробелом (пробел, табуляция, новая строка). Они позволяют включить в идентификатор любой из печатаемых символов ASCII (десятичные значения от 33 до 126, или от 21 до 7E в шестнадцатеричной системе).

Ни ведущий символ обратной косой черты, ни завершающий пробел не считаются частью идентификатора. Таким образом, экранированный идентификатор \cpu3 рассматривается так же, как и неэкранированный идентификатор cpu3.

Например:
\busa+index \-clock \***error-condition*** \net1/\net2 \{a,b} \a*(b+c)

3.7.2 Ключевые слова

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

Все ключевые слова задаются только в нижнем регистре.

3.7.3 Задачи и функции системы

Знак доллара ($) представляет языковую конструкцию, которая позволяет разрабатывать определяемые пользователем системные задачи и функции. Системные конструкции не являются семантикой проектирования, а относятся к функциональности симулятора. Имя, следующее за $, интерпретируется как системная задача или системная функция.

Синтаксис системной задачи/функции приведен в разделе Синтаксис 3-2.
system_task_enable ::= system_task_identifier [ ( [ expression ] { , [ expression ] } ) ] ; system_function_call ::= system_function_identifier [ ( expression { , expression } ) ] system_function_identifiera ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] } system_task_identifiera ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] }

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

system_task_enable ::= system_task_identifier [ ( [ expression ] { , [ expression ] } ) ] ; system_function_call ::= system_function_identifier [ ( expression { , expression } ) ] system_function_identifiera::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] } system_task_identifiera ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] }
Синтаксис 3-2-Синтаксис для системных задач и функций

Задача/функция системы $identifier может быть определена в трех местах:

  • Стандартный набор задач и функций системы $identifier, как определено в п. 17 и п. 18.
  • Дополнительные задачи и функции системы $identifier, определенные с помощью PLI, как описано в п. 20.
  • Дополнительные задачи и функции системы $identifier, определяемые программными реализациями.

В качестве имени системной задачи/функции может использоваться любой допустимый идентификатор, включая ключевые слова, уже используемые в контекстах, отличных от данной конструкции. Системные задачи и функции, описанные в п. 17 и п. 18, являются частью настоящего стандарта. Дополнительные системные задачи и функции с конструкцией $identifier не являются частью настоящего стандарта.

Например:
$display("display a message"); $finish;

3.7.4 Директивы компилятора

Символ ` (значение ASCII 0x60, называемое grave accent) представляет собой языковую конструкцию, используемую для реализации директив компилятора. Поведение компилятора, продиктованное директивой компилятора, вступает в силу, как только компилятор прочитает эту директиву. Директива остается в силе до конца компиляции, если в другой директиве компилятора не указано иное. Поэтому директива компилятора в одном файле описания может управлять поведением компилятора в нескольких файлах описания.

Директива компилятора `identifier может быть определена в двух местах:

  • Стандартный набор директив компилятора `identifier, определенный в п. 19.
  • Дополнительные директивы компилятора `identifier, определяемые программными реализациями.

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

Директивы компилятора, описанные в п. 19, являются частью настоящего стандарта. Дополнительные директивы компилятора с конструкцией `identifier не являются частью настоящего стандарта.

Например:
`define wordsize 8

3.8 Атрибуты

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

Синтаксис для указания атрибута показан в Синтаксис 3-3.

attribute_instance ::= (* attr_spec { , attr_spec } *) attr_spec ::= attr_name [ = constant_expression ] attr_name ::= identifier
Синтаксис 3-3 — Синтаксис для атрибутов

Attribute_instance может появиться в описании Verilog как префикс, прикрепленный к объявлению, элементу модуля, оператору или соединению порта. Он может появиться как суффикс к оператору или имени функции Verilog в выражении.

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

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

3.8.1 Примеры

Пример 1 — В следующем примере показано, как прикрепить атрибуты к оператору case:
(* full_case, parallel_case *) case (foo) <rest_of_case_statement> (* full_case=1 *) (* parallel_case=1 *) // Множественные экземпляры атрибутов также OK case (foo) <rest_of_case_statement> //или (* full_case, // Значение не присвоено parallel_case=1 *) case (foo) <rest_of_case_statement>
Пример 2 — Присоединить атрибут full_case, но не атрибут parallel_case: (* full_case *) // parallel_case не указан
(* full_case *) // parallel_case not specified case (foo) <rest_of_case_statement> //или (* full_case=1, parallel_case = 0 *) case (foo) <rest_of_case_statement>
Пример 3 Прикрепить атрибут к определению модуля:
(* optimize_power *) module mod1 (<port_list>); //или (* optimize_power=1 *) module mod1 (<port_list>);
Пример 4 Прикрепить атрибут к экземпляру модуля:
(* optimize_power=0 *) mod1 synth1 (<port_list>);
Пример 5 Присоединение атрибута к объявлению reg:
(* fsm_state *) reg [7:0] state1; (* fsm_state=1 *) reg [3:0] state2, state3; reg [3:0] reg1; // у этого reg НЕ установлен fsm_state (* fsm_state=0 *) reg [3:0] reg2; // и у этого тоже
Пример 6 — Для присоединения атрибута к оператору:
a = b + (* mode = "cla" *) c;

Это устанавливает значение атрибута mode как строку cla.

Пример 7 — Прикрепить атрибут к вызову функции Verilog:
a = add (\* mode = "cla" \*) (b, c);
Пример 8 — Для присоединения атрибута к условному оператору:
a = b ? (\* no_glitch \*) c : d;

3.8.2 Синтаксис

Синтаксис для разрешенных утверждений с атрибутами показан в Синтаксисе 3-4Синтаксисе 3-9. Синтаксис атрибутов объявления модуля приведен в Синтаксисе 3-4.

module_declaration ::= { attribute_instance } module_keyword module_identifier [ module_parameter_port_list ] list_of_ports ; { module_item } endmodule | { attribute_instance } module_keyword module_identifier [ module_parameter_port_list ] [ list_of_port_declarations ] ; { non_port_module_item } endmodule
Синтаксис 3-4 — Синтаксис для атрибутов объявления модуля

Синтаксис атрибутов объявления порта приведен в разделе Синтаксис 3-5.

port_declaration ::= {attribute_instance} inout_declaration | {attribute_instance} input_declaration | {attribute_instance} output_declaration
Синтаксис 3-5 — Синтаксис для атрибутов объявления порта

Синтаксис для атрибутов элементов модуля приведен в Синтаксисе 3-6

module_item ::= port_declaration ; | non_port_module_item module_or_generate_item ::= { attribute_instance } module_or_generate_item_declaration | { attribute_instance } local_parameter_declaration ; | { attribute_instance } parameter_override | { attribute_instance } continuous_assign | { attribute_instance } gate_instantiation | { attribute_instance } udp_instantiation | { attribute_instance } module_instantiation | { attribute_instance } initial_construct | { attribute_instance } always_construct | { attribute_instance } loop_generate_construct | { attribute_instance } conditional_generate_construct non_port_module_item ::= module_or_generate_item | generate_region | specify_block | { attribute_instance } parameter_declaration ;
Синтаксис 3-6-Синтаксис для атрибутов элементов модуля

Синтаксис для атрибутов порта функции, задачи и блока приведен в Синтаксисе 3-7.

function_port_list ::= {attribute_instance} input_declaration { , {attribute_instance } input_declaration} task_item_declaration ::= block_item_declaration | { attribute_instance } input_declaration ; | { attribute_instance } output_declaration ; | { attribute_instance } inout_declaration ; task_port_item ::= { attribute_instance } input_declaration | { attribute_instance } output_declaration | { attribute_instance } inout_declaration block_item_declaration ::= { attribute_instance } reg [ signed ] [ range ] list_of_block_variable_identifiers ; | { attribute_instance } integer list_of_block_variable_identifiers ; | { attribute_instance } time list_of_block_variable_identifiers ; | { attribute_instance } real list_of_block_real_identifiers ; | { attribute_instance } realtime list_of_block_real_identifiers ; | { attribute_instance } event_declaration | { attribute_instance } local_parameter_declaration ; | { attribute_instance } parameter_declaration ;
Синтаксис 3-7 — Синтаксис для атрибутов порта функции, задачи и блока

Синтаксис для атрибутов подключения к порту приведен в Синтаксисе 3-8.

ordered_port_connection ::= (From A.4.1) { attribute_instance } [ expression ] named_port_connection ::= { attribute_instance } . port_identifier ( [ expression ] )
Синтаксис 3-8 — Синтаксис для атрибутов подключения к порту

Синтаксис для атрибутов udp приведен в Синтаксисе 3-9.

udp_declaration ::= { attribute_instance } primitive udp_identifier ( udp_port_list ) ; udp_port_declaration { udp_port_declaration } udp_body endprimitive | { attribute_instance } primitive udp_identifier ( udp_declaration_port_list ) ; udp_body endprimitive udp_output_declaration ::= { attribute_instance } output port_identifier | { attribute_instance } output reg port_identifier [ = constant_expression ] udp_input_declaration ::= { attribute_instance } input list_of_port_identifiers udp_reg_declaration ::= { attribute_instance } reg variable_identifier
Синтаксис 3-9 — Синтаксис для атрибутов udp