Goroutines in Verilog
A `goroutine` is a lightweight thread of execution.
```verilog
module main;
initial begin
// Calling the function directly
f("direct");
// Calling the function asynchronously
fork
f("goroutine");
join_none
// Anonymous function call
fork
$display("going");
join_none
// Small delay to allow async tasks to complete
#10;
$display("done");
end
// Function definition
task f(input reg [7:0] from);
integer i;
begin
for (i = 0; i < 3; i = i + 1) begin
$display("%s : %0d", from, i);
end
end
endtask
endmodule
Suppose we have a function call f(s)
. Here’s how we’d call that in the usual way, running it synchronously.
initial begin
f("direct");
end
To invoke this function asynchronously, use the fork
keyword. This new fork
will execute concurrently with the calling one.
initial begin
fork
f("goroutine");
join_none
end
You can also start an anonymous function call asynchronously with fork
.
initial begin
fork
$display("going");
join_none
end
Our two function calls are running asynchronously now. We use a small delay to wait for them to finish.
initial begin
#10;
$display("done");
end
When we run this program, we see the output of the blocking call first, then the output of the other asynchronous calls. The asynchronous tasks’ output may be interleaved, because they are being run concurrently.
$ iverilog -o main main.v && vvp main
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done
Next we’ll look at a complement to fork
in concurrent Verilog programs: channels.