DocsTech
/
VERILOG HDL
/

~ cd 12. иерархические имена verilog hdl

12.5 Иерархические имена

Каждый идентификатор в описании Verilog HDL должен иметь уникальное имя иерархического пути. Иерархия модулей и определение элементов, таких как задачи и именованные блоки внутри модулей, должны определять эти имена. Иерархия имен может рассматриваться как древовидная структура, где каждый экземпляр модуля, экземпляр блока генерации(generate), задачи(task), функции(function) или именованный блок begin-end или fork-join определяет новый иерархический уровень, или область видимости, в определенной ветви дерева.

Описание конструкции содержит один или несколько модулей верхнего уровня (см. 12.1.1). Каждый такой модуль образует вершину иерархии имен. Этот корневой (модуля верхнего уровня) или эти параллельные корневые модули составляют одну или несколько иерархий в описании конструкции или описании. Внутри любого модуля каждый экземпляр модуля(module) (включая массив экземпляров), экземпляр блока генерации(generate), объявление задачи(task), объявление функции(function) и именованный блок «begin-end» или «fork-join» определяют новую ветвь иерархии. Именованные блоки внутри именованных блоков, а также внутри задач и функций должны создавать новые ветви.

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

Каждый узел в иерархическом дереве имен должен быть отдельной областью действия по отношению к идентификаторам. Определенный идентификатор может быть объявлен не более одного раза в любой области видимости. См. раздел 12.7 для обсуждения правил области видимости и раздел 4.11 для обсуждения пространств имен.

На любой именованный объект Verilog или иерархическую ссылку на имя можно однозначно ссылаться в полной форме путем конкатенации имен модулей(module), имен экземпляров модулей(module, macromodule), блоков генерации(generate), задач(task), функций(function) или именованных блоков, которые его содержат. Символ точки должен использоваться для разделения каждого имени в иерархии, за исключением экранированных идентификаторов, встроенных в иерархическую ссылку на имя, за которыми следуют разделители, состоящие из пробела и символа точки. Полное имя пути к любому объекту должно начинаться с модуля верхнего уровня (корневого). Это имя пути может быть использовано с любого уровня иерархии или из параллельной иерархии. Имя первого узла в имени пути также может быть вершиной иерархии, которая начинается с уровня, на котором используется путь (что позволяет и дает возможность ссылаться на объекты по нисходящей). Объекты, объявленные в автоматических задачах и функциях, являются исключениями и не могут быть доступны по иерархическим ссылкам имен. Объекты, объявленные в неименованных генерирующих блоках, также являются исключениями. На них можно ссылаться по иерархическим именам только внутри блока и внутри любой иерархии, объявленном экземпляре блока.

За именами в имени иерархического пути, которые ссылаются на массивы экземпляров или циклов блока generate, может сразу следовать константное выражение в квадратных скобках. Это выражение выбирает конкретный экземпляр массива и поэтому называется выбором экземпляра. Выражение должно соответствовать одному из законных значений индекса массива. Если имя массива не является последним элементом пути в иерархическом имени, то выражение instance select является обязательным.

Синтаксис для имен иерархических путей приведен в Синтаксисе 12-6.

...
Копировать
escaped_identifier ::= 
    \ {Any_ASCII_character_except_white_space} white_space
hierarchical_identifier ::=
    { identifier [ [ constant_expression ] ] . } identifier
identifier ::=
    simple_identifier
    | escaped_identifier
simple_identifier ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_$ ] }
white_space ::=
    space | tab | newline | eof
Синтаксис 12-6-Синтаксис для имен иерархических путей

Например:

Пример 1 — Код в этом примере определяет иерархию экземпляров модулей и именованных блоков.
...
Копировать
module mod(in);
    input in;

    always @(posedge in) begin : keep
        reg hold;
        hold = in;
    end
endmodule

module cct(stim1, stim2);
    input stim1, stim2;

    //экземпляр mod
    mod amod(stim1), bmod(stim2);
endmodule

module wave;
    reg stim1, stim2;

    cct a(stim1, stim2); // экземпляр cct

    initial begin :wave1
    #100    fork :innerwave
                reg hold;
            join
    #150    begin
                stim1 = 0;
            end
    end
endmodule

Рисунок 12-1 иллюстрирует иерархию, подразумеваемую в этом коде Verilog.

Глава 12.5 Иерархические имена Рисунок 12-1 Иллюстрирует иерархию примера кода Verilog

Рисунок 12-1 Иерархия в модели

Рисунок 12-2 представляет собой список иерархических форм имен всех объектов, определенных в коде.
...
Копировать
wave
    wave.stim1
    wave.stim2
    wave.a 
        wave.a.stim1 
        wave.a.stim2
        wave.a.amod
            wave.a.amod.in
            wave.a.amod.keep
                wave.a.amod.keep.hold
        wave.a.bmod
            wave.a.bmod.in
            wave.a.bmod.keep
                wave.a.bmod.keep.hold
        wave.wave1
            wave.wave1.innerwave
                wave.wave1.innerwave.hold

