Tips for new UVM users

Or: What I forgot in class

When I first learned UVM, there were many things that baffled me. What was still fuzzy after you took a UVM course?

Here is a diagram with the testbench layers, and orange transactions flowing from the test-level sequence into an agent.

  • Sequencer vs. sequence. That little ‘r’ confuses a lot of people. If you are new to UVM, just remember:
    • A sequencer is basically a smart pipe that carries transactions from the test level to the driver. (Yes, it can do more…)
    • Multiple transactions are called a sequence. A single transaction won’t find many bugs, but a flock of them can be dangerous!
  • Why are multiple transactions put in a task?
    • OK, I am generating transactions. Why don’t I just put them into an array?
    • The fourth dimension of your testbench is time! If I just made an array of transaction handles, how do I add delays? If I have two sequences running side by side, into two different interfaces, how do I synchronize them?
    • Each sequence needs to run in the body() task so I can do all this. (Remember, a function can’t have any delays.)
    • What about reactive stimulus? An array of transaction handles is static. What if you want to send in transaction A, check the result, and send in B on success, or C on failure? Or take the value from a read transaction and write that to a new location? This is easy in a SystemVerilog task, but hard with an array of handles.
  • When does my UVM class constructor have one argument vs. two? This is because are two major types of UVM classes.
    • Components such as monitors and drivers. These are part of a testbench hierarchy, the boxes shown above.
      • A test has an environment, which has an agent, which has a monitor, driver, and sequencer. When you create a component, it needs to know its name and parent. So its new() must have these two arguments.
    • Transactions or sequence items, the orange circles above. These objects are created at the test level, and are sent to an agent. Or created by a monitor and sent to a scoreboard or psychiatrist for analysis. They don’t have a fixed location in the testbench. That’s why their new() only has a single name argument.
  • What does it mean to “start a sequence”?
    • A sequence generates transactions. Where do they go? If they are UART transactions, obviously they go to the UART agent. What if there are 4 UARTS in your design? Then your testbench has 4 UART agents. Your test needs to pick one.
    • An agent is just a container for other components. So a sequence needs to connect to a driver. However, what if two sequences both want to send to a single driver. Aha – you need a smart connection, a sequencer. That is why your test class passes a sequencer handle into the sequence start() task.
    • I prefer to say, “start a sequence with a sequencer“, instead of, “start a sequence on a sequencer“. A sequencer does not execute a sequence, and virtual sequences usually don’t have a sequencer.
    • OK, that ‘r‘ is getting annoying. You get the picture.

Want to see more SystemVerilog and UVM tips? Sign up for my upcoming webinar UVM Coding Guidelines: Tip & Tricks You Probably Didn’t Know.

Enjoy your verification journey!
Chris Spear

Any questions or ideas?


One thought on “Tips for new UVM users

Leave a Reply