Calc1 UVM Verification Environment
A complete, self-checking UVM environment for the Calc1 calculator DUT, built on top of the lecture skeleton (Vežbe 5–11). 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+op1are driven in one cycle,op2in the next; the response appears≥3cycles later. Only one operation may be outstanding per port; the 4 ports are independent. - Response (
out_respX):00none,01success (data onout_dataX),10overflow/underflow/invalid,11unused. - 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) + observedresp, result;calc_cmd_e/calc_resp_eenums; 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 expectedresp/dataper 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 incalc_seq_lib.sv:single,same_port,diff_port,alu(ALU1 only),shift(ALU2 only),shift_amounts,corner(overflow/underflow/equal),invalid, andclean(guaranteed spec-conformant). - Tests (
test_lib.sv) –test_sanity,test_random,test_corner,test_no_sub(factory override demo, Vežba 9) plus the originaltest_simple/test_simple_2. calc_verif_top.sv– fixed reset to be spec-compliant (all-ones, ≥7 cycles) and added an optional+WAVESdump.
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/*.v → xvlog --sv -L uvm <pkgs+top> →
xelab -L uvm → xsim -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 (
respstays01, wrapped data returned) and invalid commands execute instead of erroring — root cause:error_foundtied to0indut/calc_top.v:90. - Port 4 ADD/SUB never responds —
dut/priority.v:73-76only asserts the ALU1 valid for port 4 whenlocal_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 + 0x036BA248gives0x0C55D724instead of0x0C55B724). - Shift by 0 returns
0instead of the operand.
- ADD overflow / SUB underflow are not reported (
-
test_no_subdemonstrates 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.