J'essaie de comprendre pourquoi nous utilisons générer dans Verilog avec une boucle for.
En utilisant une génération et une boucle ensemble:
reg [3:0] temp;
genvar i;
generate
for (i = 0; i < 3 ; i = i + 1) begin:
always @(posedge sysclk) begin
temp[i] <= 1'b0;
end
end
endgenerate
Utilisant seulement pour la boucle:
reg [3:0] temp;
genvar i;
always @(posedge sysclk) begin
for (i = 0; i < 3 ; i = i + 1) begin:
temp[i] <= 1'b0;
end
end
Je pense que les deux extraits produiraient le même résultat, à savoir temp [0] à temp [10] égal à 0. Quelle est la différence/l'avantage que nous voyons en utilisant une instruction generate dans ce cas?
En général, la principale différence entre la boucle generate pour et la boucle régulière régulière est que la boucle génère pour génère une instance pour chaque itération. Cela signifie que dans votre exemple, il y aura toujours 3 blocs (par opposition à 1 bloc dans le cas d'une boucle normale).
Un bon exemple de code que Requiert Générer pour est:
module A();
..
endmodule;
module B();
parameter NUM_OF_A_MODULES = 2; // should be overriden from higher hierarchy
genvar i;
for (i=0 i<NUM_OF_A_MODULES; i=i+1) {
A A_inst();
}
endmodule;
Dans cet exemple, un habitué de ne peut pas créer NUM_OF_A_MODULES instances.
Dans votre exemple, vous pouvez obtenir le résultat requis dans les deux sens. (tant que vous corrigez quelques bugs mineurs :))
Dans l'exemple sans generate
, i
devrait être un genvar
pas integer
. Sinon, les deux sont valides selon la version de IEEE Std 1364 prise en charge par votre jeu d’outils. La construction generate a été ajoutée dans IEEE Std 1364-2001, où les mots clés generate
/endgenerate
sont explicitement requis. Dans IEEE Std 1364-2005, cette option est devenue facultative, la seule condition étant que si generate
est utilisé, il doit correspondre à endgenerate
.
Lorsque vous utilisez IEEE Std 1364-2005 ou SystemVerilog (IEEE Std 1800), la préférence de style de codage entre déclaration implicite et déclaration explicite est importante. Explicit a l'avantage d'être une comparabilité en arrière.
Les blocs de génération sont utiles lorsque vous modifiez la structure physique du module puis via des paramètres. Par exemple, choisir Negedge ou Posedge Clock et en activer seulement un:
if ( param_use_pos == 1) begin : use_pos
always @(posedge sysclk) begin
...
end
end
else begin : use_neg
always @(negedge sysclk) begin
...
end
end
Si vous ne modifiez pas la structure physique, il est généralement préférable d'utiliser les boucles for et les instructions if-else à l'intérieur du bloc always. Les deux approches peuvent synthétiser la même chose, mais lors de l'exécution d'une simulation RTL, l'approche par blocs non générés simule généralement plus rapidement. En effet, les simulateurs peuvent normalement traiter une seule opération à N bits plus rapidement que les opérations à 1 bit. Encore une fois la synthèse est le même résultat
// faster :: 1 always block, simulator can optimize the for loop
always @(posedge sysclk) begin
for (i = 0; i < 3 ; i = i + 1) begin
temp[i] <= 1'b0;
end
end
// slower :: creates 4 always blocks, harder for the simulator to optimize
genvar i;
generate // optional if > *-2001
for (i = 0; i < 3 ; i = i + 1) begin
always @(posedge sysclk) begin
temp[i] <= 1'b0;
end
end
endgenerate // match generate