0% found this document useful (0 votes)
41 views22 pages

Evaluation Criteria For Block-Level Verification in UVM

This document details the design and verification of an 8-bit Ripple Carry Adder using Verilog, including specifications, RTL code, and testbench implementation. The design was successfully simulated and verified using the Aldec Riviera-PRO simulator, with results matching expected outputs. Additionally, it outlines UVM-based testbench architecture and methodologies for functional verification, including driver, monitor, agent, and scoreboard implementations.

Uploaded by

Rithesh Kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views22 pages

Evaluation Criteria For Block-Level Verification in UVM

This document details the design and verification of an 8-bit Ripple Carry Adder using Verilog, including specifications, RTL code, and testbench implementation. The design was successfully simulated and verified using the Aldec Riviera-PRO simulator, with results matching expected outputs. Additionally, it outlines UVM-based testbench architecture and methodologies for functional verification, including driver, monitor, agent, and scoreboard implementations.

Uploaded by

Rithesh Kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

Name: [Your Name]​

Roll Number: [Your Roll Number]​


College Name: [Your College Name]​
Department: [Your Department]​
Date of Submission: [Your Date]

Project: Design of an 8-bit Ripple Carry Adder using verilog/system


verilog/VHDL.

1.​ Introduction ​
This report presents the RTL design and functional verification of an 8-bit Ripple Carry Adder
using Verilog. The design consists of multiple full adder modules connected sequentially to
perform binary addition. The implementation was verified using EDA Playground with Aldec
Riviera-PRO simulator.

Truth table of 8-Bit Ripple Carry Adder








2.​ Specifications ​

Inputs:

A (8-bit) : First operand

B (8-bit) : Second operand

Cin (1-bit) : Carry-in

Outputs:

S (8-bit) : Sum output

Cout (1-bit) : Carry-out

Design Constraints: The design operates on single-bit addition with carry


propagation.

Design Architecture

The design consists of the following modules:

Full Adder Module: Implements single-bit addition with carry


propagation.

Ripple Carry Adder Module: Uses eight full adders in sequence to


perform 8-bit addition.


Block Diagram:
3. RTL Code
module full_adder (

input A, // Input bit A

input B, // Input bit B

input Cin, // Carry-in

output S, // Sum

output Cout // Carry-out

);

assign S = A ^ B ^ Cin; // Sum calculation

assign Cout = (A & B) | (Cin & (A ^ B)); // Carry-out calculation

endmodule

module ripple_carry_adder_8bit (

input [7:0] A, // 8-bit input A

input [7:0] B, // 8-bit input B

input Cin, // Carry-in

output [7:0] S, // 8-bit sum output

output Cout // Final carry-out

);

wire [7:0] carry; // Internal carry signals

full_adder fa0 (

.A(A[0]),

.B(B[0]),

.Cin(Cin),
.S(S[0]),

.Cout(carry[0])

);

genvar i;

generate

for (i = 1; i < 8; i = i + 1) begin : adder_loop

full_adder fa (

.A(A[i]),

.B(B[i]),

.Cin(carry[i-1]),

.S(S[i]),

.Cout(carry[i])

);

end

endgenerate

assign Cout = carry[7];

endmodule
4.Testbench Code ​

module tb_ripple_carry_adder_8bit;

reg [7:0] A;

reg [7:0] B;

reg Cin;

wire [7:0] S;

wire Cout;

// Instantiate the 8-bit ripple carry adder

ripple_carry_adder_8bit uut (

.A(A),

.B(B),

.Cin(Cin),

.S(S),

.Cout(Cout)

);

// Testbench logic

initial begin

// Test case 1

A = 8'b00000001;

B = 8'b00000001;

Cin = 0;
#10;

$display("A = %b, B = %b, Cin = %b, S = %b, Cout = %b", A, B, Cin, S, Cout);

// Test case 2

A = 8'b11111111;

B = 8'b00000001;

Cin = 0;

#10;

$display("A = %b, B = %b, Cin = %b, S = %b, Cout = %b", A, B, Cin, S, Cout);

// Test case 3

A = 8'b10101010;

B = 8'b01010101;

Cin = 1;

#10;

$display("A = %b, B = %b, Cin = %b, S = %b, Cout = %b", A, B, Cin, S, Cout);

// End simulation

$finish;

end

endmodule
5.Simulation & Verification

Testbench Setup:

■​ Input values are provided for A, B, and Cin. ​​ ​


■​ Output values S and Cout are observed. ​ ​ ​
■​ Multiple test cases are used to verify functionality. ​​ ​

6. Simulation Results:

