{"id":12195,"date":"2016-04-25T11:24:52","date_gmt":"2016-04-25T18:24:52","guid":{"rendered":"https:\/\/blogs.mentor.com\/verificationhorizons\/?p=12195"},"modified":"2026-03-27T08:41:13","modified_gmt":"2026-03-27T12:41:13","slug":"uvm-the-value-of-flexibility","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2016\/04\/25\/uvm-the-value-of-flexibility\/","title":{"rendered":"UVM: The Value of Flexibility"},"content":{"rendered":"<p>Having been deeply involved with Universal Verification Methodology (UVM) from its inception, and before that, with OVM from its secret-meetings-in-a-hidden-hotel-room beginnings, I must admit that sometimes I forget some of the truly innovative and valuable aspects of what has become the leading verification methodology for both ASIC (see <a href=\"https:\/\/blogs.mentor.com\/verificationhorizons\/blog\/2015\/07\/27\/part-10-the-2014-wilson-research-group-functional-verification-study\/\" target=\"_blank\" rel=\"noopener\">here<\/a>) and FPGA (see <a href=\"https:\/\/blogs.mentor.com\/verificationhorizons\/blog\/2015\/06\/03\/part-6-the-2014-wilson-research-group-functional-verification-study\/\" target=\"_blank\" rel=\"noopener\">here<\/a>) verification teams. So I thought it might be helpful to all of us if I took a moment to review some of the key concepts in UVM. Perhaps it will help even those of us who may have become a bit jaded over the years just how cool UVM really is.<\/p>\n<p>I have long preached that UVM allows engineers to create modular, reusable, randomized self-checking testbenches. Of course, these qualities are all inter-related. For example, modularity is the key to reuse. UVM promotes this through the use of transation-level modeling (TLM) interfaces. By abstracting the connections using ports on the \u201ccalling\u201d side and exports on the \u201cimplementation\u201d side, every component in a UVM testbench is blissfully unaware of the internal details of the component(s) to which it is connected. One of the most important places where this abstraction comes in handy is between sequences and drivers.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2016\/04\/seq2driverconnection.png\" rel=\"attachment wp-att-12196\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-12196 aligncenter\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2016\/04\/seq2driverconnection-520x318.png\" alt=\"seq2driverconnection\" width=\"520\" height=\"318\" \/><\/a> <strong>Figure 1:<\/strong> Sequence-to-Driver Connection(s)<\/p>\n<p>Much of the \u201cmechanical\u201d details are, of course, hidden by the implementation of the sequencer, and the user view of the interaction is therefore rather straightforward:<\/p>\n<p><strong><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2016\/04\/seqdriverapi.png\" rel=\"attachment wp-att-12198\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-12198 aligncenter\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2016\/04\/seqdriverapi-520x255.png\" alt=\"seqdriverapi\" width=\"520\" height=\"255\" \/><\/a><\/strong> <strong>Figure 2:<\/strong> The Sequence-Driver API<\/p>\n<p>Here\u2019s the key: That \u201cdrive_item2bus(req)\u201d call inside the driver can be anything. In many cases, it will be a task call inside the driver that manipulates signals inside the virtual interface, or the calls could be inline:<\/p>\n<pre style=\"padding-left: 30px\"><code>task run_phase(uvm_phase phase);<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0 forever begin<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0 my_transaction tx;<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0 @(posedge dut_vi.clock);<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0<strong> seq_item_port.get_next_item(tx);<\/strong><\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0 dut_vi.cmd\u00a0 = tx.cmd;<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0 dut_vi.addr = tx.addr;<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0 dut_vi.data = tx.data;<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0 @(posedge dut_vi.clock)<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>seq_item_port.item_done();<\/strong><\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>\u00a0 end<\/code><\/pre>\n<pre style=\"padding-left: 30px\"><code>endtask: run_phase<\/code><\/pre>\n<p>As long as the get_next_item() and item_done() calls are present in the driver, everything else is hidden from the rest of the environment, including the sequence. This opens up a world of possibilities.<\/p>\n<p>One example of the value of this setup is when emulation is a consideration. In this case, the task can exist inside the interface, which can itself exist anywhere. For emulation, the interface often will be instantiated inside a protocol module, which includes other protocol-specific information:<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2016\/04\/dualtop.png\" rel=\"attachment wp-att-12199\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-12199 aligncenter\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2016\/04\/dualtop.png\" alt=\"dualtop\" width=\"407\" height=\"298\" \/><\/a> <strong>Figure 3:<\/strong> Dual Top Architecture<\/p>\n<p>You can find out more about how to set up your environment like this in the <a href=\"https:\/\/verificationacademy.com\/cookbook\/connections\" target=\"_blank\" rel=\"noopener\">UVM Cookbook<\/a>. And if you\u2019re interested in learning more about setting up your testbench to facilitate emulation, you can download a very interesting paper <a href=\"http:\/\/go.mentor.com\/4xnvq\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>The flexibility of the TLM interface between the sequence and the driver gives UVM users the flexibility to reuse the same tests and sequences as the project progresses from block-level simulation through emulation. All that\u2019s needed is a mechanism to allow a single environment to instantiate different components with the same interfaces without having to change the code. That\u2019s what the factory is for, and we\u2019ll cover that in our next session.<\/p>\n<p>I&#8217;m looking forward to hearing from the new and advanced UVM users out there!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Having been deeply involved with Universal Verification Methodology (UVM) from its inception, and before that, with OVM from its secret-meetings-in-a-hidden-hotel-room&#8230;<\/p>\n","protected":false},"author":71936,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[1],"tags":[457,506,718,751,764,787,820],"industry":[],"product":[],"coauthors":[],"class_list":["post-12195","post","type-post","status-publish","format-standard","hentry","category-news","tag-emulation","tag-functional-verification","tag-simulation","tag-systemverilog","tag-tlm","tag-uvm","tag-verification-academy"],"_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/12195","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/users\/71936"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=12195"}],"version-history":[{"count":1,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/12195\/revisions"}],"predecessor-version":[{"id":14521,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/12195\/revisions\/14521"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=12195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=12195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=12195"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=12195"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=12195"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=12195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}