12. Порты. Иерархические имена в Verilog HDL

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

12.3 Порты

Порты обеспечивают средства взаимосвязи между описанием аппаратного обеспечения, состоящего из модулей и примитивов. Например, модуль A может объявляет экземпляр модуля B, используя соединения портов, соответствующие модулю A. Эти имена портов могут отличаться от имен внутренних сетей и переменных, указанных в определении модуля B.

12.3.1 Объявление порта

Синтаксис для портов и списка портов приведен в Синтаксис 12-3.

list_of_ports ::= ( port { , port } ) list_of_port_declarations ::= ( port_declaration { , port_declaration } ) | ( ) port ::= [ port_expression ] | . port_identifier ( [ port_expression ] ) port_expression ::= port_reference | { port_reference { , port_reference } } port_reference ::= port_identifier [ [ constant_range_expression ] ] port_declaration ::= {attribute_instance} inout_declaration | {attribute_instance} input_declaration | {attribute_instance} output_declaration
Синтаксис 12-3-Синтаксис для порта

12.3.2 Список портов

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

  • Простой или расширенный идентификатор
  • Битовая выборка вектора, объявленного в модуле
  • Частичная выборка вектора, объявленного в модуле
  • Конкатенация любого из вышеперечисленных вариантов

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

Первый тип порта модуля, имеющий только выражение port_expression, является неявным портом. Второй тип — это явный порт. В нем явно указывается идентификатор port_identifier, используемый для соединения портов экземпляра модуля по имени (см. 12.3.6), и выражение port_expression, содержащее идентификаторы, объявленные внутри модуля, как описано в 12.3.3. Именованные соединения портов не должны использоваться для неявных портов, если только выражение port_expression не является простым идентификатором или экранированным идентификатором, который должен использоваться в качестве имени порта.

12.3.3 Декларации портов

Каждый port_identifier в выражении port_expression в списке портов для объявления модуля должен быть также объявлен в теле модуля как одно из следующих объявлений порта: input, output или inout. Это дополнение к любому другому объявлению типа данных для конкретного порта — например, reg или wire. Синтаксис объявления порта приведен в Синтаксисе 12-4.

inout_declaration ::= inout [ net_type ] [ signed ] [ range ] list_of_port_identifiers input_declaration ::= input [ net_type ] [ signed ] [ range ] list_of_port_identifiers output_declaration ::= output [ net_type ] [ signed ] [ range ] list_of_port_identifiers | output reg [ signed ] [ range ] list_of_variable_port_identifiers | output output_variable_type list_of_variable_port_identifiers list_of_port_identifiers ::= port_identifier { , port_identifier }
Синтаксис 12-4 — Синтаксис объявления портов

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

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

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

Например:
input aport; // Первая декларация input aport; // Ошибка - множественное объявление, объявление порта output aport; // Ошибка - множественное объявление, объявление порта

Атрибут signed может быть прикреплен либо к объявлению порта, либо к соответствующему объявлению сети или reg, либо к обоим. Если либо порт, либо wire/reg объявлены как знаковым, то и другой порт будет считаться знаковым.

Неявные сети считаются беззнаковыми. Сети, подключенные к портам без явного объявления сети, считаются беззнаковыми, если только порт не объявлен как знаковым.

Например:
module test(a,b,c,d,e,f,g,h); input [7:0] a; // явного объявления нет - сеть беззнаковая input [7:0] b; input signed [7:0] c; input signed [7:0] d; // без явного объявления сети - сеть знаковая output [7:0] e; // без явного объявления - сеть беззнаковая output [7:0] f; output signed [7:0] g; output signed [7:0] h; // явного объявления сети нет - сеть знаковая wire signed [7:0] b; // порт b наследует атрибут signed от net decl. wire [7:0] c; // сеть c наследует signed атрибут от порта reg signed [7:0] f; // порт f наследует атрибут signed от reg decl. reg [7:0] g; // reg g наследует signed атрибут от порта endmodule module complex_ports ({c,d}, .e(f)); // Сетки {c,d} получают первые биты порта. // Имя 'f' объявлено внутри модуля. // Имя 'e' определено вне модуля. // Невозможно использовать соединения именованного порта первого порта. module split_ports (a[7:4], a[3:0]); // Первый порт - верхние 4 бита 'a'. // Второй порт - младшие 4 бита 'a'. // Невозможно использовать соединения с именованным портом, потому что // порта part-select 'a'. module same_port (.a(i), .b(i)); // Имя 'i' объявлено внутри модуля как порт inout. // Имена 'a' и 'b' определены для портовых соединений. module renamed_concat (.a({b,c}), f, .g(h[1])); // Имена 'b', 'c', 'f', 'h' определены внутри модуля. // Имена 'a', 'f', 'g' определены для портовых соединений. // Можно использовать соединения с именованными портами. module same_input (a,a); input a; // Это правильно. Входы связаны вместе. module mixed_direction (.p({a, e})); input a; // p содержит как входные, так и выходные направления output e;