​ Expected Output:

A = 00000001, B = 00000001, Cin = 0, S = 00000010, Cout = 0

A = 11111111, B = 00000001, Cin = 0, S = 00000000, Cout = 1

A = 10101010, B = 01010101, Cin = 1, S = 00000000, Cout = 1

Simulated Input-Output Waveforms

The design was simulated in Aldec Riviera-PRO. The waveform ​confirmed correct sum
and carry-out values for different test cases.

7. Results and discussion

The 8-bit Ripple Carry Adder was successfully implemented and verified. The simulation results
matched the expected behavior, confirming the correctness of the design.



Evaluation Criteria for Block-Level Verification in UVM

1. Testbench Architecture (50%)

●​ Proper use of UVM components


●​ Adherence to the UVM factory and configuration mechanism.
●​ Proper use of virtual sequences and sequence layering if applicable.
●​ Driver

class adder_driver extends uvm_driver #(adder_transaction);


`uvm_component_utils(adder_driver)

virtual adder_if vif;

function new(string name = "adder_driver", uvm_component parent =null);


​ super.new(name, parent);
​ endfunction

​ virtual function void build_phase(uvm_phase phase);


​ super.build_phase(phase);
​ if (!uvm_config_db#(virtual adder_if)::get(this, "", "vif", vif)) begin
​ `uvm_fatal("DRIVER", "No virtual interface found!")
​ end
​ endfunction

​ virtual task run_phase(uvm_phase phase);


​ forever begin
​ seq_item_port.get_next_item(req);
​ vif.A <= req.A;
​ vif.B <= req.B;
​ vif.Cin <= req.Cin;
​ #10; // Simulate propagation delay
​ seq_item_port.item_done();
​ end
​ endtask
endclass

●​ Monitor

class adder_monitor extends uvm_monitor;


`uvm_component_utils(adder_monitor)

virtual adder_if vif;


adder_transaction trans;
uvm_analysis_port #(adder_transaction) mon_ap;

function new(string name = "adder_monitor", uvm_component parent=null);


​ super.new(name, parent);
endfunction

​ virtual function void build_phase(uvm_phase phase);


​super.build_phase(phase);
​mon_ap = new("mon_ap", this);
​trans = adder_transaction::type_id::create("trans");
​if (!uvm_config_db#(virtual adder_if)::get(this, "", "vif", vif)) begin
​ `uvm_fatal("MONITOR", "No virtual interface found!")
​ end
​ endfunction

​ virtual task run_phase(uvm_phase phase);


​ forever begin
​ #10;
​ trans.A = vif.A;
​ trans.B = vif.B;
​ trans.Cin = vif.Cin;
​ trans.S = vif.S;
​ trans.Cout = vif.Cout;
​ mon_ap.write(trans);
​ end
​ endtask
endclass

●​ Agent

class adder_agent extends uvm_agent;


`uvm_component_utils(adder_agent)

​ adder_driver drv;
​ adder_monitor mon;
​ uvm_sequencer #(adder_transaction) seqr;

function new(string name = "adder_agent", uvm_component parent=null);


​ super.new(name, parent);
​ endfunction

​ virtual function void build_phase(uvm_phase phase);


​ super.build_phase(phase);
​ drv = adder_driver::type_id::create("drv", this);
​ mon = adder_monitor::type_id::create("mon", this);
​ seqr = uvm_sequencer#(adder_transaction)::type_id::create("seqr", this);
​ endfunction

​ virtual function void connect_phase(uvm_phase phase);


​ super.connect_phase(phase);
​ drv.seq_item_port.connect(seqr.seq_item_export);
​ endfunction
endclass

●​ Environment

class adder_env extends uvm_env;


`uvm_component_utils(adder_env)

​ adder_agent agt;
​ adder_scoreboard sb;

function new(string name = "adder_env", uvm_component parent=null);


​ super.new(name, parent);
​ endfunction

​ virtual function void build_phase(uvm_phase phase);


​ super.build_phase(phase);
​ agt = adder_agent::type_id::create("agt", this);
​ sb = adder_scoreboard::type_id::create("sb", this);
​ endfunction

virtual function void connect_phase(uvm_phase phase);


​ super.connect_phase(phase);
​ agt.mon.mon_ap.connect(sb.sb_imp);
endfunction
endclass

