Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> Verilog

For-Schleifen in Verilog meistern: Wiederverwendbare Hardware-Logik erstellen

Eine for-Schleife ist die am häufigsten verwendete Schleife in der Software, wird in Verilog jedoch primär dazu verwendet, Hardware-Logik zu replizieren. Die Idee hinter einer for-Schleife ist es, eine Reihe von Anweisungen innerhalb der Schleife so lange zu iterieren, wie die gegebene Bedingung wahr ist. Dies ist der while-Schleife sehr ähnlich, wird aber häufiger in Kontexten verwendet, in denen ein Iterator verfügbar ist und die Bedingung vom Wert dieses Iterators abhängt.

Syntax

for (<initial_condition>; <condition>; <step_assignment>) begin
  // Statements
end

Das Schlüsselwort for spezifiziert diesen Schleifentyp und hat drei Teile:

  1. Anfangsbedingung zur Spezifikation der Initialwerte von Signalen
  2. Eine Prüfung, ob die gegebene Bedingung wahr ist
  3. Aktualisierung der Steuerungsvariable für die nächste Iteration

Die Anfangsbedingung und Aktualisierungen der Steuerungsvariable sind in der for-Schleife enthalten und müssen nicht separat spezifiziert werden, im Gegensatz zur while-Schleife. Eine while-Schleife ist allgemeiner und wird meist nur verwendet, wenn die gegebenen Anweisungen so lange wiederholt werden sollen, wie eine gegebene Bedingung gilt. Die for-Schleife hat typischerweise einen definierten Anfang und ein definiertes Ende, das durch die Schrittvariable gesteuert wird.

Hier ist ein einfaches Beispiel, das die Verwendung einer for-Schleife veranschaulicht.

module my_design;
  integer i;
  initial begin
    // Beachten Sie, dass der ++-Operator in Verilog NICHT existiert!
    for (i = 0; i < 10; i = i + 1) begin
      $display ("Current loop#%0d ", i);
    end
  end
endmodule

Simulationslog:

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.

Design-Beispiel

Sehen wir uns an, wie ein 8-Bit-Links-Schieberegister in Verilog ohne eine for-Schleife implementiert werden kann und vergleichen es dann mit dem Code mit einer for-Schleife, um den Nutzen eines Schleifenkonstrukts zu würdigen.

module lshift_reg (
  input clk,           // Clock-Eingang
  input rstn,          // Aktiver Low-Reset
  input [7:0] load_val, // Ladewert
  input load_en,       // Lade-Enable
  output reg [7:0] op  // Ausgangsregister-Wert
);
  // Bei posedge von Clock: Wenn Reset low, Output auf 0 setzen
  // Wenn Reset high, neuen Wert in op laden wenn load_en=1
  // Wenn Reset high und load_en=0, Schieberegister nach links verschieben
  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

Dasselbe Verhalten kann mit einer for-Schleife implementiert werden, was den Code reduziert und ihn für verschiedene Registerbreiten skalierbar macht. Wenn die Breite des Registers als Verilog-Parameter definiert wird, wird das Design-Modul skalierbar und derselbe Parameter kann innerhalb der for-Schleife verwendet werden.

module lshift_reg (
  input clk,
  input rstn,
  input [7:0] load_val,
  input load_en,
  output reg [7:0] op
);
  integer i;
  always @ (posedge clk) begin
    if (!rstn) begin
      op <= 0;
    end else begin
      // Wenn load_en 1 ist, Wert in op laden
      // sonst bei jedem Takt weiterschieben
      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

Testbench

Der Testbench-Code ist unten gezeigt und instanziiert das Design.

module tb;
  reg clk;
  reg rstn;
  reg [7:0] load_val;
  reg load_en;
  wire [7:0] op;
  
  // DUT Clock einrichten
  always #10 clk = ~clk;
  
  // Design instanziieren
  lshift_reg u0 (
    .clk(clk),
    .rstn(rstn),
    .load_val(load_val),
    .load_en(load_en),
    .op(op)
  );
  
  initial begin
    // 1. Testbench-Variablen initialisieren
    clk <= 0;
    rstn <= 0;
    load_val <= 8'h01;
    load_en <= 0;
    
    // 2. Reset auf Design anwenden
    repeat (2) @ (posedge clk);
    rstn <= 1;
    repeat (5) @ (posedge clk);
    
    // 3. load_en für 1 Takt setzen, damit load_val geladen wird
    load_en <= 1;
    repeat(1) @ (posedge clk);
    load_en <= 0;
    
    // 4. Design 20 Takte laufen lassen und dann beenden
    repeat (20) @ (posedge clk);
    $finish;
  end
endmodule

Verilog

  1. Verilog Grundlagen: Ihr erstes AND-Gate designen
  2. C# For-Schleifen meistern: Syntax, Ablauf und praktische Beispiele
  3. C# foreach Schleifen: Arrays und Collections einfach durchlaufen
  4. Java-Programm zur Identifikation von Armstrong-Zahlen mit For-Schleife
  5. Verilog meistern: Komplettes Tutorial für digitales Schaltungsdesign
  6. Verilog Concatenation meistern: Praktischer Leitfaden
  7. Verilog Assignments verstehen: Typen, Syntax und Best Practices
  8. Verilog Blocking vs. Non-Blocking: Wichtige Unterschiede erklärt
  9. Verilog Functions meistern für effizientes RTL-Design
  10. Verilog Tasks verstehen: Functions vs. Tasks, Syntax und Verwendung