Рисунок 12-2 Иерархические имена путей в модели

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

Пример 2 — Следующий пример показывает, как пара именованных блоков может ссылаться на элементы, объявленные друг в друге.
...
Копировать
begin
    fork :mod_1
        reg x;
        mod_2.x = 1;
    join
    fork :mod_2
        reg x;
        mod_1.x = 0;
    join
end

12.6 Ссылка на имя верхней области

Имена модуля или экземпляра модуля достаточно для идентификации модуля и его местоположения в иерархии. Модуль нижнего уровня может ссылаться на элементы модуля, находящегося выше него в иерархии. На переменные могут ссылаться, если известно имя модуля более высокого уровня или имя его экземпляра. Для задач(task), функций(function), именованных блоков и блоков генерации(generate) Verilog должен искать имя в объемлющем модуле, пока оно не будет найдено или пока не будет достигнут корень иерархии(модуля верхнего уровня). Он должен искать имя только в более высоких объемлющих модулях, но не в экземплярах.

Синтаксис для ссылки на верхние области приведен в Синтаксисе 12-7.

...
Копировать
upward_name_reference ::=
    module_identifier.item_name
item_name ::=
    function_identifier
    | block_identifier
    | net_identifier
    | parameter_identifier
    | port_identifier
    | task_identifier
    | variable_identifier
Синтаксис 12-7-Синтаксис для ссылки на имя верхних областей

Возрастающем ссылки на имена также могут быть сделаны с именами вида имяобласти.имяэлемента(scope_name.item_name), где имя области является либо именем экземпляра модуля, либо именем блока generate. Имя такой формы должно быть передаваться следующим образом:

  1. Поиск в текущей области видимости область видимости с именем области. Если она не найдена и текущая область видимости не является областью видимости модуля, ищите имя в верхней области видимости, повторяя при необходимости, пока имя не будет найдено или не будет достигнута область видимости модуля. Если имя все еще не найдено, перейдите к шагу 2). В противном случае эта ссылка на имя должна рассматриваться как нисходящая ссылка из области видимости, в которой найдено имя.
  2. Ищите в самой внешней области видимости родительского модуля области видимости с scope_name видимости. Если он найден, имя элемента будет передаваться из этой области видимости.
  3. Повторите шаг 2), поднимаясь вверх по иерархии.

Существует исключение из этих правил для иерархических имен в левой части объявления defparam. Подробности см. в разделе 12.8.

Например:

В этом примере есть четыре модуля, a, b, c и d. Каждый модуль содержит целое число i. Модулями высшего уровня в этом сегменте иерархии модели являются a и d. Есть две копии модуля b, потому что модули a и d объявляется экземпляр b. Есть четыре копии c.i, потому что каждая из двух копий b объявляется экземпляр c дважды.
...
Копировать
module a;
    integer i;

    b a_b1();

endmodule

module b;
    integer i;

    c b_c1(), b_c2();

    initial             // нисходящий путь ссылается на 2 копии i:
        #10 b_c1.i = 2; // a.a_b1.b_c1.i, d.d_b1.b_c1.i

endmodule

module c;
    integer i;

    initial begin   // локальное имя ссылается на 4 копии i:
        i = 1;      // a.a_b1.b_c1.i, a.a_b1.b_c2.i,
                    // d.d_b1.b_c1.i, d.d_b1.b_c2.i
        b.i = 1;    // Возрастающем пути ссылается на 2 копии i:
                    // a.a_b1.i, d.d_b1.i
    end

endmodule

module d;
    integer i;

    b d_b1();

    initial begin // полное имя пути ссылается на каждую копию i
        a.i = 1; d.i = 5;
        a.a_b1.i = 2; d.d_b1.i = 6;
        a.a_b1.b_c1.i = 3; d.d_b1.b_c1.i = 7;
        a.a_b1.b_c2.i = 4; d.d_b1.b_c2.i = 8;
    end

endmodule

12.7 Правила области

Следующие элементы определяют новую область видимости в Verilog:

Идентификатор должен использоваться для объявления только одного элемента в пределах области видимости. Это правило означает, что объявлять две или более переменных с одинаковым именем, или называть задачу так же, как переменную в том же модуле, или давать экземпляру вентиля то же имя, что и имя сети, подключенной к его выходу, запрещено. Для блоков generate это правило применяется независимо от того, инстанцирован ли блок generate. Исключение сделано для блоков generate в условной конструкции generate. Обсуждение именования условных блоков генерации см. в разделе 12.4.3.

Если на идентификатор ссылаются непосредственно (без иерархического пути) внутри task, function, именованного блока или блока generate, то он должен быть объявлен либо внутри task, function, именованного блока или блока generate локально, либо внутри module, task, function, именованного блока или блока generate, который находится выше в той же ветви дерева имен, которая содержит task, function, именованный блок или блок generate. Если элемент объявлен локально, то используется локальный элемент. Если нет, то поиск продолжается вверх, пока не будет найден элемент с таким именем или пока не будет встречена граница модуля. Если элемент является переменной, то поиск останавливается на границе модуля. Если элемент является task, function, именованным блоком или блоком generate, то поиск продолжается в модулях более высокого уровня до тех пор, пока он не будет найден. Этот факт означает, что task и function могут использовать и изменять переменные внутри содержащего модуля по имени, не проходя через его порты.