●​ Test
class adder_test extends uvm_test;
`uvm_component_utils(adder_test)

​ adder_env env;
​ adder_sequence seq;

function new(string name = "adder_test", uvm_component parent=null);


​ super.new(name, parent);
​ endfunction

​ virtual function void build_phase(uvm_phase phase);


​ super.build_phase(phase);
​ env = adder_env::type_id::create("env", this);
​ seq = adder_sequence::type_id::create("trans",this);
​ endfunction

​ virtual task run_phase(uvm_phase phase);


​ phase.raise_objection(this);
​ seq.start(env.agt.seqr);
​ #100;
​ phase.drop_objection(this);
​ endtask
endclass
●​ Testbench

import uvm_pkg::*;
`include "uvm_macros.svh"

`include "package.sv"

module tb_top;

​ adder_if vif();

ripple_carry_adder_8bit dut (.A(vif.A), .B(vif.B), .Cin(vif.Cin), .S(vif.S), .Cout(vif.Cout));

​ initial begin
​ uvm_config_db#(virtual adder_if)::set(null, "*", "vif", vif);
​ run_test("adder_test");
​ end

initial
​ begin
​ $dumpfile("dump.vcd");
​ $dumpvars();
​ end

endmodule

2. Stimulus Generation (15%)

●​ Development of constrained-random and directed test sequences.


●​ Use of UVM sequences and transaction-based stimulus generation.
●​ Ability to generate different corner cases and invalid scenarios.
●​ Parameterization and reuse of sequences.

●​ Sequence Item

class adder_transection extends uvm_sequence_item;

`uvm_object_utils_begin(adder_transaction)
`uvm_field_int(A,UVM_ALL_ON)
`uvm_field_int(B,UVM_ALL_ON)
`uvm_field_int(Cin,UVM_ALL_ON)
`uvm_field_int(S,UVM_ALL_ON)
`uvm_field_int(Cout,UVM_ALL_ON)
`uvm_object_utils_end

​ rand bit [7:0] A, B;


​ rand bit Cin;
​ bit [7:0] S;
​ bit Cout;

​ function new(string name = "adder_transaction");


​ super.new(name);
​ endfunction
endclass

●​ Sequence

class adder_sequence extends uvm_sequence #(adder_transaction);


​ `uvm_object_utils(adder_sequence)

​ function new(string name = "adder_sequence");


​ super.new(name);
​ endfunction

​ virtual task body();


​ adder_transaction trans;
​ repeat (10) begin
​ trans = adder_transaction::type_id::create("trans");
​ start_item(trans);
​ assert (trans.randomize());
​ finish_item(trans);
​ end
​ endtask

endclass
3. Scoreboarding and Checking (25%)

●​ Implementation of functional and self-checking scoreboard.


●​ Use of predictive models and golden reference comparison.
●​ Effective use of UVM phases for checking.

●​ Scoreboard

class adder_scoreboard extends uvm_scoreboard;


`uvm_component_utils(adder_scoreboard)

​ uvm_analysis_imp #(adder_transaction, adder_scoreboard) sb_imp;

function new(string name = "adder_scoreboard", uvm_component parent=null);


​ super.new(name, parent);
​ endfunction

​ virtual function void build_phase(uvm_phase phase);


​ super.build_phase(phase);
​ sb_imp = new("sb_imp", this);
​ endfunction

​ virtual function void write(adder_transaction trans);


​ bit [8:0] expected = trans.A + trans.B + trans.Cin;
​ if (trans.S !== expected[7:0] || trans.Cout !== expected[8]) begin
​ `uvm_error("SCOREBOARD", $sformatf("Mismatch: a=%0d b=%0d cin=%0d |
Expected sum=%0d, cout=%0d | Got sum=%0d, cout=%0d",
​ trans.A, trans.B, trans.Cin, expected[7:0], expected[8],
trans.S, trans.Cout))
​ end else begin
​ `uvm_info("SCOREBOARD", "Test Passed", UVM_MEDIUM)
​ end
​ endfunction

endclass
4. Debugging and Logs (5%)

●​ Effective use of UVM messaging and verbosity levels.


●​ Debugging skills and ability to interpret waveforms and logs.
●​ Error detection.
●​ Documentation of issues and resolutions.

●​ Package

import uvm_pkg::*;
`include "uvm_macros.svh"

`include "interface.sv"
`include "transection.sv"
`include "generator.sv"
`include "driver.sv"
`include "monitor.sv"
`include "agent.sv"
`include "scoreboard.sv"
`include "env.sv"
`include "test.sv"

●​ Waveform (In Testbench)

initial
​ begin
​ $dumpfile("dump.vcd");
​ $dumpvars();
​ end
5. Code Quality and Best Practices (5%)

●​ Consistency in naming conventions and coding style.


●​ Use of parameterized and reusable components.
●​ Proper comments and documentation within the code.
●​ Efficient and optimized coding practices.

