Part 5 · Sequences · Intermediate

Sequence Items: Fields, Constraints, and Randomization

Hub — uvm_sequence_item as the transaction contract, field macros, constraints, layering, and copy/clone for scoreboards.

Overview

A uvm_sequence_item is the payload object that flows from sequence through sequencer to driver. It answers what to send — address, data, opcode, burst length — but never how to wiggle pins. That boundary is the foundation of reusable UVM agents: the same item class works in block tests, chip tests, and directed regressions because pin timing stays in the driver.

This topic breaks sequence items into five focused lessons. Each lesson answers a different why question: why items must not contain driver logic, why field macros matter for debug and scoreboards, why constraints define legal space vs directed corners, why derived items layer protocol rules, and why clone before queue prevents silent scoreboard corruption.

Lessons in this topic

  1. Item vs Driver Boundary — what belongs in items, what must stay in the driver.

  2. Field Macros & Automation — uvm_field_*, print, compare, copy, pack/unpack.

  3. Constraints & randomize() with — inline blocks, with blocks, failure handling.

  4. Layered & Derived Items — extend items, constraint layering, wr-only variants.

  5. Copy, Clone & Scoreboard — type_id::create, clone before queue, unregistered fields.

Item flow in the stimulus stack

diagram
Legend: [STIM] [SEQ] [DRV] [ITEM] [UVM]

  [STIM] TEST
      │ seq.start(sqr)
      ▼
  [SEQ] SEQUENCE.body()
      │ start_item(req)
      │ req.randomize()          ← [ITEM] fields filled here
      │ finish_item(req)
      ▼
  [SEQ] SEQUENCER  ──►  [DRV] DRIVER.drive_apb(req)
                              │
                              ▼ paddr, pwdata on vif
                         DUT pins

  [ITEM] apb_item { addr, data, write }  — data contract only
  [DRV]  drive_apb() { @(pclk); wait pready; }  — timing policy

Every sub-lesson below expands one aspect of the [ITEM] box — how to define it, randomize it, extend it, and safely copy it for checking.

diagram
[ITEM] hub — ownership rules

  IN the item:     addr, data, write, burst_len, id, user fields
  OUT of the item: virtual interface handles, #delays, clock waits
  OUT of the item: pready/pvalid handshake loops, drive state machines

  WHY: items cross sequence/driver boundary as pure data.
       Driver owns HOW; item owns WHAT.

Key takeaways

  • sequence_item is the data contract between sequence and driver.

  • Field macros give print, compare, and copy for free — register every payload member.

  • Constraints define legal space; randomize() with blocks add per-call directed corners.

  • Clone before queue — never store handles the monitor or driver still mutates.

Common pitfalls

  • Putting virtual interface handles inside items — breaks agent reuse across hierarchies.

  • Forgetting to check randomize() return value — silent constraint conflicts stall debug.

  • Using new() instead of type_id::create() — factory overrides on item types ignored.