Part 5 · Sequences · Intermediate
Sequencer Arbitration & lock/grab
Hub — multiple sequences on one driver, FIFO arbitration, lock/grab/unlock/ungrab, priority, set_arbitration modes, and starvation triage.
Overview
One uvm_sequencer serves one driver on one interface — but many sequences may run concurrently on that sequencer. The sequencer arbitrates which sequence's pending start_item gets the driver next. Without understanding arbitration, tests that mix background traffic with directed setup produce mysterious interleaving, register programming races, and hangs that look like driver bugs but are really forgotten unlocks.
This topic breaks sequencer arbitration into five focused lessons. Each answers a different why question: why one driver needs an arbiter, how default FIFO interleaves items, when lock/grab provides atomic multi-beat access, how priority and set_arbitration change ordering, and how to triage starvation when sequences block forever at start_item.
Lessons in this topic
Why Arbitration Exists — one driver, many sequences, the serialization problem.
FIFO Default Arbitration — interleaving at start_item boundaries with timeline diagram.
lock / grab / unlock / ungrab — exclusive access and atomic register programming.
Priority & set_arbitration — set_priority, UVM_SEQ_ARB modes, weighted selection.
Starvation & Debug Triage — forgotten unlock, hang signatures, verbosity playbook.
Arbitration in the stimulus stack
Legend: [STIM] [SEQ] [UVM]
[STIM] MULTIPLE SEQUENCES → ONE SEQUENCER → ONE DRIVER
TEST / VSEQ
│
│ bg_seq.start(sqr) test_seq.start(sqr) prog_seq.start(sqr)
▼
┌─────────────────────────────────────────────────────────┐
│ [UVM] SEQUENCER — arbitration engine │
│ │
│ pending queue: [bg] [test] [bg] [prog] [bg] ... │
│ │ │
│ ▼ one item at a time │
│ get_next_item → driver │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────┐
│ DRIVER │ [STIM] executes one item → DUT pins
└─────────────┘
[SEQ] Each start_item/finish_item pair = one arbitration slot
Without lock: items from different sequences interleaveArbitration sits between procedural sequence threads and the single driver executor. Every lesson below expands one mechanism in this box.
[SEQ] arbitration decision tree
Sequence calls start_item(req)
│
▼
Is sequencer locked by another sequence?
│
├─ YES → block until unlock/ungrab
│
└─ NO → enter arbitration queue
│
▼
set_arbitration mode picks winner:
FIFO → first pending start_item
WEIGHTED → priority-weighted selection
RANDOM → random among pending
USER → custom hook (rare)
│
▼
driver gets item → finish_item unblocks sequenceKey takeaways
One driver, many sequences — the sequencer serializes access via arbitration.
Default FIFO interleaves at start_item boundaries — not at fork/join thread boundaries.
lock/grab for atomic multi-beat ops; priority and set_arbitration for ordering policy.
Forgotten unlock is the #1 arbitration hang — always pair lock with unlock.
Common pitfalls
Assuming fork join order equals item order — arbitration interleaves freely.
Using grab in every sequence — defeats concurrent stimulus purpose.
Setting priority without knowing the active arbitration mode.