Verilog Parameters beheersen: herbruikbare, schaalbare modules bouwen
Parameters zijn Verilog-constructies die een module toestaan herbruikt te worden met een andere specificatie. Een 4-bit opteller kan bijvoorbeeld geparametriseerd worden om een waarde voor het aantal bits te accepteren en nieuwe parameterwaarden kunnen tijdens module-instantiating worden doorgegeven. Zo kan een N-bit opteller een 4-bit, 8-bit of 16-bit opteller worden. Ze zijn als argumenten aan een functie die tijdens een functie-aanroep worden doorgegeven.
parameter MSB = 7;
parameter REAL = 4.5;
parameter FIFO_DEPTH = 256, MAX_WIDTH = 32;
parameter [7:0] f_const = 2'b3; // 2-bit waarde geconverteerd naar 8 bits; 8'b3
Parameters zijn eigenlijk constanten en het is dus illegaal hun waarde tijdens runtime te wijzigen. Het is illegaal een naam opnieuw te declareren die al gebruikt wordt door een net, variabele of andere parameter.
Er zijn twee hoofdtypen parameters, module en specify en beide accepteren een bereiksspecificatie. Maar ze worden normaal zo breed gemaakt als de op te slaan waarde vereist en dus is een bereiksspecificatie niet noodzakelijk.
Module-parameters
Module-parameters kunnen gebruikt worden om parameterdefinities binnen een module te overschrijven en dit maakt dat de module een andere set parameters heeft tijdens compile-tijd. Een parameter kan gewijzigd worden met de defparam-statement of in de module-instantiating-statement. Het is gangbare praktijk om hoofdletters in namen voor de parameter te gebruiken om ze direct opvallend te maken.
De module hieronder gebruikt parameters om de busbreedte, databreedte en de diepte van de FIFO binnen het ontwerp te specificeren, en kan overschreven worden met nieuwe waarden wanneer de module geïnstantieerd wordt of door defparam-statements.
// Verilog 1995 stijl poortdeclaratie
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];
// Ontwerpcode gaat hier ...
endmodule
In de nieuwe ANSI-stijl van Verilog-poortdeclaratie kun je parameters declareren zoals hieronder getoond.
module design_ip #(parameter BUS_WIDTH=32, parameter DATA_WIDTH=64) (
input [BUS_WIDTH-1:0] addr,
// Overige poortdeclaraties
);
Parameters overschrijven
Parameters kunnen overschreven worden met nieuwe waarden tijdens module-instantiating. Het eerste deel instantiateert de module design_ip met de naam d0 waar nieuwe parameters binnen #( ) worden doorgegeven. Het tweede deel gebruikt een Verilog-construct genaamd defparam om de nieuwe parameterwaarden in te stellen. De eerste methode is de meest gebruikte manier om nieuwe parameters in RTL-ontwerpen door te geven. De tweede methode wordt veel gebruikt in testbench-simulaties om de ontwerpparameters snel bij te werken zonder de module opnieuw te hoeven instantiëren.
module tb;
// Module-instantiating override
design_ip #(BUS_WIDTH = 64, DATA_WIDTH = 128) d0 ( [poortlijst]);
// Gebruik van defparam om te overschrijven
defparam d0.FIFO_DEPTH = 128;
endmodule
Voorbeeld
De module counter heeft twee parameters N en DOWN gedeclareerd met een standaardwaarde van respectievelijk 2 en 0. N controleert het aantal bits in de output en controleert effectief de breedte van de teller. Standaard is het een 2-bit teller. Parameter DOWN controleert of de teller moet incrementeren of decrementeren. Standaard zal de teller decrementeren omdat de parameter op 0 staat.
2-bit up-teller
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
De module counter wordt geïnstantieerd met N als 2, ook al is dat niet vereist omdat de standaardwaarde al 2 is. DOWN wordt niet doorgegeven tijdens instantiating en neemt dus de standaardwaarde 0 aan, wat een up-teller oplevert.
module design_top (
input clk,
input rstn,
input en,
output [1:0] out
);
counter #(.N(2)) u0 (
.clk(clk),
.rstn(rstn),
.en(en)
);
endmodule
Zie dat standaardparameters gebruikt worden om de teller te implementeren waar N gelijk is aan twee (2-bit teller) en DOWN gelijk aan nul (up-teller). De output van counter is bovenin niet aangesloten.
4-bit down-teller
In dit geval wordt de module counter geïnstantieerd met N als 4, wat een 4-bit teller oplevert. DOWN krijgt een waarde van 1 tijdens instantiating en dus wordt een down-teller geïmplementeerd.
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
Specify-parameters
Deze worden primair gebruikt voor het doorgeven van timing- en vertragingswaarden en worden gedeclareerd met het trefwoord specparam. Het is toegestaan ze zowel binnen de specify-blok als de hoofdmodule-body te gebruiken.
// Gebruik van specify-blok
specify
specparam t_rise = 200, t_fall = 150;
specparam clk_to_q = 70, d_to_q = 100;
endspecify
// Binnen hoofdmodule
module my_block ( ... );
specparam dhold = 2.0;
specparam ddly = 1.5;
parameter WIDTH = 32;
endmodule
Verschil tussen specify- en module-parameters
| Specify-parameter | Module-parameter |
|---|---|
Gedeclareerd met specparam |
Gedeclareerd met parameter |
Kan gedeclareerd worden binnen specify-blok of hoofmodule |
Kan alleen gedeclareerd worden binnen de hoofmodule |
| Mag specparams en parameters toegewezen krijgen | Mag geen specparams toegewezen krijgen |
| SDF kan gebruikt worden om waarden te overschrijven | Instantiating-parameterwaarden of defparam kunnen gebruikt worden om te overschrijven |
Verilog
- Verilog beheersen: Complete tutorial voor digitale schakelingontwerp
- Verilog concatenatie beheersen: Een praktische gids
- Verilog Essentials: Een beknopt overzicht
- Verilog-toewijzingen begrijpen: types, syntax en best practices
- Verilog Blocking vs. Non-Blocking: belangrijkste verschillen uitgelegd
- Verilog-functies beheersen voor efficiënt RTL-ontwerp
- Verilog Tasks begrijpen: Functions vs Tasks, Syntax en Gebruik
- Verilog Hiërarchische Referentie Scope: Naamconflicten in Modules en Blokken vermijden
- Verilog Clock Generator: Ontwerp & Implementatie Gids
- Verilog Math Functions beheersen voor efficiënt Hardware-ontwerp
- Verilog $timeformat beheersen: Precisie en Weergave-controle