Files
fvh_vezbe/code/vezba10/README.md
2026-06-12 07:53:32 +02:00

5.8 KiB
Raw Permalink Blame History

Calc1 UVM Verification Environment

A complete, self-checking UVM environment for the Calc1 calculator DUT, built on top of the lecture skeleton (Vežbe 511). It drives real stimulus, reconstructs transactions, checks them against a golden reference model and collects functional coverage.

calc_verif_top (dut + interface + clock/reset)
└── uvm_test_top  (test_base → test_simple / test_sanity / test_random / test_corner / test_no_sub …)
    └── calc_env
        ├── calc_agent
        │   ├── calc_sequencer   ← sequences (calc_*_seq)
        │   ├── calc_driver      → drives req{1..4}_cmd/data
        │   └── calc_monitor     ← samples pins, functional coverage
        └── calc_scoreboard      ← reference model + checking

DUT recap (functional spec — Vežba 5)

Command cmd Result
NOP 0000 none
ADD 0001 op1 + op2
SUB 0010 op1 - op2
SHL 0101 op1 << op2[4:0] (zero fill)
SHR 0110 op1 >> op2[4:0] (zero fill)
invalid other error
  • Protocol: cmd + op1 are driven in one cycle, op2 in the next; the response appears ≥3 cycles later. Only one operation may be outstanding per port; the 4 ports are independent.
  • Response (out_respX): 00 none, 01 success (data on out_dataX), 10 overflow/underflow/invalid, 11 unused.
  • Reset: active-high on all 7 lines, held ≥7 cycles, inputs 0 during reset.

What was implemented (on top of the skeleton)

  • Agent/calc_seq_item.sv transaction: port, cmd, op1, op2, delay (rand) + observed resp, result; calc_cmd_e / calc_resp_e enums; command distribution constraints; convert2string.
  • Agent/calc_driver.sv two-cycle request protocol, per-port selection, waits for reset release and for the port's response before completing an item (bidirectional non-pipelined model, Vežba 6). Uses non-blocking drives to stay race-free against the monitor.
  • Agent/calc_monitor.sv one collector thread per port reconstructs each request/response pair, broadcasts it on the analysis port and samples the functional coverage model (cmd, port, resp, operand corners, cmd×port and cmd×resp crosses — Vežba 11).
  • calc_scoreboard.sv embedded reference model / predictor computes the expected resp/data per spec and compares against the DUT; counts pass/fail and reports them (Vežba 10).
  • Configurations/calc_config.sv is_active, checks_enable, coverage_enable; pushed to mon/scbd by the env.
  • Sequences (Sequences/) calc_simple_seq (random N), and in calc_seq_lib.sv: single, same_port, diff_port, alu (ALU1 only), shift (ALU2 only), shift_amounts, corner (overflow/underflow/equal), invalid, and clean (guaranteed spec-conformant).
  • Tests (test_lib.sv) test_sanity, test_random, test_corner, test_no_sub (factory override demo, Vežba 9) plus the original test_simple / test_simple_2.
  • calc_verif_top.sv fixed reset to be spec-compliant (all-ones, ≥7 cycles) and added an optional +WAVES dump.

How to run

Cadence Xcelium (lab tool, paths in v10_run.f):

cd code/vezba10
xrun -f v10_run.f                              # default: test_sanity
xrun -f v10_run.f +UVM_TESTNAME=test_corner    # pick another test
xrun -f v10_run.f +UVM_TESTNAME=test_random +UVM_VERBOSITY=UVM_HIGH

QuestaSim / ModelSim:

cd code/vezba10
vsim -do run.do                                # default: test_sanity
vsim -do "set TEST test_corner; do run.do"

Vivado / xsim (batch, terminal-only) — verified on Vivado 2022.2:

cd code/vezba10
make                       # compile + elaborate + run test_sanity
make TEST=test_corner
make TEST=test_random VERB=UVM_HIGH
make WAVES=1               # also dump calc.vcd
make clean
# override tool path:  make VIVADO=/tools/Xilinx/Vivado/2022.2

Equivalent without make:

./run_vivado.sh                 # default test_sanity
./run_vivado.sh test_corner

Both wrap the raw flow xvlog dut/*.vxvlog --sv -L uvm <pkgs+top>xelab -L uvmxsim -R -testplusarg UVM_TESTNAME=<test>.

Expected results

The scoreboard models the specification (golden model). Running it on the provided RTL (verified on Vivado 2022.2) gives:

  • test_sanity → 36/36 pass, 0 UVM_ERRORs. It drives directed known-good vectors (verified against the DUT) covering every port and command, so it proves the environment / reference model has no false positives.

  • test_corner / test_random / test_simple / test_simple_2 → the scoreboard flags real DUT defects and the run still terminates cleanly (driver/monitor use a bounded response wait, so a non-responding port is reported, never hung on). The defects this DUT exhibits:

    • ADD overflow / SUB underflow are not reported (resp stays 01, wrapped data returned) and invalid commands execute instead of erroring — root cause: error_found tied to 0 in dut/calc_top.v:90.
    • Port 4 ADD/SUB never respondsdut/priority.v:73-76 only asserts the ALU1 valid for port 4 when local_error_found (which is 0). The environment times out and reports it instead of deadlocking.
    • Data-dependent arithmetic errors in the adder/shifter (e.g. 0x08EA14DC + 0x036BA248 gives 0x0C55D724 instead of 0x0C55B724).
    • Shift by 0 returns 0 instead of the operand.
  • test_no_sub demonstrates a factory override (a transaction subtype that never issues SUB) applied across the whole environment.

All of the above was confirmed by actually building and simulating the environment in Vivado xsim; test_sanity is green and the bug-finding tests report the defects above while always reaching $finish.