Files

134 lines
5.8 KiB
Markdown
Raw Permalink Normal View History

2026-06-12 07:53:32 +02:00
# 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`):
```sh
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:**
```sh
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:
```sh
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`:
```sh
./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 (`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 responds** — `dut/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`.