Menguasai Perulangan For dalam Verilog: Membangun Logika Perangkat Keras yang Dapat Digunakan Ulang
Perulangan for adalah perulangan yang paling banyak digunakan dalam perangkat lunak, tetapi terutama digunakan untuk mereplikasi logika perangkat keras dalam Verilog. Ide di balik perulangan for adalah untuk mengulang serangkaian pernyataan yang diberikan dalam perulangan selama kondisi yang diberikan bernilai true. Ini sangat mirip dengan perulangan while, tetapi digunakan lebih dalam konteks di mana iterator tersedia dan kondisi bergantung pada nilai iterator ini.
Sintaks
for (<initial_condition>; <condition>; <step_assignment>) begin
// Statements
end
Kata kunci for digunakan untuk menentukan jenis perulangan ini dan memiliki tiga bagian:
Kondisi awal untuk menentukan nilai awal sinyal
Pemeriksaan untuk mengevaluasi apakah kondisi yang diberikan bernilai true
Pembaruan variabel kontrol untuk iterasi berikutnya
Kondisi awal dan pembaruan variabel kontrol disertakan dalam perulangan for dan tidak perlu ditentukan secara terpisah berbeda dengan perulangan while. Perulangan while lebih umum dan sebagian besar digunakan hanya ketika pernyataan yang diberikan perlu diulang selama kondisi yang diberikan. Namun perulangan for biasanya memiliki awal dan akhir yang pasti yang dikontrol oleh variabel langkah.
Berikut adalah contoh sederhana yang menggambarkan penggunaan perulangan for.
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
Log Simulasi
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.
Contoh Desain
Mari kita lihat bagaimana register geser kiri 8-bit dapat diimplementasikan dalam Verilog tanpa perulangan for dan kemudian bandingkan dengan kode menggunakan perulangan for hanya untuk menghargai utilitas konstruksi perulangan.
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
Perilaku yang sama dapat diimplementasikan menggunakan perulangan for yang akan mengurangi kode dan membuatnya dapat diskalakan untuk lebar register yang berbeda. Jika lebar register dibuat sebagai parameter Verilog, modul desain akan menjadi dapat diskalakan dan parameter yang sama dapat digunakan dalam perulangan for.
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
Testbench
Kode testbench ditunjukkan di bawah ini dan membuat instance desain.
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