Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Verilog

Maîtriser les Boucles For en Verilog : Construire une Logique Matérielle Réutilisable

Une boucle for est la boucle la plus utilisée dans le logiciel, mais elle est principalement utilisée pour répliquer la logique matérielle en Verilog. L'idée derrière une boucle for est d'itérer un ensemble d'instructions données dans la boucle aussi longtemps que la condition donnée est vraie. Cela ressemble beaucoup à la boucle while, mais est davantage utilisé dans un contexte où un itérateur est disponible et où la condition dépend de la valeur de cet itérateur.

Syntaxe

for (<condition_initiale>; <condition>; <affectation_pas>) begin
  // Instructions
end

Le mot-clé for est utilisé pour spécifier ce type de boucle et comporte trois parties :

  1. Condition initiale pour spécifier les valeurs initiales des signaux
  2. Une vérification pour évaluer si la condition donnée est vraie
  3. Mise à jour de la variable de contrôle pour l'itération suivante

La condition initiale et les mises à jour de la variable de contrôle sont incluses dans la boucle for et ne sont pas requises d'être spécifiées séparément contrairement à une boucle while. Une boucle while est plus polyvalente et est principalement utilisée seulement lorsque les instructions données doivent être répétées aussi longtemps qu'une condition donnée. Cependant, la boucle for a typiquement un début et une fin définis contrôlés par la variable de pas.

Voici un exemple simple qui illustre l'utilisation d'une boucle for.

module my_design;
  integer i;
  initial begin
    // Notez que l'opérateur ++ n'existe pas en Verilog !
    for (i = 0; i < 10; i = i + 1) begin
      $display ("Boucle actuelle #%0d ", i);
    end
  end
endmodule

Journal de Simulation

ncsim> run
Current loop#0
Current loop#1
Current loop#2
Current loop#3
Current loop#4
Current loop#5
Current loop#6
Current loop#7
Current loop#8
Current loop#9
ncsim: *W,RNQUIE: Simulation is complete.

Exemple de Conception

Examinons comment un registre à décalage gauche 8 bits peut être implémenté en Verilog sans boucle for puis comparons-le avec le code utilisant une boucle for pour apprécier l'utilité d'une structure de boucle.

module lshift_reg (
  input clk,        // Entrée d'horloge
  input rstn,       // Reset actif bas
  input [7:0] load_val, // Valeur de chargement
  input load_en,    // Activation de chargement
  output reg [7:0] op // Valeur de sortie du registre
);
  // Au front montant d'horloge, si reset est bas mettre la sortie à 0
  // Si reset est haut, charger la nouvelle valeur dans op si load_en=1
  // Si reset est haut, et load_en=0 décaler le registre vers la gauche
  always @ (posedge clk) begin
    if (!rstn) begin
      op <= 0;
    end else begin
      if (load_en) begin
        op <= load_val;
      end else begin
        op[0] <= op[7];
        op[1] <= op[0];
        op[2] <= op[1];
        op[3] <= op[2];
        op[4] <= op[3];
        op[5] <= op[4];
        op[6] <= op[5];
        op[7] <= op[6];
      end
    end
  end
endmodule

Le même comportement peut être implémenté en utilisant une boucle for qui réduira le code et le rendra évolutif pour différentes largeurs de registre. Si la largeur du registre est rendue paramètre Verilog, le module de conception deviendra évolutif et le même paramètre peut être utilisé à l'intérieur de la boucle for.

module lshift_reg (
  input clk,        // Entrée d'horloge
  input rstn,       // Reset actif bas
  input [7:0] load_val, // Valeur de chargement
  input load_en,    // Activation de chargement
  output reg [7:0] op // Valeur de sortie du registre
);
  integer i;
  // Au front montant d'horloge, si reset est bas mettre la sortie à 0
  // Si reset est haut, charger la nouvelle valeur dans op si load_en=1
  // Si reset est haut, et load_en=0 décaler le registre vers la gauche
  always @ (posedge clk) begin
    if (!rstn) begin
      op <= 0;
    end else begin
      // Si load_en est 1, charger la valeur dans op
      // sinon continuer à décaler pour chaque horloge
      if (load_en) begin
        op <= load_val;
      end else begin
        for (i = 0; i < 8; i = i + 1) begin
          op[i+1] <= op[i];
        end
        op[0] <= op[7];
      end
    end
  end
endmodule

Banc de Test

Le code du banc de test est montré ci-dessous et instancie la conception.

module tb;
  reg clk;
  reg rstn;
  reg [7:0] load_val;
  reg load_en;
  wire [7:0] op;
  // Configuration de l'horloge DUT
  always #10 clk = ~clk;
  // Instanciation de la conception
  lshift_reg u0 (
    .clk(clk),
    .rstn (rstn),
    .load_val (load_val),
    .load_en (load_en),
    .op (op)
  );
  initial begin
    // 1. Initialiser les variables du banc de test
    clk <= 0;
    rstn <= 0;
    load_val <= 8'h01;
    load_en <= 0;
    // 2. Appliquer le reset à la conception
    repeat (2) @ (posedge clk);
    rstn <= 1;
    repeat (5) @ (posedge clk);
    // 3. Mettre load_en pour 1 cycle d'horloge afin que load_val soit chargé
    load_en <= 1;
    repeat(1) @ (posedge clk);
    load_en <= 0;
    // 4. Laisser la conception tourner pendant 20 cycles d'horloge puis finir
    repeat (20) @ (posedge clk);
    $finish;
  end
endmodule

Verilog

  1. Verilog basique : concevoir votre première porte ET
  2. Maîtriser les boucles For en C# : Syntaxe, flux et exemples pratiques
  3. Programme Java pour identifier les nombres d'Armstrong avec une boucle for
  4. Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
  5. Maîtriser la concaténation Verilog : Guide pratique
  6. Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
  7. Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
  8. Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
  9. Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation