Menu

Module Ports em Verilog: Input, Output e Inout explicados

Como declarar ports de module - input, output e inout - a lista de ports no estilo ANSI e quando uma saída deve ser wire vs reg.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

A interface de um module

A lista de ports de um module é sua interface - tudo que o mundo externo pode ver e tocar. Dentro do module, o corpo calcula saídas a partir de entradas. Os ports são os wires que cruzam o limite.

A declaração moderna no estilo ANSI coloca direção, tipo e largura inline:

module my_module(
    input  wire        clk,
    input  wire        reset,
    input  wire [7:0]  data_in,
    output reg  [7:0]  data_out,
    output wire        valid
);
    // corpo
endmodule

Essa é a forma inteira. Cada port tem:

  • Uma direção: input, output ou inout.
  • Um tipo: wire ou reg (ou logic em SystemVerilog).
  • Uma largura: um range como [7:0], ou um único bit se omitido.
  • Um nome: o identificador que você vai usar dentro do corpo.

As três direções

input - Conduzido de fora

Inputs são sempre wire. O driver está fora do module - ou um sinal de um module de nível superior ou o reg do testbench. Dentro deste module, você pode ler inputs em expressões mas nunca atribuir a eles:

module reader(input wire [7:0] data);
    initial $display("data = %h", data);
endmodule

Escrever data = ... dentro do module seria um erro.

output - Conduzido de dentro

Outputs são conduzidos por algo dentro deste module. Podem ser wire (conduzidos por assign ou por uma saída de submódulo) ou reg (conduzidos a partir de always/initial).

module driver(
    input  wire       a,
    input  wire       b,
    input  wire       clk,
    output wire       y,    // wire - conduzido por assign
    output reg        q     // reg  - conduzido por always
);
    assign y = a & b;       // OK porque y é wire

    always @(posedge clk)
        q <= a;             // OK porque q é reg
endmodule

Tentar atribuir a y dentro do bloco always, ou conduzir q com um assign, seria um erro de compilação. A escolha da palavra-chave precisa combinar com o driver.

inout - Bidirecional

Ports inout são wires que podem ser conduzidos alternadamente pelo module ou pelo que estiver conectado por fora. Aparecem em fronteiras de chip - linhas SDA I²C, pinos GPIO bidirecionais, barramentos de dados compartilhados. Dentro do module, você controla a direção com um padrão tri-state:

module bidir_pin(
    input  wire data_out,
    input  wire output_enable,
    output wire data_in,
    inout  wire pin
);
    assign pin     = output_enable ? data_out : 1'bz;
    assign data_in = pin;
endmodule

pin é o wire compartilhado. Quando output_enable é alto, o module aciona pin para data_out. Quando baixo, ele libera o pino para alta impedância (z), deixando um driver externo usá-lo. data_in sempre observa o que está atualmente no pino.

inout é raro em lógica puramente interna. Se você está construindo um controlador de memória, um núcleo de CPU, um pipeline de processamento de imagem, talvez nunca precise dele. É um recurso para o anel de I/O nos limites do chip.

Ports de bit único vs multi-bit

O range de largura é opcional - omita-o para um port de bit único:

input wire valid,         // 1 bit
input wire [7:0] data,    // 8 bits
input wire [31:0] addr,   // 32 bits

Você pode usar parameters para larguras, que é como modules parametrizados funcionam:

module bus #(
    parameter WIDTH = 32
)(
    input  wire [WIDTH-1:0] in,
    output wire [WIDTH-1:0] out
);
    assign out = in;
endmodule

Estilos ANSI vs Verilog-1995

Você vai ver ocasionalmente código antigo que divide a lista de ports e as declarações:

// Estilo antigo Verilog-1995 - NÃO faça isso em código novo
module foo(clk, data_in, data_out);
    input clk;
    input [7:0] data_in;
    output reg [7:0] data_out;
    // ...
endmodule

A lista de ports contém apenas nomes; cada port é então declarado separadamente dentro do corpo. É verboso, propenso a erros do tipo "nomeado na lista de ports mas nunca declarado" e o dobro do que digitar. O estilo ANSI-2001 (o mostrado em todos estes docs) substitui ambos:

module foo(
    input  wire       clk,
    input  wire [7:0] data_in,
    output reg  [7:0] data_out
);
    // ...
endmodule

Use o estilo ANSI. Ferramentas o suportam desde 2001.

Um exemplo completo

Esse module único tem:

  • Um parameter (WIDTH).
  • Inputs para clock, reset, load enable, data e shift enable.
  • Uma saída reg (data_out) conduzida dentro de um bloco always.
  • Uma saída wire (msb_out) conduzida por uma continuous assignment.
  • Uma declaração ANSI completa que lista direção, tipo e largura de cada port inline.

É assim que quase todo module sintetizável que você vai escrever é moldado.

O que vem a seguir

O próximo doc - Module Instantiation - mostra como pegar este module e usá-lo dentro de um design maior. O shifter que você acabou de escrever não é útil sozinho; ele ganha o pão quando algo o instancia e o conecta a um sistema.

Perguntas frequentes

Quais são as três direções de port em Verilog?

input, output e inout. input é conduzido de fora do module. output é conduzido de dentro do module. inout é bidirecional - útil para barramentos tri-state onde o module ao mesmo tempo aciona e lê o mesmo pino. A grande maioria de ports internos é input ou output; inout só aparece em pinos de chip.

Qual a diferença entre output wire e output reg?

output wire significa que a saída é conduzida por uma continuous assignment ou pela saída de um submódulo - tudo fora de um bloco always. output reg significa que é conduzida de dentro de um bloco procedural (initial ou always). A palavra-chave controla se você pode mirar o sinal de dentro de um always, não se o hardware sintetizado contém um flip-flop.

Qual é o estilo ANSI para ports em Verilog?

O estilo ANSI declara direção e tipo de cada port inline na lista de ports: module foo(input wire [7:0] data, output reg [7:0] result);. O estilo Verilog-1995 mais antigo só listava nomes na lista de ports e os redeclarava dentro do module. Use sempre o estilo ANSI em código novo - é mais curto, menos sujeito a erros e padrão em qualquer lugar moderno.

Posso ter múltiplos inputs e outputs em um module Verilog?

Sim - um module pode ter quantos ports você precisar, em qualquer combinação de direções. Separe-os com vírgulas na lista de ports. A ordem na lista de ports determina a ordem de conexão posicional na instanciação, mas você quase sempre usa conexões nomeadas (.port(signal)) para evitar depender da ordem.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR