# Test Strategy: Single-Bucket Order Token Throttle

## Goal

Verify cycle-accurate `accept` / `reject` behavior for a single token
bucket, with particular focus on refill timing, saturation, depletion,
and the defined ordering of same-cycle refill and request handling.

## Golden Model Plan

I plan to use a small offline Python model to generate expected
cycle-by-cycle results for fixed test sequences before writing the
Verilog testbench.

The Python helper will:

- Track the same state as the DUT: token count and refill timer phase.
- Apply the exact spec ordering:
  1. determine whether the current cycle is a refill event,
  2. add one token if not already at capacity,
  3. evaluate `order_req`,
  4. consume one token on accept,
  5. update timer phase for the next cycle.
- Emit expected `accept` and `reject` bits for every simulated cycle.

The generated vectors will be copied into the eventual `testbench.v` as
hardcoded expected values. The testbench will not execute Python at
runtime.

## Directed Scenarios

The eventual testbench should include these deterministic cases:

1. Reset behavior:
   Confirm both outputs stay 0 during `rst=1`, the bucket is
   reinitialized to full capacity, and refill timing restarts from the
   initial phase after reset.

2. Basic depletion:
   Use a small configuration such as `bucket_capacity=3`,
   `refill_period=4`. Drive three back-to-back request pulses and confirm
   all are accepted, then confirm the next request is rejected.

3. Empty-bucket rejection:
   After draining the bucket, keep issuing requests before the next
   refill and verify repeated rejections with no underflow behavior.

4. Refill without request:
   Leave `order_req=0` across one or more refill events and verify the
   bucket refills by one token per interval and never jumps by more than
   one token.

5. Same-cycle refill and request when empty:
   Drain the bucket to zero, then issue a request exactly on a refill
   cycle. This is the key edge case. The expected result is `accept=1`
   and `reject=0` because refill happens before request evaluation.

6. Same-cycle refill and request when partially full:
   Arrange for the bucket to have a nonzero token count on a refill
   cycle, then issue a request. Verify that one token is added first,
   then one is consumed.

7. Saturation at capacity:
   Hold `order_req=0` for many cycles and confirm repeated refill events
   do not let the internal token count exceed `bucket_capacity`.

8. Minimum-period corner case:
   Use `bucket_capacity=1`, `refill_period=1`. This stresses off-by-one
   timer logic and ensures a refill event is handled every active cycle.

9. Maximum-period corner case:
   Use a long interval such as `bucket_capacity=16`, `refill_period=256`
   and place requests around the expected refill boundary to catch timer
   wrap mistakes.

10. No-request idle cycles:
    Verify `accept=0` and `reject=0` on every cycle where `order_req=0`,
    including cycles that contain a refill event.

## Testbench Structure Plan

The eventual `testbench.v` should be split into two parts:

- Short hand-written directed sequences for the most important edge
  cases, especially reset and same-cycle refill/request behavior.
- One longer deterministic sequence generated from Python for broader
  coverage across several configurations.

For the longer sequence, I plan to generate a fixed request pattern with
known cycle numbers rather than using runtime randomness. That keeps the
benchmark reproducible while still catching timer and token-accounting
errors that simple hand-written tests may miss.

## Why Python Helps Here

The main risk in this benchmark is not arithmetic width but cycle
ordering. A tiny Python model makes it easy to audit the exact expected
behavior for long sequences and avoids hand-calculating dozens or
hundreds of cycle outcomes, especially for `refill_period=256`.
