Верилог-модуль
А module
представляет собой блок кода Verilog, реализующий определенную функциональность. Модули могут быть встроены в другие модули, и модуль более высокого уровня может взаимодействовать со своими модулями более низкого уровня, используя их входные и выходные порты.
Синтаксис
модуль должен быть заключен в module
и endmodule
ключевые слова. Имя модуля должно быть указано сразу после module
ключевое слово, а также необязательный список портов. Обратите внимание, что порты, объявленные в списке объявлений портов, не могут быть повторно объявлены в теле модуля.
module <name> ([port_list]);
// Contents of the module
endmodule
// A module can have an empty portlist
module name;
// Contents of the module
endmodule
Все объявления переменных, операторы потока данных, функции или задачи и экземпляры нижних модулей, если таковые имеются, должны быть определены в module
и endmodule
ключевые слова. В одном файле может быть несколько модулей с разными именами, и они могут быть определены в любом порядке.
Пример
Модуль dff представляет собой D-триггер с тремя входными портами d, clk, rstn и одним выходным портом q. Содержимое модуля описывает, как должен вести себя D-триггер для различных комбинаций входных сигналов. Здесь вход d всегда назначается выходу q при положительном фронте тактового сигнала, если rstn высокий, потому что это активный низкий сброс.
// Module called "dff" has 3 inputs and 1 output port
module dff ( input d,
input clk,
input rstn,
output reg q);
// Contents of the module
always @ (posedge clk) begin
if (!rstn)
q <= 0;
else
q <= d;
end
endmodule
Схема оборудования
Этот модуль будет преобразован в следующую цифровую схему во время синтеза.
Обратите внимание, что вы не можете писать код вне модуля!
Какова цель модуля?
Модуль представляет собой конструкторскую единицу, которая реализует определенные поведенческие характеристики и при синтезе преобразуется в цифровую схему. Любая комбинация входов может быть дана модулю, и он обеспечит соответствующий выход. Это позволяет тому же модулю для повторного использования для формирования более крупных модулей, реализующих более сложное оборудование.
Например, DFF, показанный выше, может быть объединен в сдвиговый регистр.
module shift_reg ( input d,
input clk,
input rstn,
output q);
wire [2:0] q_net;
dff u0 (.d(d), .clk(clk), .rstn(rstn), .q(q_net[0]));
dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q(q_net[1]));
dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q(q_net[2]));
dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
endmodule
Схема оборудования
Обратите внимание, что экземпляры dff соединены проводами, как описано в модуле Verilog RTL.
Вместо того, чтобы создавать из более мелких блоков более крупные блоки дизайна, можно сделать и обратное. Рассмотрим разбиение простого движка графического процессора на более мелкие компоненты, каждый из которых может быть представлен в виде модуля, реализующего определенную функцию. Показанный ниже движок графического процессора можно разделить на пять различных подблоков, каждый из которых выполняет определенную функцию. Блок интерфейса шины получает данные извне в проект, которые обрабатываются другим блоком для извлечения инструкций. Другие подразделения обрабатывают данные, предоставленные предыдущим подразделением.
Каждый подблок может быть представлен как module
с определенным набором входных и выходных сигналов для связи с другими модулями, и каждый подблок может быть дополнительно разделен на более мелкие блоки по мере необходимости.
Что такое модули верхнего уровня?
высший уровень модуль содержит все остальные модули. Модуль верхнего уровня не создается ни в каком другом модуле.
Например, модули проектирования обычно создаются в модулях тестового стенда верхнего уровня, чтобы можно было запускать моделирование, предоставляя входные стимулы. Но тестовый стенд не создается ни в каком другом модуле, потому что это блок, который инкапсулирует все остальное и, следовательно, является модулем верхнего уровня. .
Дизайн верхнего уровня
Код дизайна, показанный ниже, имеет модуль верхнего уровня, называемый дизайном. Это связано с тем, что он содержит все остальные подмодули, необходимые для завершения проекта. Подмодули могут иметь больше вложенных подмодулей, таких как mod3 внутри mod1 и mod4 внутри mod2. В любом случае, все они включаются в модуль верхнего уровня при создании экземпляров mod1 и mod2. Это делает дизайн завершен и является модулем верхнего уровня для дизайна.
//---------------------------------
// Design code
//---------------------------------
module mod3 ( [port_list] );
reg c;
// Design code
endmodule
module mod4 ( [port_list] );
wire a;
// Design code
endmodule
module mod1 ( [port_list] ); // This module called "mod1" contains two instances
wire y;
mod3 mod_inst1 ( ... ); // First instance is of module called "mod3" with name "mod_inst1"
mod3 mod_inst2 ( ... ); // Second instance is also of module "mod3" with name "mod_inst2"
endmodule
module mod2 ( [port_list] ); // This module called "mod2" contains two instances
mod4 mod_inst1 ( ... ); // First instance is of module called "mod4" with name "mod_inst1"
mod4 mod_inst2 ( ... ); // Second instance is also of module "mod4" with name "mod_inst2"
endmodule
// Top-level module
module design ( [port_list]); // From design perspective, this is the top-level module
wire _net;
mod1 mod_inst1 ( ... ); // since it contains all other modules and sub-modules
mod2 mod_inst2 ( ... );
endmodule
Верхний уровень тестового стенда
Модуль тестового стенда содержит стимул для проверки функциональности проекта и в основном используется для функциональной проверки с использованием инструментов моделирования. Следовательно, проект создается и вызывается d0 внутри модуля тестового стенда. С точки зрения симулятора testbench является модулем верхнего уровня.
//-----------------------------------------------------------
// Testbench code
// From simulation perspective, this is the top-level module
// because 'design' is instantiated within this module
//-----------------------------------------------------------
module testbench;
design d0 ( [port_list_connections] );
// Rest of the testbench code
endmodule
Иерархические имена
Иерархическая структура формируется, когда модули могут быть реализованы внутри друг друга, поэтому модуль верхнего уровня называется корневым. . Поскольку каждая реализация нижнего модуля в данном модуле должна иметь разные имена идентификаторов, при доступе к сигналам не будет никакой двусмысленности. Иерархическое имя строится из списка этих идентификаторов, разделенных точками .
. для каждого уровня иерархии. К любому сигналу можно получить доступ в любом модуле, используя иерархический путь к этому конкретному сигналу.
// Take the example shown above in top level modules
design.mod_inst1 // Access to module instance mod_inst1
design.mod_inst1.y // Access signal "y" inside mod_inst1
design.mod_inst2.mod_inst2.a // Access signal "a" within mod4 module
testbench.d0._net; // Top level signal _net within design module accessed from testbench
Verilog