Interprocess communication is a way to communicate between different processes and testbench components. There are three mechanisms:
Mailbox
A mailbox serves as a synchronization primitive utilized for exchanging data between processes within a testbench. This data, referred to as a message, is managed through the mailbox primitive. A process intending to send data places (puts) the message into the mailbox, where it is temporarily stored in system-defined memory. The receiving process then retrieves (gets) the message from the mailbox. This mechanism facilitates efficient and orderly communication between concurrent processes in a verification environment.
A mailbox can be categorized based on its sizes as follows:
- Bounded Mailbox: is where the size of the mailbox is defined. This means it can hold a limited number of messages at any given time. Bounded mailboxes are useful for controlling the flow of data between processes, ensuring that one process does not overwhelm another with too many messages.
- Unbounded Mailbox: a mailbox that does not have a fixed size limit, allowing an unlimited number of messages to be stored. Unbounded mailboxes are particularly useful when the exact number of messages to be exchanged is not known in advance or when you want to avoid potential blocking issues due to mailbox overflow.
Generic Mailbox
A generic mailbox is designed to hold any type of data. This is typically achieved using the class keyword in SystemVerilog, where the mailbox can store objects of any class type.
Syntax
mailbox <mailbox name>
Parameterized Mailbox
A parameterized mailbox is a more flexible and type-safe way to handle different types of data. It uses SystemVerilog’s parameterization features to specify the type of data the mailbox will handle at the time of its creation.
Syntax
mailbox #(<type>) <mailbox name>
Mailbox Methods
Here is a list of some basic operations:
Method | Description |
---|---|
new(); | creates a mailbox |
put(); | send the message in the mailbox |
try_put(); | attempts to send the message without blocking if the mailbox is full |
get(); | retrieve the message from the mailbox |
try_get(); | attempts to retrieve the message from the mailbox without blocking if the mailbox is empty |
peek(); | this method allows you to look at the message at the front of the mailbox without removing it. |
Example Code
class packet;
rand bit [3:0] a;
rand bit [3:0] b;
bit [4:0] s;
function void rand_cal();
$display("--------------------- Packet Generation ---------------------");
$display("a = %0d, b = %0d, s = %0d", a, b, s);
endfunction
endclass
// transmitter class
class trans;
packet pkt;
mailbox t2r;
function new(mailbox mbx); // constructor
t2r = mbx;
endfunction
task run();
pkt = new();
pkt.randomize(); // randomize packet
pkt.rand_cal(); // display packet
pkt.s = pkt.a + pkt.b; // perform some fucntion
t2r.put(pkt); // put the packet in the mailbox
$display("-------------- Transmitter: Packet in Mailbox ---------------");
$display("a = %0d, b = %0d => s = %0d", pkt.a, pkt.b, pkt.s);
endtask
endclass
//receiver class
class rcvr;
packet pkt;
mailbox r2t;
function new(mailbox mbx);
r2t = mbx;
endfunction
task run();
r2t.get(pkt); // get the packet from the mailbox
$display("--------------- Receiver: Packet From Mailbox ---------------");
$display("a = %0d, b = %0d => s = %0d", pkt.a, pkt.b, pkt.s);
endtask;
endclass
module test;
trans trans_cl; // class handle
rcvr rcvr_cl;
mailbox mbx;
initial begin
mbx = new(); // object creation; UNBOUNDED mailbox
trans_cl = new(mbx); // transmitter object creation ang passing mailbox handle
rcvr_cl = new(mbx); // receiver object creation ang passing mailbox handle
$display("-------------------------------------------------------------");
$display("-------------------------- Mailbox --------------------------");
$display("-------------------------------------------------------------");
repeat(10) begin
trans_cl.run();
rcvr_cl.run();
$display("\n");
end
end
endmodule