Módulo Verilog
Um
module
é um bloco de código Verilog que implementa uma determinada funcionalidade. Os módulos podem ser incorporados a outros módulos e um módulo de nível superior pode se comunicar com seus módulos de nível inferior usando suas portas de entrada e saída. Sintaxe
Um módulo deve estar entre
module
e endmodule
palavras-chave. O nome do módulo deve ser dado logo após o module
palavra-chave e uma lista opcional de portas também podem ser declaradas. Observe que as portas declaradas na lista de declarações de portas não podem ser redeclaradas no corpo do módulo.
module <name> ([port_list]);
// Contents of the module
endmodule
// A module can have an empty portlist
module name;
// Contents of the module
endmodule
Todas as declarações de variáveis, instruções de fluxo de dados, funções ou tarefas e instâncias de módulos inferiores, se houver, devem ser definidas dentro do
module
e endmodule
palavras-chave. Pode haver vários módulos com nomes diferentes no mesmo arquivo e podem ser definidos em qualquer ordem. Exemplo
O módulo dff representa um flip-flop D que possui três portas de entrada d, clk, rstn e uma porta de saída q. O conteúdo do módulo descreve como um flip-flop D deve se comportar para diferentes combinações de entradas. Aqui, a entrada d é sempre atribuída à saída q na borda positiva do clock se rstn for alto porque é um reset ativo baixo.
// 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
Esquema de hardware
Este módulo será convertido no seguinte circuito digital durante a síntese.
Observe que você não pode ter nenhum código escrito fora de um módulo!
Qual é a finalidade de um módulo?
Um módulo representa uma unidade de projeto que implementa certas características comportamentais e será convertida em um circuito digital durante a síntese. Qualquer combinação de entradas pode ser fornecida ao módulo e fornecerá uma saída correspondente. Isso permite que o mesmo módulo para ser reutilizado para formar módulos maiores que implementam hardware mais complexo.
Por exemplo, o DFF mostrado acima pode ser encadeado para formar um registrador de deslocamento.
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
Esquema de hardware
Observe que as instâncias dff são conectadas com fios conforme descrito pelo módulo Verilog RTL.
Em vez de construir blocos menores para formar blocos de design maiores, o inverso também pode ser feito. Considere a divisão de um mecanismo de GPU simples em componentes menores, de modo que cada um possa ser representado como um módulo que implementa um recurso específico. O mecanismo de GPU mostrado abaixo pode ser dividido em cinco sub-blocos diferentes, onde cada um executa uma funcionalidade específica. A unidade de interface de barramento obtém dados de fora para o projeto, que são processados por outra unidade para extrair instruções. Outras unidades na linha processam dados fornecidos pela unidade anterior.
Cada sub-bloco pode ser representado como um
module
com um determinado conjunto de sinais de entrada e saída para comunicação com outros módulos e cada sub-bloco pode ser dividido em blocos mais finos conforme necessário. O que são módulos de nível superior?
Um nível superior módulo é aquele que contém todos os outros módulos. Um módulo de nível superior não é instanciado em nenhum outro módulo.
Por exemplo, os módulos de design são normalmente instanciados em módulos testbench de nível superior para que a simulação possa ser executada fornecendo estímulo de entrada. Mas, o testbench não é instanciado em nenhum outro módulo porque é um bloco que encapsula todo o resto e, portanto, é o módulo de nível superior .
Nível superior de design
O código de design mostrado abaixo possui um módulo de nível superior chamado design. Isso ocorre porque ele contém todos os outros submódulos necessários para completar o projeto. Os submódulos podem ter mais submódulos aninhados como mod3 dentro de mod1 e mod4 dentro de mod2. De qualquer forma, tudo isso é incluído no módulo de nível superior quando mod1 e mod2 são instanciados. Isso torna o design completo e é o módulo de nível superior para o design.
//---------------------------------
// 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
Nível superior da bancada de teste
O módulo testbench contém estímulos para verificar a funcionalidade do projeto e é usado principalmente para verificação funcional usando ferramentas de simulação. Portanto, o projeto é instanciado e chamado de d0 dentro do módulo testbench. Do ponto de vista do simulador, o testbench é o módulo de nível superior.
//-----------------------------------------------------------
// 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
Nomes hierárquicos
Uma estrutura hierárquica é formada quando os módulos podem ser instanciados um dentro do outro e, portanto, o módulo de nível superior é chamado de raiz . Uma vez que cada instância de módulo inferior dentro de um determinado módulo deve ter nomes de identificadores diferentes, não haverá ambiguidade no acesso aos sinais. Um nome hierárquico é construído por uma lista desses identificadores separados por pontos
.
para cada nível da hierarquia. Qualquer sinal pode ser acessado dentro de qualquer módulo usando o caminho hierárquico para aquele sinal específico.
// 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