EDA LInk: https://edaplayground.com/x/aUb6


Generate GDS using OpenROAD tool

In this section, the layout of the RTL code has been generated using the OpenROAD software
tool.

Technology/Platform utilized: gf180

Instructions of the config.mk

export DESIGN_NICKNAME = ripple_carry_adder_8bit


export DESIGN_NAME = ripple_carry_adder_8bit
export PLATFORM​ = gf180

export VERILOG_FILES = $(sort $(wildcard


$(DESIGN_HOME)/src/$(DESIGN_NICKNAME)/ripple_carry_adder_8bit.v))
export SDC_FILE ​ =
$(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint.sdc

#export PLACE_PINS_ARGS = -min_distance 4 -min_distance_in_tracks

export CORE_UTILIZATION = 0.5


#export CORE_ASPECT_RATIO = 1
#export CORE_MARGIN = 2

export PLACE_DENSITY = 0.1


export TNS_END_PERCENT = 100

#export EQUIVALENCE_CHECK ?= 0
#export REMOVE_CELLS_FOR_EQY = sky130_fd_sc_hd__tapvpwrvgnd*

#export FASTROUTE_TCL =
$(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/fastroute.tcl

#export REMOVE_ABC_BUFFERS = 1
Instructions of the constraint.sdc

current_design ripple_carry_adder_8bit

set clk_name v_clk


#set clk_port_name clk
set clk_period 2.5
set clk_io_pct 0.2

#set clk_port [get_ports $clk_port_name]

create_clock -name $clk_name -period $clk_period

set non_clock_inputs [lsearch -inline -all -not [all_inputs]]

set_input_delay [expr $clk_period * $clk_io_pct] -clock $clk_name $non_clock_inputs


set_output_delay [expr $clk_period * $clk_io_pct] -clock $clk_name [all_outputs]

Layout of the Design


Performance Analysis

Power Measurement:

Group Internal Switching​ Leakage ​ Total


​ Power Power ​ Power ​ Power (Watts)
----------------------------------------------------------------
Sequential 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%
Combinational 1.15e-11 1.20e-12 1.13e-08 1.13e-08 7.3%
Clock ​0.00e+00 0.00e+00 1.43e-07 1.43e-07 92.7%
Macro 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%
Pad ​0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%
----------------------------------------------------------------
Total ​ 1.15e-11 1.20e-12 1.55e-07 1.55e-07

Area Measurement:

Design area 4462 u^2 2% utilization.

Timing Information:

Delay​ Time Description


---------------------------------------------------------
0.00​ 0.00 v input external delay
0.00​ 0.00 v B[0] (in)
0.70​ 0.70 v input9/Z (gf180mcu_fd_sc_mcu9t5v0__dlyb_2)
0.09​ 0.80 ^ _20_/ZN (gf180mcu_fd_sc_mcu9t5v0__clkinv_2)
0.28​ 1.08 ^ _34_/CO (gf180mcu_fd_sc_mcu9t5v0__addf_2)
0.06​ 1.14 v _26_/ZN (gf180mcu_fd_sc_mcu9t5v0__clkinv_2)
0.29​ 1.44 v _27_/CO (gf180mcu_fd_sc_mcu9t5v0__addf_1)
0.32​ 1.76 v _28_/CO (gf180mcu_fd_sc_mcu9t5v0__addf_1)
0.29​ 2.05 v _29_/CO (gf180mcu_fd_sc_mcu9t5v0__addf_2)
0.30​ 2.35 v _30_/CO (gf180mcu_fd_sc_mcu9t5v0__addf_1)
0.31​ 2.67 v _31_/CO (gf180mcu_fd_sc_mcu9t5v0__addf_1)
0.32​ 2.98 v _32_/S (gf180mcu_fd_sc_mcu9t5v0__addf_1)
0.70​ 3.69 v _41_/Z (gf180mcu_fd_sc_mcu9t5v0__dlyb_2)
0.71​ 4.39 v output25/Z (gf180mcu_fd_sc_mcu9t5v0__dlyb_2)
0.00​ 4.39 v S[6] (out)
​ 4.39 data arrival time
---------------------------------------------------------
(Path is unconstrained)

Generated GDS
Conclusions
In this report, the RTL code of 8-bit ripple carry adder has been designed in verilog. The code is
successfully verified with the UVM with 100% test case pass. The design code is further
processed in the openROAD tool to generate its GDS using the gf180 platform. It has shown
that the generated layout consumes 155nW power which occupies 4662 sq. um area. There is
no setup and hold violations.

You might also like