You can control the flow of System Verilog with specific conditions or loops.
System Verilog Loop
If the sequential flow is repeated, it can be easily implemented with the following loop structure.
| Loop | Description |
|---|---|
| forever | Runs the given set of statements forever |
| repeat | Repeats the given set of statements for a given number of times |
| while | Repeats the given set of statments as long as given condition is true |
| for | Similar to while loop, but more condense and popular form |
| do while | Repeats the given set of statements atleast once, and then loops as long as condition is true |
| foreach | Used mainly to iterate through all elements in an array |
forever loop
Forever is a loop that repeats continuously while the simulation is in progress, like while(1).
module top();
//clk 선언
logic clk; initial clk = 1'b0;
//forever loop
initial begin
forever #5 clk = ~clk;
end
//Simulation run time
initial #50 $finish;
//dump file 생성
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmoduleThis is the result of an example that includes a separate statement to terminate the simulation through the $finish task.
repeat loop
If the forever we looked at earlier is a loop that repeats infinitely, repeat is a loop that specifies the number of repetitions.
module top();
logic clk; initial clk = 1'b0;
initial begin
repeat(3) #5 clk = ~clk;
end
initial #50 $finish;
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmoduleIf you run the simulation above, you can see that clk toggles only 3 times.
while, do while loop
while is a loop that repeats the flow as long as the condition is true.
module top();
int cnt = 0;
initial begin
while (cnt < 5 ) begin
$display("cnt = %0d", cnt);
cnt++;
end
end
endmodule>> cnt = 0
>> cnt = 1
>> cnt = 2
>> cnt = 3
>> cnt = 4
On the other hand, do while is a loop that executes the statement once and then repeats the flow if the condition is true.
module top();
int cnt = 0;
int cnt_1 = 0;
initial begin
while (cnt == 5 ) begin
$display("cnt = %0d", cnt);
cnt++;
end
end
initial begin
do begin
$display("cnt_1 = %0d", cnt_1);
cnt++;
end while (cnt == 5 );
end
endmodule>> cnt_1 = 0 (cnt is not printed)
That is, the difference between these two is that the do while statement executes at least once even if the condition is false.
for loop
The differences between System Verilog and Verilog are as follows:
- Declaring variables within a for loop
- One or more initial declarations or modifications within a for loop
module top();
initial begin
$display("###############");
for(int i=0; i<4; i++) $display("i = %0d",i);
$display("###############");
end
initial begin
$display("###############");
for ( int j=0,i=4; j<8; j++) begin
if(j==i) $display("i = j. j=%0d i=%0d",j,i);
end
$display("###############");
end
initial begin
$display("###############");
for ( int j=0,i=3; j<4; j++,i--) begin
$display("j=%0d, i=%0d",j,i);
end
$display("###############");
end
endmoduleAs above, a more enhanced for statement can be used in System Verilog.
foreach
The System Verilog foreach statement specifies iteration over the elements of an array. The loop variable is determined by the array elements, and the number of variables must match the array size.
module top();
int array_1[4];
int array_2[3][2];
initial begin
$display("###############");
foreach(array_1[i]) begin
array_1[i] = i;
$display("array_1[%0d]=%0d",i,array_1[i]);
end
$display("###############");
end
initial begin
$display("###############");
foreach(array_2[i,j]) begin
array_2[i][j] = i+j;
$display("array_2[%0d][%0d]=%0d",i,j,array_2[i][j]);
end
$display("###############");
end
endmoduleThe simulation results are as follows.
Whether synthesis is possible
Most of the above statements are loops for testbench use. This means they won't be implemented as actual semiconductor circuits during System Verilog synthesis. While for loops, while loops, and foreach loops can be synthesized, for loops are primarily used in actual RTL designs.
Break, Continue
Break and continue are constructs that can be used in System Verilog's loop structures (forever, repeat, while, do-while, for, foreach).
Let's look at a simple example.
module top();
initial begin
$display("#####################");
for (int i=0; i<8; i++) begin
if ((i > 2) && (i < 5)) begin
$display("Continue");
continue;
end
if (i==6) begin
$display("Time to finish i = %0d",i);
break;
end
$display("INT i = %0d",i);
end
$display("#####################");
end
endmoduleThe simulation results are as follows.
if – else
System Verilog's if-else has unique-if and priority-if added, which are not present in Verilog.
unique-if
unique-if evaluates all conditions simultaneously, and issues a warning if two or more conditions are true or none of them are true (i.e., there is no else condition).
module top();
int a,b,c;
initial begin
a=10;
b=20;
c=40;
unique if ( a < b ) $display("a is less than b");
else if ( a < c ) $display("a is less than c");
else $display("a is greater than b and c");
end
endmodule>> xmsim: *W,MCONDE: Unique if violation: Multiple true if clauses at {line=10:pos=13 and line=11:pos=13}.
module top();
int a,b,c;
initial begin
a=50;
b=20;
c=40;
unique if ( a < b ) $display("a is less than b");
else if ( a < c ) $display("a is less than c");
//else $display("a is greater than b and c");
end
endmodule>> xmsim: *W,NOCOND: Unique if violation: Every if clause was false.
priority-if
priority-if evaluates all conditions sequentially, and generates a warning if no conditions are true or there is no final else.
module top();
int a,b,c;
initial begin
a=50;
b=20;
c=40;
priority if ( a < b ) $display("a is less than b");
else if ( a < c ) $display("a is less than c");
end
endmodule>> xmsim: *W,NOCOND: Priority if violation: Every if clause was false.
Event
Events are used to synchronize two or more concurrent processes.
event e1;
event e2 = e1;
event done = null;Events are triggered using the -> or ->> operator, and changes to events can be detected using the @ operator and .triggered.
module top();
event event_a;
initial begin
#20 -> event_a;
$display("[%0t] Thread1: event_a triggered", $time);
end
initial begin
$display("[%0t] Thread2: waiting event_a", $time);
@(event_a);
$display("[%0t] Thread2: received event_a", $time);
end
initial begin
$display("[%0t] Thread3: waiting event_a", $time);
wait(event_a.triggered);
$display("[%0t] Thread3: received event_a", $time);
end
endmoduleThread3 detects an event with wait, but an error occurs when wait(event_a) is entered.
What is the difference between @ and .triggered in the above example? Let's check out the example below.
module top();
event event_a;
initial begin
#20 -> event_a;
$display("[%0t] Thread1: event_a triggered", $time);
end
initial begin
$display("[%0t] Thread2: waiting event_a", $time);
#20 @(event_a);
$display("[%0t] Thread2: received event_a", $time);
end
initial begin
$display("[%0t] Thread3: waiting event_a", $time);
#20 wait(event_a.triggered);
$display("[%0t] Thread3: received event_a", $time);
end
endmoduleIf you do event detection at the moment it is triggered, you will get the following result.
wait is a non-blocking statement, so it can detect an event because it is executed after the # delay in the same time slot, but @ is a blocking statement, so it cannot detect an event because it is executed before the # delay (race condition). In this case, ->> can be used.
module top();
event event_a;
initial begin
#20 ->> event_a;
$display("[%0t] Thread1: event_a triggered", $time);
end
initial begin
$display("[%0t] Thread2: waiting event_a", $time);
#20 @(event_a);
$display("[%0t] Thread2: received event_a", $time);
end
initial begin
$display("[%0t] Thread3: waiting event_a", $time);
#20 wait(event_a.triggered);
$display("[%0t] Thread3: received event_a", $time);
end
endmoduleYou can detect events in @ by using the trigger operator as ->> instead of ->.
Functions
System Verilog functions are used to reduce lines of code by declaring repetitive statements as a single function. Functions have the following constraints:
- Time-controlled statements such as #, @, wait, posedge, and negedge cannot be used.
- You can use other functions inside a function, but not tasks (tasks are time-consuming).
- At least one input is required and output and inout cannot be declared.
- Non-blocking assignment, force-release, or assign-deassign cannot be used.
Here's how to declare it:
function [automatic] [return_type] name ([port_list]);
[statements]
endfunctionLet's check out a simple example.
function int sum (
int x
,int y
);
sum = x + y;
endfunction
function int mul (
int x
,int y
);
return x * y;
endfunction
module top ();
initial begin
$display("sum(3,4) = %0d", sum(3,4));
$display("mul(3,4) = %0d", mul(3,4));
end
endmodule>> sum(3,4) = 7
>> mul(3,4) = 12
If there is no output value, you can specify it as a void function.
module top ();
function void print_hello;
$display("Hello System Verilog!!");
endfunction
initial begin
print_hello;
end
endmodule>> Hello System Verilog!!
Task
Tasks, like functions, allow you to reduce repetitive statements into a single statement. The difference from functions is that they allow for time-controlled statements.
module top;
int x;
//task to add two integer numbers.
task sum(input int a,b,output int c);
c = a+b;
endtask
initial begin
sum(10,5,x);
$display("Value of x = %0d",x);
end
endmodule>> Value of x = 15
References: chip verify