Verilog voor Loop
Een for
lus is de meest gebruikte lus in software, maar wordt voornamelijk gebruikt om te repliceren hardwarelogica in Verilog. Het idee achter een for
lus is het herhalen van een reeks instructies die in de lus zijn gegeven, zolang de gegeven voorwaarde waar is. Dit lijkt erg op de while
lus, maar wordt meer gebruikt in een context waar een iterator beschikbaar is en de voorwaarde afhankelijk is van de waarde van deze iterator.
Syntaxis
for (<initial_condition>; <condition>; <step_assignment>) begin
// Statements
end
Het trefwoord for
wordt gebruikt om dit type lus te specificeren en bestaat uit drie delen:
- Initiële voorwaarde om beginwaarden van signalen te specificeren
- Een controle om te evalueren of de gegeven voorwaarde waar is
- Controlevariabele bijwerken voor de volgende iteratie
De beginvoorwaarde en updates voor de controlevariabele zijn opgenomen in de for
lus en hoeft niet apart te worden opgegeven in tegenstelling tot een while
lus. Een while
lus is meer algemeen bedoeld en wordt meestal alleen gebruikt wanneer de gegeven instructies moeten worden herhaald zolang een bepaalde voorwaarde. Maar de for
lus heeft typisch een duidelijk begin en einde, bestuurd door de stapvariabele.
Hier is een eenvoudig voorbeeld dat het gebruik van een for-lus illustreert.
module my_design;
integer i;
initial begin
// Note that ++ operator does not exist in Verilog !
for (i = 0; i < 10; i = i + 1) begin
$display ("Current loop#%0d ", i);
end
end
endmodule
Simulatielogboek 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.
Ontwerpvoorbeeld
Laten we eens kijken hoe een 8-bits linkerschuifregister kan worden geïmplementeerd in Verilog zonder een for
loop en vergelijk het dan met de code met behulp van een for
loop alleen maar om het nut van een looping-constructie te waarderen.
module lshift_reg (input clk, // Clock input
input rstn, // Active low reset input
input [7:0] load_val, // Load value
input load_en, // Load enable
output reg [7:0] op); // Output register value
// At posedge of clock, if reset is low set output to 0
// If reset is high, load new value to op if load_en=1
// If reset is high, and load_en=0 shift register to left
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
Hetzelfde gedrag kan worden geïmplementeerd met een for
lus die de code verkleint en schaalbaar maakt voor verschillende registerbreedtes. Als de breedte van het register een Verilog-parameter wordt, wordt de ontwerpmodule schaalbaar en kan dezelfde parameter worden gebruikt in de for
lus.
module lshift_reg (input clk, // Clock input
input rstn, // Active low reset input
input [7:0] load_val, // Load value
input load_en, // Load enable
output reg [7:0] op); // Output register value
integer i;
// At posedge of clock, if reset is low set output to 0
// If reset is high, load new value to op if load_en=1
// If reset is high, and load_en=0 shift register to left
always @ (posedge clk) begin
if (!rstn) begin
op <= 0;
end else begin
// If load_en is 1, load the value to op
// else keep shifting for every clock
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
Testbank
De testbench-code wordt hieronder weergegeven en geeft het ontwerp aan.
module tb;
reg clk;
reg rstn;
reg [7:0] load_val;
reg load_en;
wire [7:0] op;
// Setup DUT clock
always #10 clk = ~clk;
// Instantiate the design
lshift_reg u0 ( .clk(clk),
.rstn (rstn),
.load_val (load_val),
.load_en (load_en),
.op (op));
initial begin
// 1. Initialize testbench variables
clk <= 0;
rstn <= 0;
load_val <= 8'h01;
load_en <= 0;
// 2. Apply reset to the design
repeat (2) @ (posedge clk);
rstn <= 1;
repeat (5) @ (posedge clk);
// 3. Set load_en for 1 clk so that load_val is loaded
load_en <= 1;
repeat(1) @ (posedge clk);
load_en <= 0;
// 4. Let design run for 20 clocks and then finish
repeat (20) @ (posedge clk);
$finish;
end
endmodule
Verilog