Day 25 — SystemVerilog Processes & IPC
Implement and debug concurrent stimulus using fork/join variants, events, mailboxes, semaphores and watchdog timeouts.
Concept lesson
Understand the language feature before coding
Day 25 — Processes and IPC
Simulation status (28 Oct 2026): The full lab passes on Verilator 5.052, including mailbox, semaphore, event and fork. Icarus Verilog 12 runs only the tb/day25_processes_ipc_icarus.sv subset. Details: Week 5 validation record (VALIDATION.md).
Workspace: project_workspace/week5_systemverilog/day25_processes_ipc
Theory (2 h)
Explain fork...join, join_any, join_none, wait fork, disable fork, events, mailbox, bounded mailbox, semaphore and producer/consumer patterns.
Guided lab (2 h)
Demonstrate the six XLS exercises: fork/join; join_any; join_none; wait fork; disable fork; event trigger/wait. Record ordering and termination.
Independent lab (2 h)
Demonstrate mailbox put/get/try_get, bounded mailbox, semaphore locking, producer/consumer, parallel stimulus, and timeout/watchdog.
Debug / assignment (1 h)
Intentionally block a consumer and start a worker that never completes; capture watchdog evidence, correct synchronization/termination and rerun.
Suggested execution
verilator --binary --timing --top-module day25_processes_ipc tb/day25_processes_ipc.sv -o day25_sim
./obj_dir/day25_sim | tee logs/day25.log
For the Icarus-supported process/event and queue-based producer-consumer
subset, run .venv/bin/python scripts/check_week5_simulator.py --simulator
iverilog --run. This fallback does not validate native mailbox, semaphore,
join_any, join_none, wait fork or disable fork behavior; run the full
lab on a simulator that supports those constructs.
Compatibility: the full lab passes on Verilator 5.052. On another simulator, check its support for SystemVerilog mailbox, semaphore, event and fork constructs first.
Evidence
Keep source, logs, transaction ordering, deadlock reproduction, fix and final PASS/FAIL report. Do not use UVM or Week 6 constrained-random features.
Visual explanation
Connect syntax with simulator behavior
Worked example
Read and run the supplied SystemVerilog source
Example source · Day 25
// Week 5 Day 25 — SystemVerilog process and IPC demonstration.
// Simulator compatibility must be checked before claiming runtime PASS.
module day25_processes_ipc;
mailbox #(int) channel = new(2);
semaphore gate = new(1);
event start_event;
int received = 0;
int total = 0;
bit done = 0;
task automatic producer();
for (int i = 1; i <= 4; i++) begin
channel.put(i);
$display("PRODUCER put %0d", i);
end
channel.put(-1); // sentinel
endtask
task automatic consumer();
int value;
forever begin
channel.get(value);
if (value == -1) break;
gate.get(1);
received += value;
total++;
gate.put(1);
$display("CONSUMER get %0d", value);
end
done = 1;
endtask
initial begin : main
fork
begin
#1;
-> start_event;
end
begin
@start_event;
$display("EVENT received");
end
join
fork
producer();
consumer();
join
if (!done || total != 4 || received != 10)
$fatal(1, "DAY25 FAIL: count=%0d sum=%0d", total, received);
fork
begin #2; $display("join_any fast"); end
begin #4; $display("join_any slow"); end
join_any
wait fork;
fork
begin #1; $display("join_none worker"); end
join_none
wait fork;
fork
begin forever #1; end
begin #3; $display("disable fork cleanup"); end
join_any
disable fork;
$display("DAY25 PASS");
$finish;
end
initial begin : watchdog
#100;
$fatal(1, "DAY25 FAIL: watchdog timeout");
end
endmodule
Compile and run
mkdir -p logsverilator --binary --timing --top-module day25_processes_ipc tb/day25_processes_ipc.sv -o day25_sim./obj_dir/day25_sim | tee logs/day25.log
What to verify
- fork/join
- join_any
- join_none
- wait fork
- disable fork
- event synchronization
- mailbox put/get/try_get
- bounded mailbox
- semaphore exclusion
- producer-consumer
- parallel stimulus
- timeout/watchdog
- deadlock recovery
Pass condition: Expected values and transaction counts match; no hanging process; watchdog catches intentional timeout; final DAY25 PASS is printed.
Hands-on practice
Complete the exercises in order
Written assignment
- Compare fork/join, join_any and join_none with timing diagrams.
- Explain event missed-trigger risk and a safe synchronization pattern.
- Document bounded mailbox backpressure and semaphore mutual exclusion.
- Provide deadlock/runaway before-and-after logs, simulator version and command.
Debug challenge
Reproduce a blocked mailbox consumer and a runaway worker, record the timeout, then fix the producer/consumer termination protocol and rerun.
Completion criteria
12 XLS activities covered; concurrent processes terminate deterministically; bounded mailbox, semaphore and watchdog tests pass.
Knowledge check
Check your understanding
How do fork...join, join_any and join_none differ?
join waits for all children; join_any waits for any one; join_none starts children without waiting.
Why can an event trigger be missed?
A process waiting on an event after its trigger does not receive the earlier transient trigger; establish synchronization before triggering.
How does a bounded mailbox provide backpressure?
A blocking put waits when the mailbox reaches its capacity until a consumer removes an item.
What problem does a semaphore solve in concurrent stimulus?
It limits access to a shared resource so critical sections cannot be entered by too many processes simultaneously.
What does wait fork do after processes were started with join_none?
It blocks until all outstanding child processes of the current process complete.
Why use a typed mailbox such as mailbox #(transaction)?
It restricts transferred values to the expected transaction type.
Evidence to retain
- SystemVerilog source
- Build and run commands
- PASS/FAIL transcript
- producer-consumer ordering proof
- watchdog timeout proof
- deadlock/runaway fix evidence