12.3.4 Список деклараций портов

Для указания портов модуля может быть использован альтернативный синтаксис, минимизирующий дублирование данных. Каждый модуль должен быть объявлен либо полностью с использованием синтаксиса списка портов, как описано в п. 12.3.2, либо полностью с использованием list_of_port_declarations, как описано в данном подпункте.

Каждый объявленный порт предоставляет полную информацию о нем. Полностью описывается направление, ширинe, сеть или тип переменной порта, а также то, является ли порт знаковым или беззнаковым. Для объявлений ввода, вывода и двунаправленного в заголовке модуля используется тот же синтаксис, что и для объявления стиля списка портов, за исключением того, что list_of_port_declarations включается в заголовок модуля, а не отдельно (после символа ;, завершающего заголовок модуля).

Например:

В качестве примера, модуль с именем test, приведенный в предыдущем примере, может быть альтернативно объявлен следующим образом:
module test ( input [7:0] a, input signed [7:0] b, c, d, // // Несколько портов, которые совместно используют все // атрибуты могут быть объявлены вместе. output [7:0] e, // Каждый атрибут декларации // должны быть в одном объявлении. output reg signed [7:0] f, g, output signed [7:0] h) ; // Незаконно повторно объявлять любые порты из // модуль в теле модуля. endmodule

Объявление портов в модуле типа port_reference не должно выполняться с использованием стиля объявлений модулей list_of_port_declarations. Также порты, объявленные с использованием list_of_port_declarations, должны быть только простыми идентификаторами или экранированными идентификаторами. Они не должны быть битовыми, частичными или конкатенациями (как в примере complex_ports). Порты не могут быть разделены (как в примере split_ports). Они также не могут быть именованными портами (как в примере same_port).

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

12.3.5 Подключение портов экземпляра модуля по упорядоченному списку

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

Например:

Следующий пример иллюстрирует модуль верхнего уровня (topmod), который инстанцирует второй модуль (modB). Модуль modB имеет порты, которые соединены упорядоченным списком. Соединения выполняются следующим образом:

  • Порт wa в определении modB подключается к битовой выборке v[0] в модуле topmod.
  • Порт wb подключается к v[3].
  • Порт c подключается к w.
  • Порт d подключается к v[4].
В определении modB порты wa и wb объявлены как inout(двунаправленные), а порты c и d — как input(входной).
module topmod; wire [4:0] v; wire a,b,c,w; modB b1 (v[0], v[3], w, v[4]); endmodule module modB (wa, wb, c, d); inout wa, wb; input c, d; tranif1 g1 (wa, wb, cinvert); not #(2, 6) n1 (cinvert, int); and #(6, 5) g2 (int, c, d); endmodule

Во время моделирования экземпляра b1 modb сначала активируется вентиль and и g2 для получения значения на int. Это значение запускает вентиль not n1 для получения выхода на cinvert, который затем активирует вентиль tranif1 g1.

12.3.6 Подключение портов экземпляра модуля по имени

Второй способ соединения портов модулей заключается в явном связывании двух имен для каждой стороны соединения. Имя объявления порта из объявления модуля в выражение. Т.е. имя, используемое в объявлении модуля, за которым следует имя, используемое в экземпляре модуля. Это составное имя затем помещается в список соединений модуля. Имя порта должно быть именем, указанным в объявлении модуля. Имя порта не может быть битовой выборкой, частичной выборкой или конкатенацией портов. Если объявление порта модуля было неявным, то выражение port_expression должно быть простым или экранированным идентификатором, который будет использоваться в качестве имени порта. Если объявление порта в модуле было явным, то в качестве имени порта используется явное имя.

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

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

Например:

Пример 1 — В следующем примере экземпляре модуля подключает свои сигналы topA и topB к портам In1 и Out, определенным модулем ALPHA. По крайней мере один порт, предоставляемый ALPHA, не используется. Он назван In2. Могут существовать и другие неиспользуемые порты, не упомянутые в экземпляре.
ALPHA instance1 (.Out(topB),.In1(topA),.In2());
Пример 2 — В этом примере определяются модули modB и topmod, а затем topmod объявляется экземпляр modB, используя порты, соединенные по имени.
module topmod; wire [4:0] v; wire a,b,c,w; modB b1 (.wb(v[3]),.wa(v[0]),.d(v[4]),.c(w)); endmodule module modB(wa, wb, c, d); inout wa, wb; input c, d; tranif1 g1(wa, wb, cinvert); not #(6, 2) n1(cinvert, int); and #(5, 6) g2(int, c, d); endmodule

Поскольку эти соединения выполняются по имени, порядок их появления не имеет значения. Соединения портов нескольких экземпляров модуля не допускаются, например, следующий пример является незаконным:

Пример 3 — В этом примере показаны незаконные соединения портов.
module test; a ia (.i (a), .i (b), // незаконное подключение входного порта дважды. .o (c), .o (d), // незаконное подключение входного порта дважды. .e (e), .e (f)); // незаконное подключение двунаправленного порта дважды. endmodule

12.3.7 Вещественные числа в портовых соединениях

real тип данных не должен быть напрямую подключен к порту. Он должен быть подключен косвенно, как показано в следующем примере. Для передачи битовых шаблонов через порты модуля должны использоваться системные функции $realtobits и $bitstoreal. (Описание этих системных задач см. в разделе 17.8).

Например:
module driver (net_r); output net_r; real r; wire [64:1] net_r = $realtobits(r); endmodule module receiver (net_r); input net_r; wire [64:1] net_r; real r; initial assign r = $bitstoreal(net_r); endmodule

12.3.8 Подключение разнородных портов

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

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

Порт, который объявлен как вход (output), но используется как выход (input) или inout, может быть принудительно переведен в inout. Если он не принудительно приведен к inout, должно быть выдано предупреждение.

12.3.9 Правила подключения к порту

Правила 12.3.9.112.3.9.3 должны определять способ объявления портов модуля и способ их соединения.

12.3.9.1 Правило 1

Входной или выходной порт должен иметь тип net.

12.3.9.2 Правило 2

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

Выражение структурной сети — это выражение порта, операнды которого могут быть следующими:

  • Скалярная сеть
  • Векторная сеть
  • Константная битовая выборка векторной сети
  • Частичная выборка векторной сети
  • Конкатенация выражений структурной сети

Следующие внешние элементы не должны подключаться к выходным или входным портам модулей:

  • Переменные
  • Выражения, отличные от следующих:
  • Скалярная сеть
  • Векторная сеть
  • Константная битовая выборка векторной сети
  • Частичная выборка векторной сети
  • Конкатенация выражений, перечисленных выше

12.3.9.3 Правило 3

Если сеть по обе стороны от порта имеет тип сети uwire, выдается предупреждение, если сети не объединены в одну сеть, как описано в п. 12.3.10.

12.3.10 Типы сетей, возникающие в результате разнородных соединений портов

Когда через порт модуля соединяются сети разных типов, сети с обеих сторон порта могут принимать один и тот же тип. Результирующий тип сети может быть определен, как показано в таблице 12-1. В таблице внешняя сеть означает сеть, объявленную в экземпляре модуля, а внутренняя сеть означает сеть, объявленную в модуле определение. Сеть, тип которой используется, называется доминирующей сетью. Сеть, тип которой изменяется, называется доминированной сетью. Допускается объединение доминирующей и доминированной сетей в одну сеть. Тип которой должен быть типом доминирующей сети. Полученная сеть называется моделируемой сетью, а недоминированная сеть называется свернутой сетью.

Моделируемая сеть должна принять задержку, указанную для доминирующей сети. Если доминирующая сеть имеет тип trireg, любое значение прочности, заданное для сети trireg, будет применяться к моделируемой сети.

Таблица 12-1-Типы сетей, возникающие в результате разнородных соединений портов
Internal net/ External netwire, triwand, triandwor, triortriregtri0tri1uwiresupply0supply1
wire, triextextextextextextextextext
wand, triandintextext warnext warnext warnext warnext warnextext
wor, triorintext warnextext warnext warnext warnext warnextext
triregintext warnext warnextextextext warnextext
tri0intext warnext warnintextext warnext warnextext
tri1intext warnext warnintext warnextext warnextext
uwireintint warnint warnint warnint warnint warnextextext
supply0intintintintintintintextext warn
supply1intintintintintintintext warnext

КЛЮЧ:

ext = Используется тип внешней сети.

int = Используется тип внутренней сети.

warn = Выдается предупреждение.

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

12.3.10.1 Правило разрешения типа сети

Когда две сети, соединенные портом, имеют разный тип сети, результирующей единой сети может быть присвоен один из следующих типов:

  • Тип доминирующей сети, если одна из двух сетей является доминирующей, или
  • Тип сети, внешний по отношению к модулю

Если доминирующий тип сети не существует, используется внешний тип сети.

12.3.10.2 Таблица типов сетей

В таблице 12-1 показан тип сети, диктуемый правилом разрешения типа сети.

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

12.3.11 Подключение знаковых значений через порты

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