Skip to content

UVM

Sequence Arbitration

How the sequencer chooses among contending sequences at each grant — the arbitration modes (FIFO, weighted, random, strict, user), how priority works in each, and the strict-vs-weighted starvation trade-off.

Advanced Sequences · Module 10 · Page 10.4

The Engineering Problem

Module 9.2 introduced that a sequencer arbitrates among competing sequences and named the modes in passing. When multiple sequences run on one sequencer — background traffic, a periodic interrupt, an error injector — they compete for the single driver, and which one's item goes next at each grant is decided by the sequencer's arbitration policy. That decision is not a detail: choose the wrong policy and a high-priority interrupt waits behind background traffic, or a low-priority background sequence never runs at all because a high-priority one always wins. Arbitration is the sequencer's scheduler, and like any scheduler it has policies with real trade-offs.

This chapter is that scheduler in depth. The sequencer offers a set of arbitration modesUVM_SEQ_ARB_FIFO (order, ignores priority), UVM_SEQ_ARB_WEIGHTED (probabilistic by priority), UVM_SEQ_ARB_RANDOM (uniform), UVM_SEQ_ARB_STRICT_FIFO/UVM_SEQ_ARB_STRICT_RANDOM (highest priority always wins), and UVM_SEQ_ARB_USER (custom) — and each uses sequence priority differently. The defining trade-off is strict vs weighted: strict modes guarantee high-priority sequences win, but can starve low-priority ones forever; weighted/random modes avoid starvation by giving everyone a chance. This chapter is the modes, how priority works in each, the starvation trade-off, custom arbitration, and why a starved low-priority sequence is the bug strict arbitration causes.

How does a sequencer arbitrate among contending sequences — the modes (FIFO, weighted, random, strict, user), how each uses priority, and the strict-vs-weighted trade-off where strict guarantees priority ordering but can starve low-priority sequences?

Motivation — why arbitration needs configurable policy

A single, fixed arbitration rule can't serve every testbench, because different scenarios want different scheduling — and each mode exists for one:

  • Sometimes order is all that matters, so FIFO exists. When sequences are equal peers and you just want fairness-by-arrival, first-come-first-served (FIFO, the default) is simplest and predictable — no priority to manage.
  • Sometimes you want bias without guarantees, so weighted exists. Often a sequence should be favored (an interrupt over background traffic) but not allowed to monopolize. Weighted arbitration makes higher priority more likely to win each grant while still giving others a chance — bias without starvation.
  • Sometimes you want strict ordering, so strict modes exist. When a high-priority sequence must win whenever it's ready (a critical handler that can't wait), strict priority guarantees it — at the cost of potentially starving lower-priority sequences.
  • Sometimes you want pure randomness, so random exists. For coverage, uniformly random selection among waiting sequences (ignoring priority) maximizes mixing — every contender equally likely.
  • Sometimes none of the built-ins fit, so user arbitration exists. Custom fairness (round-robin), dynamic priority, or scenario-specific selection needs a hook — user_priority_arbitration() lets you write the policy.

The motivation, in one line: different scenarios want different scheduling — order, weighted bias, strict priority, pure randomness, or custom — so the sequencer makes arbitration a configurable policy, with the central trade-off being how strictly priority is honored versus how much starvation is avoided.

Mental Model

Hold sequence arbitration as an OS scheduler choosing which process runs next:

The sequencer is a scheduler, and arbitration is its scheduling policy — choosing, at each tick, which waiting process (sequence) gets the CPU (the grant) next, with the classic priority-versus-starvation trade-off. Several processes are ready (sequences blocked in start_item, each with an item to send), and the scheduler must pick one per tick. Its policy decides how: first-come-first-served (FIFO) runs them in arrival order, ignoring priority; a weighted-fair policy (weighted) rolls a loaded die — higher-priority processes are more likely but not certain, so everyone still runs eventually; a strict-priority policy (strict) always runs the highest-priority ready process, so a critical process never waits — but a low-priority process can be starved forever if something high-priority is always ready; a lottery (random) picks uniformly; and a custom policy (user) is any rule you write. This is exactly the dilemma every OS scheduler faces: strict priority is responsive but starves, weighted-fair is starvation-free but less guaranteed. The one failure mode that bites: pick strict priority, run a high-priority process that's always ready, and your low-priority background process never gets the CPU — it's not broken, it's starved.

