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.