Parâmetros Verilog
Os parâmetros são construções Verilog que permitem que um módulo seja reutilizado com uma especificação diferente. Por exemplo, um somador de 4 bits pode ser parametrizado para aceitar um valor para o número de bits e novos valores de parâmetro podem ser passados durante a instanciação do módulo. Assim, um somador de N bits pode se tornar um somador de 4 bits, 8 bits ou 16 bits. Eles são como argumentos para uma função que são passados durante uma chamada de função.
parameter MSB = 7; // MSB is a parameter with a constant value 7
parameter REAL = 4.5; // REAL holds a real number
parameter FIFO_DEPTH = 256,
MAX_WIDTH = 32; // Declares two parameters
parameter [7:0] f_const = 2'b3; // 2 bit value is converted to 8 bits; 8'b3
Os parâmetros são basicamente constantes e, portanto, é ilegal modificar seu valor em tempo de execução. É ilegal redeclarar um nome que já é usado por uma rede, variável ou outro parâmetro.
Existem dois tipos principais de parâmetros, module e especifique e ambos aceitam uma especificação de intervalo. Mas, eles são normalmente feitos tão largos quanto o valor a ser armazenado exige que eles sejam e, portanto, uma especificação de intervalo não é necessária.
Parâmetros do módulo
Os parâmetros do módulo podem ser usados para substituir as definições de parâmetros dentro de um módulo e isso faz com que o módulo tenha um conjunto diferente de parâmetros em tempo de compilação. Um parâmetro pode ser modificado com o
defparam
instrução ou na instrução de instância do módulo. É uma prática comum usar letras maiúsculas em nomes para o parâmetro para torná-los instantaneamente perceptíveis. O módulo mostrado abaixo usa parâmetros para especificar a largura do barramento, a largura dos dados e a profundidade do FIFO dentro do projeto e pode ser substituído por novos valores quando o módulo é instanciado ou usando
defparam
declarações.
// Verilog 1995 style port declaration
module design_ip ( addr,
wdata,
write,
sel,
rdata);
parameter BUS_WIDTH = 32,
DATA_WIDTH = 64,
FIFO_DEPTH = 512;
input addr;
input wdata;
input write;
input sel;
output rdata;
wire [BUS_WIDTH-1:0] addr;
wire [DATA_WIDTH-1:0] wdata;
reg [DATA_WIDTH-1:0] rdata;
reg [7:0] fifo [FIFO_DEPTH];
// Design code goes here ...
endmodule
No novo estilo ANSI de declaração de porta Verilog, você pode declarar parâmetros como mostrado abaixo.
module design_ip
#(parameter BUS_WIDTH=32,
parameter DATA_WIDTH=64) (
input [BUS_WIDTH-1:0] addr,
// Other port declarations
);
Substituindo parâmetros
Os parâmetros podem ser substituídos por novos valores durante a instanciação do módulo. A primeira parte instancia o módulo chamado design_ip pelo nome d0 onde novos parâmetros são passados dentro de
#( )
. A segunda parte usa uma construção Verilog chamada defparam
para definir os novos valores de parâmetro. O primeiro método é a maneira mais comumente usada para passar novos parâmetros em projetos RTL. O segundo método é comumente usado em simulações de bancada de teste para atualizar rapidamente os parâmetros de projeto sem precisar reinstanciar o módulo.
module tb;
// Module instantiation override
design_ip #(BUS_WIDTH = 64, DATA_WIDTH = 128) d0 ( [port list]);
// Use of defparam to override
defparam d0.FIFO_DEPTH = 128;
endmodule
Exemplo
O contador do módulo tem dois parâmetros N e DOWN declarados com um valor padrão de 2 e 0, respectivamente. N controla o número de bits na saída controlando efetivamente a largura do contador. Por padrão, é um contador de 2 bits. O parâmetro DOWN controla se o contador deve aumentar ou diminuir. Por padrão, o contador diminuirá porque o parâmetro está definido como 0.
contador ascendente de 2 bits
module counter
#( parameter N = 2,
parameter DOWN = 0)
( input clk,
input rstn,
input en,
output reg [N-1:0] out);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
if (en)
if (DOWN)
out <= out - 1;
else
out <= out + 1;
else
out <= out;
end
end
endmodule
O contador do módulo é instanciado com N como 2, embora não seja necessário porque o valor padrão é 2. DOWN não é passado durante a instanciação do módulo e, portanto, assume o valor padrão de 0, tornando-o um contador ascendente.
module design_top ( input clk,
input rstn,
input en,
output [1:0] out);
counter #(.N(2)) u0 ( .clk(clk),
.rstn(rstn),
.en(en));
endmodule
Veja que os parâmetros padrão são usados para implementar o contador onde N é igual a dois tornando-o um contador de 2 bits e DOWN igual a zero tornando-o um contador ascendente. A saída do contador é deixada desconectada no nível superior.
contador regressivo de 4 bits
Neste caso, o contador do módulo é instanciado com N como 4 tornando-o um contador de 4 bits. DOWN recebe um valor de 1 durante a instanciação do módulo e, portanto, um contador regressivo é implementado.
module design_top ( input clk,
input rstn,
input en,
output [3:0] out);
counter #(.N(4), .DOWN(1))
u1 ( .clk(clk),
.rstn(rstn),
.en(en));
endmodule
Especificar parâmetros
Eles são usados principalmente para fornecer valores de tempo e atraso e são declarados usando o
specparam
palavra-chave. É permitido ser usado tanto dentro do especificar bloco e o corpo do módulo principal.
// Use of specify block
specify
specparam t_rise = 200, t_fall = 150;
specparam clk_to_q = 70, d_to_q = 100;
endspecify
// Within main module
module my_block ( ... );
specparam dhold = 2.0;
specparam ddly = 1.5;
parameter WIDTH = 32;
endmodule
Diferença entre parâmetros de especificação e de módulo
Especificar parâmetro | Parâmetro do módulo |
---|---|
Declarado por specparam | Declarado por parameter |
Pode ser declarado dentro de specify bloco ou dentro do módulo principal | Só pode ser declarado dentro do módulo principal |
Pode ser atribuído specparams e parâmetros | Não podem ser atribuídos specparams |
SDF pode ser usado para substituir valores | Valores de parâmetro de declaração de instância ou defparam pode ser usado para substituir |
Verilog