So arbitration is scheduling sequences: pick the policy that matches the scenario — order, weighted bias, strict priority, lottery, or custom — knowing that the more strictly you honor priority, the more you risk starving the low-priority work. The sequencer is a tiny OS scheduler, and the trade-offs are the same.

Visual Explanation — the arbitration modes and priority

The defining picture is the mode taxonomy: each mode is a different rule for using priority, from "ignore it" to "it always decides."

Arbitration modes arranged by how they use priority: ignored, biased, absolute, customadd priority biasmake priorityabsoluteor write your ownFIFO · RANDOMignore priority — order oruniformWEIGHTEDpriority biases (probabilistic)— no starvationSTRICT_FIFO · STRICT_RANDOMhighest priority always wins — canstarveUSERuser_priority_arbitration() —custom12
Figure 1 — the arbitration modes differ in how they use priority. FIFO: ignores priority, grants in arrival order. RANDOM: ignores priority, grants uniformly at random. WEIGHTED: random but biased by priority — higher priority more likely, all still possible. STRICT_FIFO / STRICT_RANDOM: highest priority always wins, with FIFO or random breaking ties at the same priority. USER: your user_priority_arbitration() decides. The spectrum runs from priority-ignored (FIFO/RANDOM) through priority-biased (WEIGHTED) to priority-absolute (STRICT), with USER as the escape hatch.

The figure arranges the modes along a spectrum of how much priority decides. At one end, FIFO and RANDOM ignore priority entirely: FIFO grants in arrival order (the default, predictable, fair-by-arrival), and RANDOM grants uniformly at random among the waiting sequences (maximal mixing). In the middle, WEIGHTED makes priority a bias: it picks randomly but weighted by priority, so a higher-priority sequence is more likely to win each grant while every waiting sequence keeps a non-zero chance — priority influences without dictating. At the far end, STRICT_FIFO and STRICT_RANDOM make priority absolute: the highest-priority waiting sequence always wins, with FIFO (arrival order) or RANDOM breaking ties among sequences of the same priority. And USER is the escape hatch: user_priority_arbitration() lets you implement any policy. The spectrum is the key mental model: as you move from FIFO/RANDOM → WEIGHTED → STRICT, priority goes from ignoredbiasingdeciding, and — crucially — the risk of starvation rises with it. FIFO/RANDOM/WEIGHTED all give every sequence a turn eventually; STRICT does not. So choosing a mode is choosing where on this spectrum you want priority to sit, which is a trade-off the next section makes explicit.

RTL / Simulation Perspective — setting the mode and priority

Arbitration is configured with two calls: set_arbitration on the sequencer (the mode) and set_priority/the start priority argument (per-sequence priority). The code shows both, plus the user hook.

setting the arbitration mode, priorities, and a user policy
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ── SET THE MODE on the sequencer (default is UVM_SEQ_ARB_FIFO) ──
task my_test::run_phase(uvm_phase phase);
  env.agent.sequencer.set_arbitration(UVM_SEQ_ARB_WEIGHTED);  // probabilistic by priority
 
  phase.raise_objection(this);
  fork
    bg.start (env.agent.sequencer, null, /*priority*/ 100);   // background traffic (low priority)
    irq.start(env.agent.sequencer, null, /*priority*/ 500);   // interrupt (high priority)
  join
  phase.drop_objection(this);
endtask
//   higher number = higher priority; default priority is 100
//   also: seq.set_priority(300);   // change a running sequence's priority
 
