Threads, Events, Mailboxes, and Semaphores
Run several testbench activities in parallel and choose the right synchronization mechanism.
Several activities at once
A testbench often needs to generate commands, monitor responses, and enforce a timeout in parallel. fork...join launches several threads.
fork
drive_requests();
monitor_responses();
watch_timeout();
joinjoin waits for every thread. join_any resumes after the first finishes. join_none resumes immediately and leaves all branches running. With join_any, the remaining branches often need a clean stop such as disable fork so a timeout or driver does not outlive the test.
Automatic local variables prevent loop iterations from unintentionally sharing one value between threads.
Events
An event carries a notification without data.
event reset_done;
fork
begin
apply_reset();
-> reset_done;
end
begin
@reset_done;
start_traffic();
end
join-> triggers the event and @reset_done waits for the next trigger. An event can be missed if it fires before the waiting thread starts. For a persistent condition, a state variable with wait(condition) is often a better fit.
Mailboxes
A mailbox is a FIFO channel that transports values or object handles between threads.
mailbox #(bus_transaction) gen_to_drv = new();
// Generator
gen_to_drv.put(tr);
// Driver
bus_transaction next_tr;
gen_to_drv.get(next_tr);put and get block. try_put, try_get, and try_peek continue if the operation is not possible. A bounded mailbox can apply backpressure inside the testbench, but a bad waiting order can deadlock the entire environment.
Semaphores
A semaphore manages a number of keys representing a shared resource.
semaphore bus_lock = new(1);
bus_lock.get(1);
drive_exclusive_sequence();
bus_lock.put(1);With one key, it acts as a lock. Code must return exactly the keys it acquired, even on an error path. A semaphore protects access but carries no command or result.
Choose the mechanism
- use
forkto start concurrent activities; - an
eventfor a one-time notification with no data; - a mailbox to pass transactions;
- a semaphore to limit access to a resource.
Simple synchronization is easier to debug. Hangs often come from a thread waiting for a notification that already happened or a resource that was never released.
Key points
fork...joincontrols concurrent thread launch and completion.- An event can be missed when it is not awaited at the right time.
- A mailbox transports transactions in FIFO order.
- A semaphore protects a shared resource with a number of keys.
- Every thread needs an exit condition and a timeout strategy.
📝 Test your knowledge - Chapter quiz