What is a uvm monitor?

A "uvm_monitor" is an essential element of a testbench that is responsible for observing the activity on the DUT. Its main purpose is to capture the output signals and other relevant data from the DUT's interface and convert them into transaction-level information that can be analyzed and checked for correctness during the verification process.

Code
// Filename : basic_monitor.sv

class basic_monitor extends uvm_monitor;
  `uvm_component_utils(basic_monitor)

	extern         function      new(string name, uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void connect_phase(uvm_phase phase);
	extern virtual function void end_of_elaboration_phase(uvm_phase phase);
	extern virtual function void start_of_simulation_phase(uvm_phase phase);
	
	extern virtual task  main_phase(uvm_phase phase);
	
	extern virtual function void extract_phase(uvm_phase phase);
	extern virtual function void check_phase(uvm_phase phase);
	extern virtual function void report_phase(uvm_phase phase);
	extern virtual function void final_phase(uvm_phase phase);
	
endclass

//------------------------------------------------------------------//

function basic_monitor::new(string name, uvm_component parent);
	super.new(name, parent);

endfunction: new

//------------------------------------------------------------------//

function void basic_monitor::build_phase(uvm_phase phase);
	super.build_phase(phase);
	
endfunction: build_phase

//------------------------------------------------------------------//

function void basic_monitor::connect_phase(uvm_phase phase);
	super.connect_phase(phase);
	
endfunction: connect_phase

//------------------------------------------------------------------//

function void basic_monitor::end_of_elaboration_phase(uvm_phase phase);
	super.end_of_elaboration_phase(phase);
	
endfunction: end_of_elaboration_phase

//------------------------------------------------------------------//

function void basic_monitor::start_of_simulation_phase(uvm_phase phase);
	super.start_of_simulation_phase(phase);
	
endfunction: start_of_simulation_phase

//------------------------------------------------------------------//

task basic_monitor::main_phase(uvm_phase phase);
	super.main_phase(phase);
	phase.raise_objection(this);
	
	phase.drop_objection(this);
endtask: main_phase

//------------------------------------------------------------------//

function void basic_monitor::extract_phase(uvm_phase phase);
	super.extract_phase(phase);
	
endfunction: extract_phase

//------------------------------------------------------------------//

function void basic_monitor::check_phase(uvm_phase phase);
	super.check_phase(phase);
	
endfunction: check_phase

//------------------------------------------------------------------//

function void basic_monitor::report_phase(uvm_phase phase);
	super.report_phase(phase);
	
endfunction: report_phase

//------------------------------------------------------------------//

function void basic_monitor::final_phase(uvm_phase phase);
	super.final_phase(phase);
	
endfunction: final_phase
Theory Questions
    A UVM monitor passively observes the DUT's interface signals and extracts relevant transaction-level information for checking, coverage, or further analysis.
    A driver actively drives stimulus to the DUT, while a monitor passively observes the DUT without influencing its behavior.
    uvm_monitor is the base class from which custom monitors are extended.
    Monitors use analysis ports to broadcast observed transactions to scoreboards or other components that subscribe to the port.
    Because they are meant only to observe and collect data without driving or altering signal values on the DUT interface.
    By connecting to the DUT’s interface and using SystemVerilog constructs like @(posedge clk) or wait statements to sample values passively.
    The analysis port allows the monitor to send collected transactions to one or more subscribers like scoreboards or coverage collectors.
    Yes. A monitor may have multiple analysis ports if it needs to send different types of data or broadcast to different components (e.g., one for scoreboard, another for coverage).
    By monitoring control signals (like valid/ready or req/ack) and capturing data when both handshake conditions are met.
    The run_phase contains the main sampling loop where the monitor waits for signal events and constructs transactions.
    Protocol checking involves monitoring signal sequences and timing relationships, then asserting or logging an error if protocol rules are violated.
    By using multiple clocks or sampling mechanisms (like clocking blocks or asynchronous wait statements) to ensure correct data capture without missing events.
    By writing monitors in a modular, parameterized, and protocol-independent manner using virtual interfaces, so they can be plugged into different environments.
    A monitor extracts transactions from the DUT, while a coverage collector samples these transactions to record coverage metrics. Monitors can feed data to coverage collectors through analysis ports.
    By embedding coverage sampling code inside the monitor or connecting an analysis port to a separate coverage collector component.