// ── USER ARBITRATION: override to implement a custom policy (e.g. round-robin) ──
class fair_sequencer extends uvm_sequencer #(bus_item);
  `uvm_component_utils(fair_sequencer)
  function int user_priority_arbitration(int avail_sequences[$]);
    return avail_sequences[0];          // custom selection logic among the waiting sequences
  endfunction                            // (set_arbitration(UVM_SEQ_ARB_USER) to invoke it)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
endclass

The configuration is two knobs. The mode is set on the sequencer with set_arbitration(UVM_SEQ_ARB_WEIGHTED) (or any mode) — it governs how the sequencer picks among contenders, and defaults to UVM_SEQ_ARB_FIFO. Priority is per-sequence: passed when starting (start(sequencer, parent, priority) — here bg at 100, irq at 500) or changed on a running sequence with set_priority; higher number = higher priority, default 100. How the mode uses that priority is the spectrum from Figure 1: under WEIGHTED (shown), irq's 500 makes it more likely to win each grant than bg's 100, but bg still gets turns; under STRICT_FIFO, irq would win every grant it's ready for, starving bg; under FIFO, the priorities would be ignored entirely. User arbitration (the fair_sequencer) overrides user_priority_arbitration(avail_sequences) — which receives the queue of currently-waiting sequences and returns the index of the one to grant — invoked when the mode is UVM_SEQ_ARB_USER; this is where you write a custom policy (round-robin, dynamic fairness, scenario-specific). The shape to carry: mode on the sequencer, priority per sequence, and the mode decides how strictly priority is honored — which directly determines the starvation risk.

Verification Perspective — the strict-vs-weighted trade-off

The decision that matters most is strict vs weighted, because it's the one with a failure mode: strict guarantees priority but can starve, weighted avoids starvation but doesn't guarantee. Understanding the trade-off is choosing correctly.

Strict guarantees priority but starves low-priority; weighted avoids starvation but doesn't guaranteehigh-priorityalways winslow-priority starvedeveryone makes progresseveryonemakes…high-priority not guaranteedhigh-prioritynot…STRICTpriority is absolute✓ Guaranteed orderingcritical seq always goes✗ Starvation possiblelow-priority may never runWEIGHTEDpriority is a bias✓ No starvationeveryone makes progress✗ No guaranteehigh-priority not certain eachgrant12
Figure 2 — strict vs weighted: the starvation trade-off. Strict (STRICT_FIFO/STRICT_RANDOM): the highest-priority ready sequence always wins, so a critical sequence is guaranteed to go — but a low-priority sequence is starved (never runs) whenever a high-priority one is always ready. Weighted: higher priority is more likely but every sequence keeps a non-zero chance, so the low-priority sequence still makes progress — at the cost of the high-priority one not being guaranteed each grant. Strict = guaranteed ordering, risk of starvation; weighted = no starvation, no guarantee.

The trade-off is symmetric, and choosing means deciding which failure you can tolerate. Strict modes (STRICT_FIFO, STRICT_RANDOM) make priority absolute: the highest-priority ready sequence always wins the grant. The benefit is guaranteed ordering — a critical sequence (an interrupt handler that must respond immediately) is certain to go whenever it's ready, which is exactly what some scenarios require. The cost is starvation: if a high-priority sequence always has an item ready, it wins every grant, and lower-priority sequences never run at all — not slowed, starved. Weighted makes priority a bias: the higher-priority sequence is more likely to win, but every waiting sequence keeps a non-zero probability, so all of them make progress eventually. The benefit is no starvation — the low-priority background sequence still gets its turns. The cost is no guarantee — the high-priority sequence isn't certain to win any given grant, so it might occasionally wait. So the choice is: strict when a sequence must win whenever ready and you can ensure it doesn't monopolize (or starvation of others is acceptable); weighted when you want to favor a sequence but every sequence must keep making progress. The default FIFO sits outside this (ignores priority, fair-by-arrival, no starvation). The practical rule: reach for weighted by default (bias without starvation), and use strict only when guaranteed priority ordering is genuinely required — because strict's starvation is the arbitration bug the DebugLab covers.

Runtime / Execution Flow — selection at each grant

At run time, arbitration runs per grant: the sequencer collects the waiting sequences and applies the mode to pick one. Seeing the flow — and where the user hook plugs in — clarifies how the policy is enforced.

Per-grant arbitration: collect waiting sequences, apply the mode to select one, grant it, others re-contendgrant needed → collect waiting → apply mode → grant one → re-contendgrant needed → collect waiting → apply mode → grant one → re-contend1Grant needed (driver pulls)get_next_item triggers a grant; arbitration runs now, per item(Module 9.2).2Collect waiting sequencesall sequences blocked in start_item with an item ready are thecandidates.3Apply the modeFIFO/RANDOM (ignore priority), WEIGHTED (biased), STRICT (highest),USER (custom hook).4Grant one; others re-contendthe chosen sequence's start_item unblocks; the rest wait andre-contend next grant.
Figure 3 — arbitration selects one sequence per grant, by mode. When the driver pulls and a grant is needed, the sequencer collects the sequences currently waiting (blocked in start_item). It then applies the configured mode: FIFO picks the earliest arrival, RANDOM picks uniformly, WEIGHTED picks randomly biased by priority, STRICT picks the highest priority (FIFO/random among ties), and USER calls user_priority_arbitration(). The chosen sequence is granted; the others re-contend at the next grant. The mode is the rule applied at this per-grant decision point.

The per-grant flow is where the policy is enforced, and its per-item nature (Module 9.2's recurring theme) is what makes the mode matter so much. Step 1, a grant is needed when the driver pulls (get_next_item) — arbitration runs at every item, not once per sequence. Step 2, the sequencer collects the candidates: every sequence currently blocked in start_item with an item ready. Step 3, it applies the configured mode to pick one: FIFO takes the earliest arrival, RANDOM picks uniformly, WEIGHTED rolls a priority-weighted random choice, STRICT_FIFO/STRICT_RANDOM take the highest priority (breaking ties by arrival or randomly), and USER calls user_priority_arbitration(avail_sequences), which returns the index of the winner. Step 4, the chosen sequence's start_item unblocks (it sends its item), and the others re-contend at the next grant. The reason the mode's effect is so pronounced is this repetition: because arbitration runs every grant, a strict mode applied to a continuously-ready high-priority sequence re-selects it every single time, which is exactly how starvation arises — the low-priority sequence loses every per-grant decision. Weighted, by contrast, gives the low-priority sequence a fresh non-zero chance at each grant, so over many grants it does win some. So the runtime view explains why the strict-vs-weighted trade-off has teeth: the policy isn't applied once — it's applied at every item, so a starving policy starves continuously, and a fair policy distributes continuously. The USER hook plugs in at step 3, giving you control over that repeated decision.

Waveform Perspective — strict starvation vs weighted fairness

The trade-off is visible on a timeline: under strict arbitration a high-priority sequence wins every grant (starving the low-priority one), while under weighted the low-priority sequence occasionally wins.

Strict (low-priority starved) vs weighted (low-priority occasionally wins)

12 cycles
Strict (low-priority starved) vs weighted (low-priority occasionally wins)STRICT: high-priority H wins every grantSTRICT: high-priority …STRICT: low-priority L never granted — starved (L_prog stays 0)STRICT: low-priority L…WEIGHTED: H favored but L occasionally winsWEIGHTED: H favored bu…WEIGHTED: L granted → makes progress (L_prog rises)WEIGHTED: L granted → …clkmodeSTRSTRSTRSTR--WGTWGTWGTWGTWGTWGT--grantedHHHH--HHLHHL--L_progt0t1t2t3t4t5t6t7t8t9t10t11
Figure 4 — the same two contending sequences under strict vs weighted arbitration. In the STRICT region, the high-priority sequence (H) is always ready and wins every grant, so granted shows only H — the low-priority sequence (L) is starved, never granted. In the WEIGHTED region, H still wins most grants (it's favored), but L occasionally wins (granted shows L at points) — every sequence makes progress. Same priorities, same readiness; the mode decides whether L starves or progresses.

The waveform shows the same contention resolving two ways. In the STRICT region, the high-priority sequence H is always ready, and because strict arbitration always grants the highest priority, granted shows only H — every single grant goes to H, and the low-priority sequence L is never granted: L_prog stays at 0, meaning L makes no progress at all. This is starvationL isn't slow, it's shut out. In the WEIGHTED region, with the identical priorities and readiness, H is favored and wins most grants, but granted shows L winning occasionally (at the marked points), so L_prog risesL makes progress. The visual contrast is the whole trade-off: strict produces an all-H grant stream (guaranteed priority, starved L), weighted produces a mostly-H-some-L stream (favored priority, progressing L). Nothing about the sequences changed — only the mode — yet L is starved under strict and served under weighted. This is why the mode choice is consequential and why a starved low-priority sequence is a real, mode-caused bug: the timeline makes it unmistakable that strict + an always-ready high-priority sequence = a low-priority sequence that never runs, and that weighted is the fix when starvation is unacceptable.

DebugLab — the background sequence that never ran

A low-priority sequence starved by strict arbitration and a continuously-ready high-priority one

Symptom

A test ran a high-priority interrupt-style sequence and a low-priority background-traffic sequence concurrently on the same sequencer, with strict arbitration to ensure the interrupt always won. The interrupt worked perfectly — but the background traffic produced almost no stimulus: it ran a stray item or two, then nothing, for the rest of the test. The background sequence was correct (it ran fine alone), the objection handling was right, and there was no error or hang — the background sequence was simply never getting granted.

Root cause

Strict arbitration plus a continuously-ready high-priority sequence meant the high-priority sequence won every grant — starving the low-priority background sequence:

why the background sequence never ran
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sequencer: set_arbitration(UVM_SEQ_ARB_STRICT_FIFO);   // highest priority ALWAYS wins
  irq seq:  priority 500, always has an item ready (continuous interrupts)
  bg  seq:  priority 100, always has an item ready (background traffic)
 
per grant (arbitration runs at EVERY item):
  both ready → STRICT picks highest priority → irq (500) wins → EVERY time
  → bg (100) loses every grant → never granted → STARVED (no error, just no progress)
 
fix — use a non-starving mode (weighted) so bg still makes progress:
  set_arbitration(UVM_SEQ_ARB_WEIGHTED);   // irq favored, but bg keeps a non-zero chance
  // or: ensure irq is NOT continuously ready (yields between interrupts),
  //     or raise bg's priority / lower irq's so strict doesn't shut bg out

This is the strict-arbitration starvation bug, the classic failure mode of strict priority. Arbitration runs at every grant (per item, Module 9.2), and STRICT_FIFO always grants the highest-priority ready sequence. The interrupt sequence (priority 500) was continuously ready — it always had an item — so at every grant, strict arbitration compared it against the background sequence (priority 100) and picked the interrupt, every single time. The background sequence (lower priority, also always ready) therefore lost every grant and was starved: it never got the sequencer, so it produced no stimulus. There was no error because starvation isn't a failure state — the background sequence is alive and waiting, just never chosen. The telltale is exactly this: a low-priority sequence that runs fine alone but produces nothing when a high-priority one runs concurrently under strict arbitration. The fix depends on intent: if the background sequence must make progress, switch to UVM_SEQ_ARB_WEIGHTED so the interrupt is favored but the background keeps a non-zero chance (no starvation); alternatively, ensure the high-priority sequence is not continuously ready (it yields between bursts, so the background wins the gaps), or adjust priorities so strict doesn't completely shut the background out. The general lesson: strict arbitration guarantees priority but starves, so it's only safe when the high-priority sequence yields or when starving the others is acceptable — otherwise use weighted, which favors without starving.

Diagnosis

The tell is a low-priority sequence that runs alone but not under contention with a high-priority one. Diagnose starvation:

  1. Check the arbitration mode. A strict mode (STRICT_FIFO/STRICT_RANDOM) is the prerequisite for starvation. Under FIFO/weighted/random, a low-priority sequence still gets turns.
  2. Check whether the high-priority sequence is continuously ready. Strict starves only when a higher-priority sequence is always ready to win. If it yields, the low-priority sequence wins the gaps.
  3. Confirm it's starvation, not a hang or bug. The starved sequence is alive and waiting (no error), runs fine alone, and only fails under contention — distinguishing starvation from a logic or objection bug.
  4. Compare priorities. A large priority gap under strict means the lower one is fully shut out; confirm the priorities and mode produce the observed all-high-priority grant stream.
Prevention

Choose arbitration to match the fairness you need:

  1. Default to weighted for favored-but-fair. UVM_SEQ_ARB_WEIGHTED biases toward high priority while keeping every sequence's chance non-zero — no starvation. Reach for it unless strict ordering is required.
  2. Use strict only when a sequence must always win and yields (or others may starve). Strict guarantees priority; only use it when the high-priority sequence isn't continuously ready, or when starving the rest is acceptable.
  3. Mind that arbitration is per item. Because it runs every grant, a continuously-ready high-priority sequence under strict wins every time — design priorities and readiness with that repetition in mind.
  4. Test under contention. A sequence that works alone can be starved under concurrent traffic; run the real concurrent mix to surface starvation, not isolated sequences.

The one-sentence lesson: strict arbitration always grants the highest-priority ready sequence at every grant, so a continuously-ready high-priority sequence starves lower-priority ones — they run fine alone but never under contention — and the fix is to use UVM_SEQ_ARB_WEIGHTED (favored but starvation-free), or ensure the high-priority sequence yields, because strict guarantees priority at the cost of starvation.

Common Mistakes

  • Using strict arbitration with a continuously-ready high-priority sequence. It starves lower-priority sequences (they never get granted); use weighted, or ensure the high-priority sequence yields.
  • Expecting priority to matter under FIFO/RANDOM. Those modes ignore priority; if you want priority to count, use weighted or strict.
  • Assuming weighted guarantees the high-priority sequence wins. Weighted only biases; the high-priority sequence isn't certain each grant. Use strict for a guarantee.
  • Forgetting arbitration is per item. The mode is applied at every grant, not once per sequence — so its effect (favoring or starving) compounds over every item.
  • Not setting the mode (leaving FIFO) when priority is intended. The default is FIFO, which ignores priority; set the mode explicitly if you assigned priorities.
  • Testing sequences in isolation. Starvation and priority effects appear only under contention; isolated runs hide them.

Senior Design Review Notes

Interview Insights

The sequencer offers several arbitration modes that differ in how they use sequence priority. UVM_SEQ_ARB_FIFO, the default, grants in arrival order and ignores priority entirely. UVM_SEQ_ARB_RANDOM grants uniformly at random among the waiting sequences, also ignoring priority. UVM_SEQ_ARB_WEIGHTED picks randomly but biased by priority, so a higher-priority sequence is more likely to win each grant while every waiting sequence keeps a non-zero chance. UVM_SEQ_ARB_STRICT_FIFO and UVM_SEQ_ARB_STRICT_RANDOM make priority absolute: the highest-priority ready sequence always wins, with arrival order or random choice breaking ties among sequences of the same priority. And UVM_SEQ_ARB_USER calls your user_priority_arbitration override, which receives the queue of waiting sequences and returns the index of the one to grant, letting you implement any custom policy like round-robin. You set the mode on the sequencer with set_arbitration, and priority is per-sequence, passed when starting the sequence or via set_priority, with a higher number meaning higher priority and a default of 100. The way to think of the modes is as a spectrum of how much priority decides: FIFO and RANDOM ignore it, WEIGHTED biases by it, STRICT makes it absolute, and USER is the escape hatch. As you move from ignore to bias to absolute, the risk of starvation rises, because FIFO, RANDOM, and WEIGHTED all give every sequence a turn eventually, while STRICT does not. So choosing a mode is choosing where on that spectrum you want priority to sit.

It's a trade-off between guaranteed priority ordering and freedom from starvation. Strict arbitration makes priority absolute: the highest-priority ready sequence always wins the grant, so a critical sequence — say an interrupt handler that must respond immediately — is guaranteed to go whenever it's ready. The cost is starvation: if a high-priority sequence always has an item ready, it wins every grant, and lower-priority sequences never run at all, because arbitration runs at every item and strict re-selects the high-priority one every single time. Weighted arbitration makes priority a bias instead: the higher-priority sequence is more likely to win, but every waiting sequence keeps a non-zero probability, so all of them make progress eventually. The cost there is the absence of a guarantee: the high-priority sequence isn't certain to win any given grant, so it might occasionally wait. So strict gives guaranteed ordering with the risk of starvation, and weighted gives starvation-free progress without a guarantee. The practical guidance is to default to weighted, which favors a sequence without starving the others, and to use strict only when a sequence genuinely must win whenever it's ready and either it yields between bursts so it isn't continuously ready, or starving the lower-priority sequences is acceptable. This is the same dilemma an OS scheduler faces between strict priority scheduling and weighted-fair scheduling, and the failure mode to watch for is a low-priority sequence that runs fine alone but is starved under strict arbitration when a high-priority one is always ready.

Exercises

  1. Match mode to need. For (a) fair-by-arrival peers, (b) an interrupt favored but background must progress, (c) a critical handler that must always win, (d) maximal random mixing — name the arbitration mode.
  2. Predict the grant stream. Two always-ready sequences, priority 500 and 100, under STRICT_FIFO then under WEIGHTED — describe the grant stream and which (if any) starves.
  3. Fix the starvation. A low-priority sequence never runs under strict arbitration with an always-ready high-priority one. Give two fixes and the trade-off of each.
  4. Custom policy. Describe a scenario where user_priority_arbitration is needed and what your override would return.

Summary

  • Sequence arbitration is the sequencer's policy for choosing, at each grant, which contending sequence's item goes next — set with set_arbitration(mode), with per-sequence priority via start(..., priority)/set_priority (higher number = higher priority).
  • The modes form a spectrum of how priority is used: FIFO (default) and RANDOM ignore priority (order / uniform); WEIGHTED makes priority a bias (probabilistic); STRICT_FIFO/STRICT_RANDOM make it absolute (highest always wins, ties by FIFO/random); USER calls your user_priority_arbitration().
  • The defining trade-off is strict vs weighted: strict guarantees the highest-priority sequence wins but can starve lower-priority ones (if a high-priority sequence is always ready); weighted avoids starvation (every sequence keeps a non-zero chance) but doesn't guarantee the high-priority sequence each grant.
  • Arbitration is per item, so the mode's effect compounds: strict re-selects an always-ready high-priority sequence every grant (continuous starvation), while weighted distributes turns continuously.
  • The durable rule of thumb: default to UVM_SEQ_ARB_WEIGHTED (favored but starvation-free), use STRICT only when a sequence must always win and it yields (or starving others is acceptable), set the mode explicitly when you assign priorities (the default FIFO ignores them), and test under contention — because arbitration runs at every grant, so a strict policy with a continuously-ready high-priority sequence silently starves the rest.

Next — Parallel Sequences: arbitration decides which of several concurrent sequences goes next; the next chapter focuses on running sequences in parallel — the fork/join patterns, managing multiple concurrent sequences on one or many sequencers, and synchronizing their completion.