SystemVerilog Mailbox
A SystemVerilog mailbox is a way of communication between different processes to exchange data. One process can put data into a mailbox that stores data internally and can be retrieved by another process. Mailbox behaves as first-in, first-out (FIFO).
Mailbox Types
- Generic mailbox
- Parameterized mailbox
These mailboxes can be further categorized based on the size as
- Bounded mailbox
- Unbounded mailbox
Generic mailbox
The generic mailbox can be put or get data of any data_type like int, bit, byte, string, etc. By default, the mailbox is a typeless or generic mailbox.
Syntax:
mailbox <mailbox_name>
Parameterized mailbox
The parameterized mailbox can be put or get data of particular data_type. The parameterized mailbox is useful when data_type needs to be fixed. For differences in data_type, a compilation error is expected.
Syntax:
mailbox #(<type>) <mailbox_name>
Example: mailbox #(int) mb;
Bounded mailbox
If the size of the mailbox is defined then it is a bounded mailbox. When the mailbox is full, no further data can be put in the mailbox until an item or data is get from the mailbox.
Unbounded mailbox
The size is not defined. An unbounded mailbox has unlimited size.
Mailbox methods
Method name |
Description |
function new(int bound = 0) |
Returns mailbox handle. An argument represents bounded mailbox size otherwise, it is an unbounded mailbox |
task put(<data>) |
Blocking method that stores data in the mailbox. |
function int try_put(<data>) |
The non-blocking method that stores data in the mailbox if it is not full and returns 1 else 0. |
task get(ref <data>) |
Blocking method to retrieve data from the mailbox |
function int try_get(ref <data>) |
The non-blocking method which returns data if a mailbox is non-empty else returns 0. |
task peek(ref <data>) |
Copies data from the mailbox without removing it from a mailbox |
function int try_peek(ref <data>) |
Tries to copy data from the mailbox without removing it from a mailbox |
function int num() |
Returns number of entries in the mailbox |
Mailbox Examples
Bounded mailbox (Generic mailbox) example
module mailbox_example();
mailbox mb = new(3);
task process_A();
int value = 5;
string name = "STRING";
mb.put(value);
$display("Put data = %0d", value);
mb.put("STRING");
$display("Put data = %s", name);
endtask
task process_B();
int value;
string name;
mb.get(value);
$display("Retrieved data = %0d", value);
mb.get(name);
$display("Retrieved data = %s", name);
endtask
initial begin
fork
process_A();
process_B();
join
end
endmodule
Output:
Put data = 5
Put data = STRING
Retrieved data = 5
Retrieved data = STRING
Unbounded mailbox example
module mailbox_example();
mailbox mb = new();
task process_A();
int value;
repeat(10) begin
value = $urandom_range(1, 50);
mb.put(value);
$display("Put data = %0d", value);
end
$display("----------------------");
endtask
task process_B();
int value;
repeat(10) begin
mb.get(value);
$display("Retrieved data = %0d", value);
end
endtask
initial begin
fork
process_A();
process_B();
join
end
endmodule
Output:
Put data = 42
Put data = 37
Put data = 8
Put data = 29
Put data = 23
Put data = 9
Put data = 4
Put data = 11
Put data = 26
Put data = 29
----------------------
Retrieved data = 42
Retrieved data = 37
Retrieved data = 8
Retrieved data = 29
Retrieved data = 23
Retrieved data = 9
Retrieved data = 4
Retrieved data = 11
Retrieved data = 26
Retrieved data = 29
Parameterized mailbox example
module mailbox_example();
mailbox #(string) mb = new(3);
task process_A();
string name = "Alex";
mb.put(name);
$display("Put data = %s", name);
name = "Robin";
mb.put(name);
$display("Put data = %s", name);
endtask
task process_B();
string name;
mb.get(name);
$display("Retrieved data = %s", name);
mb.get(name);
$display("Retrieved data = %s", name);
endtask
initial begin
fork
process_A();
process_B();
join
end
endmodule
Output:
Put data = Alex
Put data = Robin
Retrieved data = Alex
Retrieved data = Robin
try_get, try_put example
module mailbox_example();
mailbox mb = new(3);
task process_A();
int value;
repeat(5) begin
value = $urandom_range(1, 50);
if(mb.try_put(value))
$display("successfully try_put data = %0d", value);
else begin
$display("failed while try_put data = %0d", value);
$display("Number of messages in the mailbox = %0d", mb.num());
end
end
$display("---------------------------------------");
endtask
task process_B();
int value;
repeat(5) begin
if(mb.try_get(value))
$display("Successfully retrieved try_get data = %0d", value);
else begin
$display("Failed in try_get data");
$display("Number of messages in the mailbox = %0d", mb.num());
end
end
endtask
initial begin
fork
process_A();
process_B();
join
end
endmodule
Output:
successfully try_put data = 42
successfully try_put data = 37
successfully try_put data = 8
failed while try_put data = 29
Number of messages in the mailbox = 3
failed while try_put data = 23
Number of messages in the mailbox = 3
---------------------------------------
Successfully retrieved try_get data = 42
Successfully retrieved try_get data = 37
Successfully retrieved try_get data = 8
Failed in try_get data
Number of messages in the mailbox = 0
Failed in try_get data
Number of messages in the mailbox = 0
peek and try_peek example
module mailbox_example();
mailbox mb = new(3);
task process_A();
int value;
repeat(3) begin
value = $urandom_range(1, 50);
mb.put(value);
$display("put data = %0d", value);
end
$display("----------------------------------");
endtask
task process_B();
int value;
mb.peek(value); // message is not removed
$display("peek data = %0d", value);
mb.peek(value); // message is not removed
$display("peek data = %0d", value);
if(mb.try_peek(value))
$display("Successful try_peek data = %0d", value);
else begin
$display("Failed in try_peek");
end
$display("----------------------------------");
repeat(3) begin
mb.get(value);
$display("get data = %0d", value);
end
$display("----------------------------------");
if(mb.try_peek(value))
$display("Successful try_peek data = %0d", value);
else begin
$display("Failed in try_peek");
end
endtask
initial begin
fork
process_A();
process_B();
join
end
endmodule
Output:
put data = 42
put data = 37
put data = 8
----------------------------------
peek data = 42
peek data = 42
Successful try_peek data = 42
----------------------------------
get data = 42
get data = 37
get data = 8
----------------------------------
Failed in try_peek
System Verilog Tutorials