This repository contains a SystemVerilog verification environment for a 4-bit ALU, implemented using an interface-based, class-based testbench (similar in style to UVM, but lightweight).
The project was originally developed and run in EDA Playground and can also be run locally with a simulator such as ModelSim/Questa or VCS.
Module: alu
Functionality
The ALU operates on two 4-bit operands a and b, controlled by a 2-bit select input:
select = 2'b00→out = a + bselect = 2'b01→out = a - bselect = 2'b10→out = a * bselect = 2'b11→out = a / b
The following status flags are generated from the result:
zero– high ifout == 0sign– MSB ofout(out[3])parity– even parity ofout(~^out)carry– MSB of the 5-bit result{carry,out} = operation(a,b)overflow– signed overflow for add/sub:overflow = (a[3] & b[3] & ~out[3]) | (~a[3] & ~b[3] & out[3])
I/O Ports
| Signal | Dir | Width | Description |
|---|---|---|---|
a |
in | 4 | First operand |
b |
in | 4 | Second operand |
select |
in | 2 | Operation select (00=ADD, 01=SUB, 10=MUL, 11=DIV) |
out |
out | 4 | Operation result (lower 4 bits) |
carry |
out | 1 | Carry / borrow / extra result bit |
zero |
out | 1 | 1 if out == 0 |
sign |
out | 1 | Sign bit (MSB) of out |
parity |
out | 1 | Even parity flag of out |
overflow |
out | 1 | Signed overflow indicator |
The verification environment follows the structure used in lab:
-
Top-level testbench:
alu_tb.sv- Generates clock.
- Instantiates the ALU interface and the DUT.
- Instantiates the
testprogram.
-
Interface:
alu_interface.sv- Bundles DUT pins:
a,b,select,out,zero,carry,sign,parity,overflow. - Provides:
task drive_transaction(transaction tr);function transaction sample_transaction();
- Bundles DUT pins:
-
Program / test:
test.svprogram test(alu_interface inter);- Creates the
environmentand callsenv.run().
-
Environment:
environment.sv- Connects and controls all verification components:
generatordrivermonitorreferencecomparecoverage
- Owns the communication queues:
gen2drv– generator → drivermon2cmp– monitor → comparatormon2cvg– monitor → coverage
- Connects and controls all verification components:
-
Transaction:
transaction.sv- Fields:
- Randomized:
a,b,select - Observed / computed:
out,zero,carry,sign,parity,overflow
- Randomized:
- Methods:
- Constraints on
selectandb(avoid most divide-by-zero, but still allow some). display(string tag),do_copy,do_compare.
- Constraints on
- Fields:
-
Generator:
generator.sv- Randomizes number of transactions.
- Randomizes each
transactionand pushes intogen2drv.
-
Driver:
driver.sv- Has a
virtual alu_interface. - At each clock, pops transactions from
gen2drvand callsinter.drive_transaction(tr).
- Has a
-
Monitor:
monitor.sv- Has a
virtual alu_interface. - On each clock edge (with a small delay), calls
inter.sample_transaction(). - Pushes each sampled transaction into:
mon2cmp(for scoreboard)mon2cvg(for coverage)
- Has a
-
Reference model:
reference.sv- Golden model of ALU behavior at transaction level.
function transaction process(const ref transaction in_tr);- Recomputes the operation and flags from
a,b,select.
- Recomputes the operation and flags from
-
Comparator (Scoreboard core):
compare.sv- Contains counters for total / passed / failed transactions.
- For each
act_trinmon2cmp:- Calls
refm.process(act_tr)→exp_tr. - Compares
act_trvsexp_trusingdo_compare. - Prints detailed ACT vs EXP on mismatches.
- Calls
-
Coverage:
coverage.svcovergroup alu_covergroup with function sample(transaction tr);- Coverpoints:
select(operations)- ranges of
aandb - flags:
zero,sign,parity,carry,overflow
- Cross coverage:
op_cvp× operand rangesop_cvp× each flag
class coveragewraps the covergroup and prints functional coverage percentage.
The testbench uses constrained-random generation plus implicit directed scenarios through constraints. Example scenarios:
-
Basic arithmetic (ADD/SUB)
- Purpose: verify correctness of addition and subtraction for small/mid-range values.
- Inputs:
select ∈ {0,1}a,bconstrained to typical ranges (0–15).
- Expected:
outmatchesa + bora - b(4-bit).carry,zero,sign,parity,overflowfollow ALU spec.
-
Edge and overflow cases (ADD/SUB)
- Purpose: exercise boundary values and signed overflow.
- Inputs focused around extremes:
a,b ∈ {0, 7, 8, 15}select ∈ {0,1}
- Expected:
- Carry high on 4-bit overflow.
overflowhigh for signed overflow patterns (e.g. positive+positive ⇒ negative).
-
Multiply/Divide (including divide-by-zero)
- Purpose: verify multiplication and division operations.
- Inputs:
select = 2with variousa,b.select = 3withb != 0and some cases withb == 0.
- Expected:
- For
b != 0:out = a / b, flags consistent. - For
b == 0: result and flags may be X/undefined; this behavior is observed and documented.
- For
-
Random regression
- Purpose: improve coverage and stress the design.
generatorrandomizesnum_transand all inputs under constraints.- Coverage is sampled on each monitored transaction until target coverage is reached.
Functional coverage is implemented by alu_covergroup:
- operation coverage (
select), - operand value classes (zero, small, mid, max),
- flags (
zero,sign,parity,carry,overflow), - cross coverage between:
- operation and operands,
- operation and each flag.
Coverage is sampled from transactions observed by the monitor (i.e. post-DUT behavior) and summarized at the end of the run:
[COV] Functional coverage = XX.XX %