https://github.com/thomasafroo/uvm-based-verification-of-4-bit-adder
A combinational adder project that contains verification in UVM.
https://github.com/thomasafroo/uvm-based-verification-of-4-bit-adder
systemverilog uvm
Last synced: 3 months ago
JSON representation
A combinational adder project that contains verification in UVM.
- Host: GitHub
- URL: https://github.com/thomasafroo/uvm-based-verification-of-4-bit-adder
- Owner: thomasafroo
- Created: 2025-01-05T06:42:20.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-01-12T22:44:51.000Z (9 months ago)
- Last Synced: 2025-01-21T20:19:00.847Z (9 months ago)
- Topics: systemverilog, uvm
- Language: SystemVerilog
- Homepage:
- Size: 38.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# UVM-Based Verification of 4-Bit Adder
This project demonstrates the use of Universal Verification Methodology (UVM) to verify a 4-bit combinational adder design. The project contains the SystemVerilog design module, interface, and a comprehensive UVM-based testbench that verifies the functionality of the design using various verification components.
## Project Structure
### Design Module (`adder_4_bit.sv`)
The adder module performs a simple 4-bit addition and outputs the 5-bit result.
```systemverilog
module add(
input [3:0] a, b,
output [4:0] y
);
assign y = a + b;
endmodule
```### Interface (`add_if`)
The interface connects the testbench with the design-under-test (DUT) by defining the input and output signals:
```systemverilog
interface add_if();
logic [3:0] a;
logic [3:0] b;
logic [4:0] y;
endinterface
```### Testbench Structure
#### Transaction
The `transaction` class represents data items (input and expected output) used during the test.
```systemverilog
class transaction extends uvm_sequence_item;
rand bit [3:0] a;
rand bit [3:0] b;
bit [4:0] y;
function new(input string path = "transaction");
super.new(path);
endfunction
`uvm_object_utils_begin(transaction)
`uvm_field_int(a, UVM_DEFAULT)
`uvm_field_int(b, UVM_DEFAULT)
`uvm_field_int(y, UVM_DEFAULT)
`uvm_object_utils_end
endclass```
#### GeneratorThe `generator` creates random transactions and sends them to the driver.
```systemverilog
class generator extends uvm_sequence #(transaction);
`uvm_object_utils(generator)
transaction t;
integer i;
function new(input string path = "generator");
super.new(path);
endfunction
virtual task body();
t = transaction::type_id::create("t");
repeat(10)
begin
start_item(t);
t.randomize();
`uvm_info("GEN",$sformatf("Data send to Driver a :%0d , b :%0d",t.a,t.b), UVM_NONE);
finish_item(t);
end
endtask
endclass
```
#### DriverThe `driver` applies the generated transactions to the DUT using the interface.
```systemverilog
class driver extends uvm_driver #(transaction);
`uvm_component_utils(driver)
function new(input string path = "driver", uvm_component parent = null);
super.new(path, parent);
endfunction
transaction tc;
virtual add_if aif;virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
tc = transaction::type_id::create("tc");if(!uvm_config_db #(virtual add_if)::get(this,"","aif",aif))
`uvm_error("DRV","Unable to access uvm_config_db");
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(tc);
aif.a <= tc.a;
aif.b <= tc.b;
`uvm_info("DRV", $sformatf("Trigger DUT a: %0d ,b : %0d",tc.a, tc.b), UVM_NONE);
seq_item_port.item_done();
#10;
end
endtask
endclass
```
#### MonitorThe `monitor` observes the DUT's outputs and sends them to the scoreboard for checking.
```systemverilog
class monitor extends uvm_monitor;
`uvm_component_utils(monitor)
uvm_analysis_port #(transaction) send;
function new(input string path = "monitor", uvm_component parent = null);
super.new(path, parent);
send = new("send", this);
endfunction
transaction t;
virtual add_if aif;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
t = transaction::type_id::create("t");
if(!uvm_config_db #(virtual add_if)::get(this,"","aif",aif))
`uvm_error("MON","Unable to access uvm_config_db");
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
#10;
t.a = aif.a;
t.b = aif.b;
t.y = aif.y;
`uvm_info("MON", $sformatf("Data send to Scoreboard a : %0d , b : %0d and y : %0d", t.a,t.b,t.y), UVM_NONE);
send.write(t);
end
endtask
endclass
```
#### ScoreboardThe `scoreboard` compares the DUT output with the expected output to verify correctness.
```systemverilog
class scoreboard extends uvm_scoreboard;
`uvm_component_utils(scoreboard)
uvm_analysis_imp #(transaction,scoreboard) recv;
transaction tr;
function new(input string path = "scoreboard", uvm_component parent = null);
super.new(path, parent);
recv = new("recv", this);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
tr = transaction::type_id::create("tr");
endfunction
virtual function void write(input transaction t);
tr = t;
`uvm_info("SCO",$sformatf("Data rcvd from Monitor a: %0d , b : %0d and y : %0d",tr.a,tr.b,tr.y), UVM_NONE);
if(tr.y == tr.a + tr.b)
`uvm_info("SCO","Test Passed", UVM_NONE)
else
`uvm_info("SCO","Test Failed", UVM_NONE);
endfunction
endclass
```#### Agent
The `agent` encapsulates the driver, monitor, and sequencer to provide a reusable verification component.
```systemverilog
class agent extends uvm_agent;
`uvm_component_utils(agent)
function new(input string inst = "AGENT", uvm_component c);
super.new(inst, c);
endfunction
monitor m;
driver d;
uvm_sequencer #(transaction) seqr;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
m = monitor::type_id::create("m",this);
d = driver::type_id::create("d",this);
seqr = uvm_sequencer #(transaction)::type_id::create("seqr",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
d.seq_item_port.connect(seqr.seq_item_export);
endfunction
endclass
```
#### EnvironmentThe `environment` connects the agent and scoreboard, providing the testbench structure.
```systemverilog
class env extends uvm_env;
`uvm_component_utils(env)
function new(input string inst = "ENV", uvm_component c);
super.new(inst, c);
endfunction
scoreboard s;
agent a;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
s = scoreboard::type_id::create("s",this);
a = agent::type_id::create("a",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
a.m.send.connect(s.recv);
endfunction
endclass
```
#### TestThe `test` defines the test sequence and initiates the verification process.
```systemverilog
class test extends uvm_test;
`uvm_component_utils(test)
function new(input string inst = "TEST", uvm_component c);
super.new(inst, c);
endfunction
generator gen;
env e;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
gen = generator::type_id::create("gen");
e = env::type_id::create("e",this);
endfunction
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this);
gen.start(e.a.seqr);
#50;
phase.drop_objection(this);
endtask
endclass
```
### Top-Level Testbench Module (`adder_4_bit_tb.sv`)The top-level module instantiates the DUT and interface and runs the UVM test.
```systemverilog
module add_tb();
add_if aif();
add dut (.a(aif.a), .b(aif.b), .y(aif.y));initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
initial begin
uvm_config_db #(virtual add_if)::set(null, "uvm_test_top.e.a*", "aif", aif);
run_test("test");
end
endmodule
```
## How to Run1. **Requirements:**
- EDA Playground supporting SystemVerilog and UVM with Aldec Riviera Pro
- [View on EDA Playground](https://edaplayground.com/x/tb4f)## Features
- **UVM Components:** Full utilization of UVM components (transaction, driver, monitor, scoreboard, etc.).
- **Randomization:** Randomized input generation to stress-test the design.
- **Coverage:** Functional coverage through monitored transactions.
- **Reusability:** Modular and reusable verification components.## Verification Flow
1. The generator produces random input transactions.
2. The driver applies these transactions to the DUT.
3. The monitor captures the DUT outputs.
4. The scoreboard checks if the DUT output matches the expected values.
5. Results are logged, and the test passes or fails based on the comparison.## Example Simulation Log
```
UVM_INFO @ 0: GEN: Data sent to Driver a: 5, b: 3
UVM_INFO @ 10: DRV: Trigger DUT a: 5, b: 3
UVM_INFO @ 20: MON: Data sent to Scoreboard a: 5, b: 3, y: 8
UVM_INFO @ 20: SCO: Test Passed
```## Future Work
- Extend verification for corner cases (e.g., overflow).
- Add functional and code coverage reports.
- Parameterize the design for variable bit widths (e.g. 8-bit, 16-bit)## References
- [UVM Reference Manual](https://www.accellera.org/)
- [SystemVerilog Language Reference](https://www.ieee.org/)---
Feel free to reach out for any questions or suggestions regarding this project!