Assignment -4
UVM-Based Verification of a Simple Traffic Light Controller
********interface********
interface TrafficLightInterface(input logic clk, input logic rst_n);
logic pedestrian_request;
logic [1:0] light;
logic pedestrian_light;
endinterface
******top.sv******
`include "uvm_macros.svh"
import uvm_pkg::*;
import uvm_testbench_pkg::*;
module top_tb;
logic clk, rst_n, pedestrian_request;
logic [1:0] light;
logic pedestrian_light;
TrafficLightController dut (
.clk(clk),
.rst_n(rst_n),
.pedestrian_request(pedestrian_request),
.light(light),
.pedestrian_light(pedestrian_light)
);
// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Reset logic
initial begin
rst_n = 0;
#20
rst_n = 1;
end
initial begin
run_test();
end
endmodule
**********monitor**********
class TrafficLightMonitor extends uvm_monitor;
`uvm_component_utils(TrafficLightMonitor)
uvm_analysis_port #(TrafficLightTransaction) ap;
function new(string name, uvm_component parent);
super.new(name, parent);
ap = new("ap", this);
endfunction
task run_phase(uvm_phase phase);
forever begin
// Capture DUT outputs (to be implemented)
end
endtask
endclass
**********scoreboard***************
class TrafficLightScoreboard extends uvm_scoreboard;
`uvm_component_utils(TrafficLightScoreboard)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
task analyze();
// Verify correctness of DUT outputs (to be implemented)
endtask
endclass
*******sequence***********
class TrafficLightSequence extends uvm_sequence;
`uvm_object_utils(TrafficLightSequence)
function new(string name = "TrafficLightSequence");
super.new(name);
endfunction
task body();
// Sequence logic (to be implemented)
endtask
endclass
***********agent*********
class TrafficLightAgent extends uvm_agent;
`uvm_component_utils(TrafficLightAgent)
TrafficLightDriver driver;
TrafficLightMonitor monitor;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = TrafficLightDriver::type_id::create("driver", this);
monitor = TrafficLightMonitor::type_id::create("monitor", this);
endfunction
endclass
********env**********
`include "uvm_macros.svh"
// Define the environment class
class traffic_light_env extends uvm_env;
// Define DUT (Device Under Test)
TrafficLightController dut;
// Constructor
function new(string name = "traffic_light_env");
super.new(name);
endfunction
// Build phase to instantiate the DUT
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
dut = TrafficLightController::new("dut"); // Instantiate the DUT
endfunction
// Connect phase (optional) for connecting DUT ports to testbench signals
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// Connect DUT ports to testbench components if necessary
endfunction
endclass
// Define the test class for running the test
class traffic_light_test extends uvm_test;
// Declare environment instance
traffic_light_env env;
// Constructor
function new(string name = "traffic_light_test");
super.new(name); // Call base class constructor
endfunction
// Build phase
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = traffic_light_env::new("env", this); // Instantiate the environment
endfunction
// Run phase: test execution logic
virtual task run_phase(uvm_phase phase);
// Test your DUT here by applying inputs and checking outputs
$display("Running traffic light test...");
endtask
endclass
// Top-level module to run the UVM test
module top;
initial begin
run_test(); // Run the UVM testbench
end
endmodule
****driver*********
`include "uvm_macros.svh"
import uvm_pkg::*;
import uvm_testbench_pkg::*;
class TrafficLightDriver extends uvm_driver#(traffic_light_transaction);
// Interface handle
virtual TrafficLightInterface vif;
// Constructor
function new(string name = "TrafficLightDriver", uvm_component parent =
null);
super.new(name, parent);
endfunction
// Build phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual TrafficLightInterface)::get(this, "", "vif", vif))
begin
`uvm_fatal("NOVIF", "Virtual interface not set for TrafficLightDriver")
end
endfunction
// Main driving loop
task run_phase(uvm_phase phase);
traffic_light_transaction tx;
forever begin
seq_item_port.get_next_item(tx);
// Drive inputs to DUT
vif.pedestrian_request <= tx.pedestrian_request;
// Wait for one clock cycle
@(posedge vif.clk);
// Indicate the transaction is complete
seq_item_port.item_done();
end
endtask
endclass
******test**********
class TrafficLightTest extends uvm_test;
`uvm_component_utils(TrafficLightTest)
TrafficLightEnv env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = TrafficLightEnv::type_id::create("env", this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
// Run test sequence
phase.drop_objection(this);
endtask
endclass
************system Verilog testbench***********
`timescale 1ns/1ps
module tb_TrafficLightController;
// Testbench Signals
logic clk;
logic rst_n;
logic pedestrian_request;
logic [1:0] light; // Traffic light output
logic pedestrian_light; // Pedestrian light output
// DUT Instantiation
TrafficLightController dut (
.clk(clk),
.rst_n(rst_n),
.pedestrian_request(pedestrian_request),
.light(light),
.pedestrian_light(pedestrian_light)
);
// Clock Generation
initial begin
clk = 0;
forever #5 clk = ~clk; // 10ns clock period
end
// Reset Logic
initial begin
rst_n = 0;
#15 rst_n = 1; // De-assert reset after 15ns
end
// Test Stimuli
initial begin
// Initialize inputs
pedestrian_request = 0;
// Wait for reset release
@(posedge rst_n);
// Test Case 1: Normal sequence (Green -> Yellow -> Red -> Green)
repeat (5) @(posedge clk); // Allow green light
check_light_state(2'b01); // Green state
repeat (5) @(posedge clk); // Allow yellow light
check_light_state(2'b10); // Yellow state
repeat (5) @(posedge clk); // Allow red light
check_light_state(2'b00); // Red state
// Test Case 2: Pedestrian request during red light
pedestrian_request = 1;
@(posedge clk);
check_light_state(2'b00); // Should stay in red with pedestrian light on
pedestrian_request = 0; // Clear pedestrian request
repeat (5) @(posedge clk);
// Test Case 3: Immediate transitions (simulate edge case)
rst_n = 0;
@(posedge clk);
rst_n = 1;
@(posedge clk);
check_light_state(2'b00); // Should default to red on reset
$stop;
end
// Task to check light state
task check_light_state(input [1:0] expected_light);
if (light !== expected_light) begin
$display("TEST FAILED at time %t: Expected light = %b, Observed light =
%b", $time, expected_light, light);
end else begin
$display("TEST PASSED at time %t: Light = %b", $time, light);
end
endtask
endmodule
Results: