<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: mritunjay bihari singh</title>
    <description>The latest articles on DEV Community by mritunjay bihari singh (@mritunjay_biharisingh).</description>
    <link>https://dev.to/mritunjay_biharisingh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4044983%2Fb656dfee-c930-4f60-8f9b-e180b62f14fa.png</url>
      <title>DEV Community: mritunjay bihari singh</title>
      <link>https://dev.to/mritunjay_biharisingh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mritunjay_biharisingh"/>
    <language>en</language>
    <item>
      <title>5 UVM Patterns Every Verification Engineer Should Know</title>
      <dc:creator>mritunjay bihari singh</dc:creator>
      <pubDate>Fri, 24 Jul 2026 06:55:46 +0000</pubDate>
      <link>https://dev.to/mritunjay_biharisingh/5-uvm-patterns-every-verification-engineer-should-know-4i24</link>
      <guid>https://dev.to/mritunjay_biharisingh/5-uvm-patterns-every-verification-engineer-should-know-4i24</guid>
      <description>&lt;p&gt;Production-Tested Patterns That Scale from IP Blocks to SoCs&lt;br&gt;
Introduction&lt;br&gt;
Over the past 8 years verifying everything from cache coherency controllers to high-speed interconnects, I've noticed that most verification headaches come from not knowing these five UVM patterns. They're not flashy. They won't make your testbench run faster. But they'll make the difference between a clean coverage closure in 6 weeks versus a nightmare that drags 16 weeks past tape-out.&lt;/p&gt;

&lt;p&gt;This isn't a tutorial. This assumes you know UVM basics. This is about how professionals actually structure testbenches when the stakes are real.&lt;/p&gt;

&lt;p&gt;Pattern 1: The Layered Agent Architecture&lt;br&gt;
(Why Your Monitor Shouldn't Drive, and Your Driver Shouldn't Monitor)&lt;br&gt;
The Problem&lt;br&gt;
Ninety-nine percent of first-time UVM code I review has this sin:&lt;/p&gt;

&lt;p&gt;// ❌ WRONG: Driver trying to do everything&lt;br&gt;
class axi_driver extends uvm_driver #(axi_transaction);&lt;br&gt;
    virtual axi_if vif;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task run_phase(uvm_phase phase);
    forever begin
        seq_item_port.get_next_item(item);

        // Driving
        vif.awaddr &amp;lt;= item.addr;
        vif.awlen &amp;lt;= item.len;

        // ⚠️ Also monitoring back???
        // Checking slave response
        if (vif.bvalid) begin
            // This is a MONITOR's job, not driver's!
            `uvm_info("DRV", $sformatf("Write complete: %0h", item.addr), UVM_MEDIUM)
        end

        seq_item_port.item_done(item);
    end
endtask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;endclass&lt;br&gt;
Why this is toxic:&lt;/p&gt;

&lt;p&gt;Tight coupling – Driver can't be tested independently from monitor&lt;br&gt;
Race conditions – Driver writes data, then immediately monitors its own write (timing issues)&lt;br&gt;
Scoreboard confusion – Monitor is supposed to collect gold truth; now it's mixed with driver implementation&lt;br&gt;
Reusability nightmare – Can't plug this driver into different testbenches&lt;br&gt;
The Pattern: Layered, Separate Concerns&lt;br&gt;
// ✅ CORRECT: Driver only drives&lt;br&gt;
class axi_driver extends uvm_driver #(axi_transaction);&lt;br&gt;
    virtual axi_if vif;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task run_phase(uvm_phase phase);
    forever begin
        seq_item_port.get_next_item(item);
        drive_write_transaction(item);
        seq_item_port.item_done(item);
    end
endtask

// ONLY driving logic here
task drive_write_transaction(axi_transaction item);
    @(posedge vif.clk);
    vif.awvalid &amp;lt;= 1'b1;
    vif.awaddr  &amp;lt;= item.addr;
    vif.awlen   &amp;lt;= item.len;
    vif.awsize  &amp;lt;= item.size;

    // Wait for slave to accept
    wait(vif.awready);
    @(posedge vif.clk);
    vif.awvalid &amp;lt;= 1'b0;
endtask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;endclass&lt;/p&gt;

&lt;p&gt;// ✅ CORRECT: Monitor only monitors (passive)&lt;br&gt;
class axi_monitor extends uvm_monitor;&lt;br&gt;
    virtual axi_if vif;&lt;br&gt;
    uvm_analysis_port #(axi_transaction) ap;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task run_phase(uvm_phase phase);
    forever begin
        @(posedge vif.awvalid &amp;amp;&amp;amp; posedge vif.awready);

        // Purely passive observation
        axi_transaction item = axi_transaction::type_id::create("item");
        item.addr = vif.awaddr;
        item.len  = vif.awlen;
        item.size = vif.awsize;

        // Send to analysis port (for scoreboard)
        ap.write(item);
    end
endtask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;endclass&lt;br&gt;
Why This Works at Scale&lt;br&gt;
When I was verifying the interconnect on a 32-core SoC:&lt;/p&gt;

&lt;p&gt;Isolation meant I could test the driver with a simple slave (5 hours to debug driver issues)&lt;br&gt;
Reuse meant I used the same driver on 4 different interconnect variants&lt;br&gt;
Scoreboard clarity – I knew EXACTLY which transactions came from the monitor (observation) vs. the driver (stimulus)&lt;br&gt;
Real win: Found a subtle slave-to-driver handshake bug only because the monitor was purely passive. If they were tangled, I'd never have caught it.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
