Constantes com uma reviravolta
Um parameter é uma constante - o compilador escolhe seu valor e o assa no design antes da simulação começar. A reviravolta é que quem instancia o module pode mudar o valor. O mesmo arquivo fonte de module pode produzir circuitos de tamanhos diferentes dependendo de como chamadores o parametrizam.
É assim que você constrói IP reutilizável. Um module FIFO com parameters WIDTH e DEPTH pode servir cada equipe em uma empresa. Um contador com um parameter WIDTH é o mesmo fonte quer ele conte até 16 ou 4 bilhões.
Declaração básica de parameter
Três pedaços de sintaxe nova:
- Bloco de parameter:
#( parameter WIDTH = 8 )entre o nome do module e a lista de ports. O valor padrão8é o que o module usa quando ninguém sobrescreve. - Local de uso:
output reg [WIDTH-1:0] count. O parameter é só uma constante - nós o plugamos no range de bits. Mesmo fonte de module produz uma saída de 8 bits ou de 16 bits dependendo deWIDTH. - Sintaxe de sobrescrita:
counter #(.WIDTH(16)) dut16(...)no momento da instanciação. O bloco#(...)vai antes do nome da instância, depois do nome do module. Quaisquer parameters que você não mencionar mantêm seus padrões.
localparam: Constantes internas
Há constantes que você não quer que chamadores sobrescrevam. Codificações de estado são o caso clássico:
localparam torna IDLE, RUNNING, DONE disponíveis dentro do module mas não sobrescritíveis a partir da instanciação. Essa é a escolha certa - mudar o que o valor IDLE significa de fora do module seria aterrorizante.
Use parameter para coisas que chamadores devem configurar (larguras, profundidades, opções de comportamento) e localparam para todo o resto. Um padrão comum é derivar localparams de parameters:
parameter WIDTH = 32;
localparam WIDTH_M1 = WIDTH - 1; // calculado uma vez; não sobrescritível
Larguras parametrizadas na prática
O uso mais comum de parameters é tornar larguras de barramento flexíveis. Aqui está um somador que funciona em qualquer largura:
Um arquivo fonte, duas instâncias, duas larguras diferentes, sem copy-paste. Essa é a recompensa inteira dos parameters.
Múltiplos parameters, sobrescrita nomeada
Para modules maiores você frequentemente terá vários parameters. Sobrescreva-os por nome em qualquer ordem:
module fifo #(
parameter WIDTH = 8,
parameter DEPTH = 16,
parameter AFULL = DEPTH - 2
)(
input wire clk,
input wire reset,
// ... ports ...
);
// ...
endmodule
// No local de chamada:
fifo #(.WIDTH(32), .DEPTH(1024)) cmd_queue (.clk(clk), .reset(reset), ...);
Você não precisa sobrescrever cada parameter; os não mencionados mantêm seus padrões. O padrão AFULL no exemplo é calculado a partir de DEPTH, o que significa que se você sobrescrever DEPTH, AFULL segue automaticamente - exatamente o tipo de dependência que localparam também lidaria se você não quisesse que chamadores conseguissem sobrescrever AFULL independentemente.
Erros comuns
Esquecer o # na sobrescrita. counter (.WIDTH(16)) dut(...) parece uma sobrescrita mas Verilog lê (.WIDTH(16)) como uma conexão de port. Você precisa de counter #(.WIDTH(16)) dut(...).
Usar parameters onde eles não são constantes o suficiente. Parameters resolvem em tempo de elaboração, antes que qualquer sinal exista. Você não pode parametrizar com base em um sinal de runtime - se o valor depende do que uma entrada está fazendo no tempo de simulação, não é um parameter, é lógica.
Confundir parameter e localparam em listas de port. Apenas parameter vai no bloco #(...) no topo. localparam vive dentro do corpo. O compilador vai te avisar se você trocar.
O que vem a seguir
Você agora consegue fazer modules cujo tamanho é definido em tempo de compilação. Os próximos dois docs cobrem as regras para escrever constantes literais (8'h1F, 4'b1010, 32'd100) e os valores x e z que aparecem quando sinais não são conduzidos ou estão em contenção. Depois disso passamos a operadores - tudo que você consegue fazer com os vetores e parameters que agora viu.
Perguntas frequentes
O que é um parameter em Verilog?
Um parameter é uma constante em tempo de compilação declarada dentro de um module. Pode ser usado em qualquer lugar onde uma constante é permitida - larguras de barramento, profundidades de memória, codificações de estado, valores padrão. Crucialmente, cada instância do module pode sobrescrever o parameter, então o mesmo arquivo fonte pode produzir, digamos, um contador de 8 bits em um lugar e um contador de 32 bits em outro.
Qual a diferença entre parameter e localparam em Verilog?
Valores parameter podem ser sobrescritos de fora do module quando ele é instanciado. Valores localparam não podem - são constantes internas apenas. Use localparam para codificações de estado e constantes derivadas que o autor do module não quer que chamadores bagunçem.
Como sobrescrevo um parameter em Verilog?
Quando você instancia o module, adicione um bloco de override de parameter antes do nome da instância: counter #(.WIDTH(16)) my_inst (.clk(clk), .count(count));. A sintaxe .WIDTH(16) define esse parameter específico; quaisquer parameters que você não listar mantêm seus padrões. Múltiplas sobrescritas são separadas por vírgulas dentro do #(...).
O que é um module parametrizado?
Um module que expõe um ou mais parameters que chamadores podem sobrescrever. Um FIFO parametrizado pode ter parameters WIDTH e DEPTH para que o mesmo fonte produza um FIFO de 32 bits por 16 fundo em um lugar e um FIFO de 8 bits por 1024 fundo em outro. É assim que bibliotecas de blocos de IP reutilizáveis são escritas.