Advanced Verification

OSVVM provides randomization, functional coverage, scoreboards, logging/alerts, transaction-level verification components (AXI4, AXI-Stream, UART), and test reporting (HTML/JUnit).

30.1 Self-checking testbench architecture

Bus functional models (BFMs): procedures that drive protocol transactions (axi_write(addr, data)).

Scoreboards: compare actual vs expected outputs (queues of expected transactions).

Functional coverage: measure which scenarios were exercised.

Constrained random: random stimulus within legal constraints.

┌────────────┐      ┌──────┐      ┌────────────┐
Stimulus →  Driver /   │ ───► │ DUT  │ ───► │  Monitor   │
generator │  BFM       │      └──────┘      └─────┬──────┘
         └────────────┘                          │
               │          ┌────────────────┐     ▼
               └────────► │ Reference model │ → Scoreboard (compare) → pass/fail, coverage
                          └────────────────┘

30.2 OSVVM (Open Source VHDL Verification Methodology)

OSVVM provides randomization, functional coverage, scoreboards, logging/alerts, transaction-level verification components (AXI4, AXI-Stream, UART), and test reporting (HTML/JUnit). It's an IEEE-backed, widely used methodology.

library osvvm;
context osvvm.OsvvmContext;

process
  variable RV : RandomPType;
  variable Cov : CoverageIDType;
begin
  RV.InitSeed(RV'instance_name);
  Cov := NewID("ALU_ops");
  AddBins(Cov, GenBin(0, 7));                    -- cover all 8 opcodes
  while not IsCovered(Cov) loop
    op <= std_logic_vector(to_unsigned(RV.RandInt(0, 7), 3));
    a  <= RV.RandSlv(0, 255, 8);
    b  <= RV.RandSlv(0, 255, 8);
    wait until rising_edge(clk);
    ICover(Cov, to_integer(unsigned(op)));
    AffirmIfEqual(result, model(op, a, b), "ALU result");
  end loop;
  ReportAlerts;
  std.env.stop;
end process;

30.3 UVVM (Universal VHDL Verification Methodology)

Utility library (check_value, await_value, logging), BFMs, and VVCs (VHDL Verification Components) for UART, SPI, I2C, AXI, Avalon, Ethernet; ESA-supported, popular in aerospace.

30.4 VUnit — unit testing & test automation

VUnit integrates with CI (JUnit XML), supports OSVVM/UVVM, and includes verification components and check/logging libraries.

library vunit_lib;
context vunit_lib.vunit_context;

entity tb_counter is
  generic (runner_cfg : string);
end entity;

architecture tb of tb_counter is
begin
  main : process
  begin
    test_runner_setup(runner, runner_cfg);
    while test_suite loop
      if run("count_up") then
        check_equal(1 + 1, 2, "basic sanity");
      elsif run("wraps_around") then
        check(true);
      end if;
    end loop;
    test_runner_cleanup(runner);
  end process;
end architecture;
# run.py
from vunit import VUnit
vu = VUnit.from_argv()
lib = vu.add_library("lib")
lib.add_source_files("src/*.vhd")
lib.add_source_files("test/*.vhd")
vu.main()
python run.py -p 8          # run all tests in parallel with GHDL/NVC/Questa/...

30.5 cocotb — testbenches in Python

cocotb drives VHDL/Verilog designs from Python coroutines (with GHDL, NVC, Questa, Riviera, Xcelium), enabling Python models (NumPy), pytest integration, and libraries like cocotbext-axi.

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, ReadOnly

@cocotb.test()
async def counter_counts(dut):
    cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
    dut.rst.value = 1
    for _ in range(3):
        await RisingEdge(dut.clk)
    dut.rst.value = 0
    await RisingEdge(dut.clk)                 # first edge with reset released
    for expected in range(1, 20):
        await RisingEdge(dut.clk)
        await ReadOnly()                      # sample after the edge has settled
        assert int(dut.q.value) == expected, f"q={int(dut.q.value)}, expected {expected}"

30.6 Regression & CI

Automate simulation with VUnit/OSVVM scripts/cocotb + GitHub Actions or GitLab CI using containers (ghdl/ghdl, OSS CAD Suite); track code coverage (Questa, GHDL+gcov) and functional coverage.