# Median7 Signal Denoiser Test Strategy

## Scope

The testbench should treat the DUT as a fixed-rate synchronous 1D median
filter with one signed sample captured on every clock cycle and no input
handshake. The benchmark is intentionally focused on order-statistic logic:
maintaining a sliding 7-sample history, applying signed comparisons
correctly, and selecting the 4th of 7 values exactly. The checker should
validate observable behaviour only: startup fill, exact one-cycle output
latency, signed median semantics, duplicate handling, continuous
window-by-window advancement, and reset behaviour.

Python is useful here because longer overlapping windows become tedious to
audit by hand. If used later, it must be used only offline to generate
expected cycle/value pairs for directed vectors. The Verilog testbench must
hardcode those final expectations and must not execute Python at runtime.

## Coverage Goals

- Reset outputs: confirm `out_valid=0` and `sample_out=0` while `rst=1`.
- Startup fill: confirm no valid output is produced until seven new samples
  have been captured after reset deassertion.
- First-output timing: confirm the first median appears exactly one cycle
  after the 7th sample is captured.
- Signed ordering: confirm negative values compare below positive values and
  the DUT does not accidentally treat samples as unsigned.
- Duplicate handling: confirm repeated values are counted as separate
  samples when selecting the median.
- Positive impulse suppression: confirm one large positive spike inside an
  otherwise nominal window does not dominate the output.
- Negative impulse suppression: confirm one large negative spike is also
  rejected by the median selection.
- Sliding-window updates: confirm the output changes correctly when one old
  sample leaves the window and one new sample enters.
- Continuous throughput: once the history is full, confirm `out_valid`
  remains high every cycle until reset.
- Reset mid-stream: confirm stored history is cleared immediately and no
  pre-reset samples influence post-reset outputs.

## Planned Directed Scenarios

- Hold reset active for several cycles, then feed a monotonic sequence such
  as `-9, -4, 0, 3, 8, 12, 20`; verify the first valid output occurs on the
  following cycle and equals `3`.
- Feed a nominal positive baseline with one strong impulsive outlier such as
  `10, 11, 12, 300, 13, 11, 10`; verify the median is `11`, not the spike.
- Feed a nominal negative baseline with one strong negative outlier such as
  `-8, -7, -6, -200, -5, -7, -6`; verify the median is `-7`.
- Feed a mixed-sign, duplicate-heavy window such as
  `-15, 4, 4, 100, -2, 4, 9`; verify the median is `4`.
- Feed a longer sequence whose overlapping windows should produce different
  medians as old samples age out, for example
  `0, 0, 50, 0, 0, 100, 0, 0, 0`; verify each cycle's output against the
  expected median of the most recent 7 captured samples.
- Start producing valid outputs, then assert reset mid-stream and feed a new
  unrelated sequence; verify `out_valid` drops immediately and the first new
  output appears only after seven post-reset samples have been captured.

## Checking Method

- Maintain a sample index and expected output schedule in the testbench so
  each observed `out_valid` cycle can be matched to one specific 7-sample
  input window.
- Compare `sample_out` only on cycles where `out_valid=1`, except during
  reset where `sample_out` must be 0.
- Treat any missing valid pulse, extra valid pulse, wrong output value, or
  wrong restart timing after reset as a failure.
- Prefer short, auditable directed sequences for the core edge cases, then
  add one or two slightly longer sequences to stress sliding-window updates
  across many adjacent windows.

## Python Use

If a helper script is added later, use it only to generate offline golden
values for the directed sequences above.

Planned workflow:

1. Encode each directed stimulus sequence as a Python list of signed
   integers, plus explicit reset boundaries.
2. Simulate the spec, not the RTL:
   - Clear the stored history whenever reset is asserted.
   - Append each post-reset sample to a deque capped at 7 entries.
   - Once the deque reaches length 7, compute the expected median as
     `sorted(window)[3]`.
   - Record the expected output as a `(cycle, value)` pair for the next
     clock cycle, because the spec defines a one-cycle output latency.
3. Print the resulting expected cycle/value table or Verilog initializer
   lines.
4. Copy those literal expected values into `testbench.v`. The final
   simulation must remain pure Verilog and must not call Python.

This workflow keeps the median values reproducible and auditable while
ensuring the runnable benchmark remains self-contained.
