Fork..join for multiple analysis_port.write() in monitor

The execution order of the threads in a fork-join block is not deterministic, in other words you shouldn’t rely on the order.

The usual strategy in this type of monitor component is to fork a number of tasks in the run_phase() which are dedicated to each particular type of cycle. Each task sits in a forever loop and sends an analysis transaction using an analysis_port write() each time it sees the specific cycle complete.

task run_phase(uvm_phase phase);

fork
rdat_cyc();
rd_cyc();
wr_cyc();
idl_cyc();
join

endtask: run_phase

task rdat_cyc;
forever begin
// Look for RDAT
// Assemble TXN
// Clone TXN
ap.write(TXN_CLONE);
end
endtask

Note that if you have a common transaction and a common analysis port, then you should clone() the transaction before you send it, otherwise the transaction handle you see in the analysis component is always the same - i.e. it will be overwritten.