Если на идентификатор ссылается иерархическое имя, путь может начинаться с имени модуля, имени экземпляра, задачи(task), функции(function), именованного блока или именованного блока generate. Имена должны искаться сначала на текущем уровне, а затем в модулях более высокого уровня, пока не будут найдены. Поскольку могут использоваться как имена модулей, так и имена экземпляров, приоритет отдается именам экземпляров, если существует модуль с тем же именем, что и имя экземпляра.

Из-за восходящего поиска можно использовать имена путей, которые не находятся строго на нисходящем пути. Например:

Пример 1 — На рисунке 12-3 каждый прямоугольник представляет локальную область поиска. Область видимости, доступная для восходящего поиска, распространяется на все содержащие прямоугольники — с границей модуля A в качестве внешней границы. Таким образом, блок G может напрямую ссылаться на идентификаторы в F, E и A. Он не может напрямую ссылаться на идентификаторы в H, B, C и D.

12.5 Иерархические имена Рисунок 12-3 Области, доступные для ссылки на имя (из примера) Verilog HDL

Рисунок 12-3 Области, доступные для ссылки на имя

Пример 2 — Следующий пример показывает, как к переменным можно обращаться напрямую или с помощью иерархических имен:
...
Копировать
task t;
    reg s;

    begin : b
        reg r;
        t.b.r = 0;// Эти три строки обращаются к одной и той же переменной r
        b.r = 0;
        r = 0;

        t.s = 0;/ Эти две строки обращаются к одной и той же
        s = 0;
    end
endtask

12.8 Элаборация

Элаборация — это процесс, который происходит между разбором и моделированием. Он связывает модули с экземплярами модулей, строит иерархию модели, вычисляет значения параметров, передает иерархические имена, устанавливает сетевые связи и готовит все это к моделированию. С добавлением конструкций generate порядок выполнения этих задач становится важным.

12.8.1 Порядок Элаборации

Из-за конструкций generate иерархия модели может зависеть от значений параметров. Поскольку операторы defparam могут изменять значения параметров практически из любой точки иерархии, результат элаборации может быть неоднозначным, когда задействованы конструкции generate.

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

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

  1. Список начальных точек инициализируется списком модулей верхнего уровня.
  2. Иерархия под каждой начальной точкой расширяется настолько, насколько это возможно без детализации общих конструкций. Все параметры, встречающиеся во время этого расширения, получают свои окончательные значения путем применения начальных значений, переопределения параметров и объявление defparam. Другими словами, любое объявление defparam, цель которого может быть определена в иерархии, элаборации до сих пор, должно иметь свою цель и свое значение. Объявление defparam, цель которых не может быть определена, откладываются до следующей итерации этого шага. Поскольку ни один defparam в иерархии ниже конструкции generate не может ссылаться на параметр вне конструкции generate, возможно, что параметры получат свои окончательные значения до перехода к шагу 2).
  3. Каждая конструкция generate, встреченная на шаге 2), просматривается, и схема generate оценивается. Полученные экземпляры блока generate составляют новый список начальных точек. Если новый список начальных точек не пуст, перейдите к шагу 2).

12.8.2 Раннее передача иерархических имен

Чтобы соответствовать этому алгоритму, иерархические имена в некоторых объявлениях defparam должны быть передача до полной элаборации иерархии. Возможно, что после завершения элаборации правила передачи имен будут диктовать, что иерархическое имя в объявления defparam передавалась бы иначе, если бы не требовалось ранняя передача. Это может привести к ситуации, когда идентичное иерархическое имя в каком-либо другом объявлении в той же области видимости будет передаваться иначе, чем в объявление defparam. Ниже приведен пример конструкции с такой проблемой:
...
Копировать
module m;
    m1 n();
endmodule

module m1;
    parameter p = 2;

    defparam m.n.p = 1;

    initial $display(m.n.p);

    generate
        if (p == 1) begin : m
            m2 n();
        end
    endgenerate
endmodule

module m2;
    parameter p = 3;
endmodule

В этом примере defparam должен быть оценен до того, как будет элаборация условной конструкции generate. На этом этапе элаборации имя передается в parameter p в модуле m1, и этот параметр используется в схеме generate. Результатом действия defparam является присвоение этого параметра в 1. Следовательно, условие generate истинно. После элаборации иерархии под конструкцией generate правила передач иерархического имени диктуют, что имя должно было передаваться в parameter p в модуле m2. На самом деле, идентичное имя в операторе $display будет передаваться на этот другой параметр.

Будет ошибкой, если иерархическое имя в defparam будет начинать передачу до того, как иерархия будет полностью проработана, и это имя будет трактоваться по-другому после того, как модель будет полностью проработана.

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

Главная
Курсы
Вебинары
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. Зашифрованные оболочки
Закрыть