Verilog Generate Blöcke meistern: Dynamische Instanziierung & Bedingtes Design
Ein generate Block ermöglicht multiple Modul-Instanzen oder bedingte Instanziierung basierend auf Verilog-Parametern. Praktisch bei wiederholten Operationen/Instanzen oder bedingtem Code-Einschluss.
generate Block darf keine Port-, Parameter-, specparam-Deklarationen oder specify Blöcke enthalten. Andere Module-Items und verschachtelte generate Blöcke erlaubt. Kodierung zwischen generate/endgenerate innerhalb eines module.
Generierte Instanziierungen: Module, Continuous Assignments, always/initial Blöcke, User-Defined Primitives. Drei Konstrukte:
- Generate For Loop
- Generate If-Else
- Generate Case
Generate For Loop
Half Adder N-mal in Top-Level my_design instanziieren. Loop-Variable mit genvar deklarieren (Elaboration-Zeit Variable, nicht zur Simulationszeit verfügbar).
module ha (input a,b, output sum, cout);
assign sum = a ^ b; assign cout = a & b;
endmodule
module my_design #(parameter N=4) (input [N-1:0] a,b, output [N-1:0] sum, cout);
genvar i;
generate
for (i = 0; i < N; i = i + 1) begin
ha u0 (a[i], b[i], sum[i], cout[i]);
end
endgenerate
endmodule
Testbench
Parameter N=2 → 2 Half-Adder Instanzen. a[0],b[0] → sum[0],cout[0]; a[1],b[1] → sum[1],cout[1].
Elaboriertes RTL zeigt tatsächlich zwei Half-Adder Instanzen.
Generate If-Else
Auswahl zwischen zwei Mux-Implementierungen per Parameter USE_CASE.
module mux_assign (input a,b,sel, output out);
assign out = sel ? a : b;
initial $display("mux_assign instantiated");
endmodule
module mux_case (input a,b,sel, output reg out);
always @ (a or b or sel) begin
case (sel) 0: out=a; 1: out=b; endcase
end
initial $display("mux_case instantiated");
endmodule
module my_design (input a,b,sel, output out);
parameter USE_CASE = 0;
generate
if (USE_CASE) mux_case mc (.a(a),.b(b),.sel(sel),.out(out));
else mux_assign ma (.a(a),.b(b),.sel(sel),.out(out));
endgenerate
endmodule
Testbench
USE_CASE=1 → mux_case instanziiert (Simulationslog zeigt Display). USE_CASE=0 → mux_assign.
Generate Case
Instanziierung basierend auf case Expression (multiple Choices).
module ha (input a,b, output reg sum,cout);
always @ (a or b) {cout,sum} = a+b;
initial $display("Half adder instantiation");
endmodule
module fa (input a,b,cin, output reg sum,cout);
always @ (a or b or cin) {cout,sum} = a+b+cin;
initial $display("Full adder instantiation");
endmodule
module my_adder (input a,b,cin, output sum,cout);
parameter ADDER_TYPE = 1;
generate
case (ADDER_TYPE)
0: ha u0 (.a(a),.b(b),.sum(sum),.cout(cout));
1: fa u1 (.a(a),.b(b),.cin(cin),.sum(sum),.cout(cout));
endcase
endgenerate
endmodule
Testbench
ADDER_TYPE=0 → Half Adder instanziiert. cin hat keine Wirkung auf Outputs (Simulationslog bestätigt).
Verilog
- Verilog meistern: Komplettes Tutorial für digitales Schaltungsdesign
- Verilog Concatenation meistern: Praktischer Leitfaden
- Verilog Essentials: Kurzer Überblick
- Verilog Assignments verstehen: Typen, Syntax und Best Practices
- Verilog Blocking vs. Non-Blocking: Wichtige Unterschiede erklärt
- Verilog Functions meistern für effizientes RTL-Design
- Verilog Tasks verstehen: Functions vs. Tasks, Syntax und Verwendung
- Verilog Clock Generator: Design & Implementierungsleitfaden
- Verilog Math Functions meistern für effizientes Hardware-Design
- Verilog $timeformat meistern: Präzision und Anzeigesteuerung