This commit is contained in:
2026-06-12 07:53:32 +02:00
commit 59e71f3297
259 changed files with 29010 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
/****************************************************************************
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
FILE i2c_slave_agent.sv
DESCRIPTION slave agent
****************************************************************************/
`ifndef I2C_SLAVE_AGENT_SV
`define I2C_SLAVE_AGENT_SV
typedef uvm_sequencer #(i2c_transaction) i2c_slave_sequencer;
/**
* Class: i2c_slave_agent
*/
class i2c_slave_agent extends uvm_agent;
// configuration object
i2c_slave_config cfg;
// components
i2c_slave_driver drv;
i2c_slave_sequencer seqr;
i2c_monitor mon;
// UVM factory registration
`uvm_component_utils_begin(i2c_slave_agent)
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
`uvm_component_utils_end
// new - constructor
function new(string name = "i2c_slave_agent", uvm_component parent = null);
super.new(name, parent);
endfunction : new
// UVM build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// get configuration object from db
if(!uvm_config_db#(i2c_slave_config)::get(this, "", "i2c_slave_config", cfg))
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
// create driver and sequencer if agent is active
if(cfg.is_active == UVM_ACTIVE) begin
seqr = i2c_slave_sequencer::type_id::create("seqr", this);
drv = i2c_slave_driver::type_id::create("drv", this);
end
// always create monitor
mon = i2c_monitor::type_id::create("mon", this);
endfunction : build_phase
// UVM connect_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// connect driver and sequencer if agent is active
if(cfg.is_active == UVM_ACTIVE) begin
drv.seq_item_port.connect(seqr.seq_item_export);
end
endfunction : connect_phase
endclass : i2c_slave_agent
`endif

View File

@@ -0,0 +1,41 @@
/****************************************************************************
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
FILE i2c_slave_config.sv
DESCRIPTION slave configuration object
****************************************************************************/
`ifndef I2C_SLAVE_CONFIG_SV
`define I2C_SLAVE_CONFIG_SV
/**
* Class: i2c_slave_config
*/
class i2c_slave_config extends uvm_object;
// is agent active or passive
uvm_active_passive_enum is_active = UVM_ACTIVE;
// checks and coverage control
bit has_checks = 1;
bit has_coverage = 1;
// UVM factory registration
`uvm_object_utils_begin(i2c_slave_config)
`uvm_field_enum(uvm_active_passive_enum, is_active, UVM_DEFAULT)
`uvm_field_int(has_checks, UVM_DEFAULT)
`uvm_field_int(has_coverage, UVM_DEFAULT)
`uvm_object_utils_end
// new - constructor
function new(string name = "i2c_slave_config");
super.new(name);
endfunction : new
endclass : i2c_slave_config
`endif

View File

@@ -0,0 +1,148 @@
/****************************************************************************
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
FILE i2c_slave_driver.sv
DESCRIPTION drives slave response
****************************************************************************/
`ifndef I2C_SLAVE_DRIVER_SV
`define I2C_SLAVE_DRIVER_SV
/**
* Class: i2c_slave_driver
*/
class i2c_slave_driver extends uvm_driver #(i2c_transaction, i2c_transaction);
// i2c virtual interface
virtual i2c_if vif;
// configuration
i2c_slave_config cfg;
// UVM factory registration
`uvm_component_utils_begin(i2c_slave_driver)
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
`uvm_component_utils_end
// new - constructor
function new(string name = "i2c_slave_driver", uvm_component parent = null);
super.new(name, parent);
endfunction : new
// UVM build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// get configuration object from db
if(!uvm_config_db#(i2c_slave_config)::get(this, "", "i2c_slave_config", cfg))
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
endfunction: build_phase
// UVM connect_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// get interface from db
if(!uvm_config_db#(virtual i2c_if)::get(this, "", "i2c_if", vif))
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
endfunction : connect_phase
// additional class methods
extern virtual task run_phase(uvm_phase phase);
extern virtual task reset();
extern virtual task get_and_drive();
extern virtual task drive_tr(i2c_transaction tr);
endclass : i2c_slave_driver
// UVM run_phase
task i2c_slave_driver::run_phase(uvm_phase phase);
reset(); // init.
forever begin
fork
@(posedge vif.rst); // reset is active low
// threads killed at reset
get_and_drive();
join_any
disable fork;
reset();
end
endtask : run_phase
// reset signals
task i2c_slave_driver::reset();
`uvm_info(get_type_name(), "Reset observed", UVM_MEDIUM)
vif.scl <= 1'b1;
vif.sda <= 1'b1;
@(negedge vif.rst); // reset dropped
endtask : reset
// sequencer/driver handshake
task i2c_slave_driver::get_and_drive();
forever begin
seq_item_port.get_next_item(req);
drive_tr(req);
seq_item_port.item_done();
end
endtask : get_and_drive
// drive transaction
task i2c_slave_driver::drive_tr (i2c_transaction tr);
// wait for the master to initiate the transaction
@(negedge vif.sda_wire iff vif.scl_wire === 1'b1); // start condition
// address
tr.addr = 0;
repeat(ADDR_WIDTH) begin
@(posedge vif.scl_wire);
#1;
tr.addr = {tr.addr[ADDR_WIDTH - 2 : 0], vif.sda_wire};
end
// read / write bit
@(posedge vif.scl_wire);
#1;
tr.dir = i2c_direction_enum'(vif.sda_wire);
// drive addr ack / nack
@(posedge vif.scl_wire);
vif.sda = tr.addr_ack;
// recieved ack - continue
if(tr.addr_ack == I2C_ACK) begin
if(tr.dir == I2C_WRITE) begin
// data
repeat(DATA_WIDTH) begin
@(posedge vif.scl_wire);
#1;
tr.data = {tr.data[DATA_WIDTH - 2 : 0], vif.sda_wire};
end
// drive data ack / nack
@(posedge vif.scl_wire);
vif.sda <= tr.data_ack;
end
else begin // READ
// drive data - msb first
for(int i = DATA_WIDTH; i > 0; --i) begin
@(posedge vif.scl_wire);
vif.sda <= tr.data[i-1];
end
// read data ack / nack
@(posedge vif.scl_wire);
#1;
if(vif.sda_wire === 1'b0) tr.data_ack = I2C_ACK;
else tr.data_ack = I2C_NACK;
end
end
`uvm_info(get_type_name(), $sformatf("i2c Finished Driving tr \n%s", tr.sprint()), UVM_HIGH)
endtask : drive_tr
`endif

View File

@@ -0,0 +1,31 @@
/****************************************************************************
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
FILE i2c_slave_base_seq.sv
DESCRIPTION base sequence to be extended by other sequences
****************************************************************************/
`ifndef I2C_SLAVE_BASE_SEQ_SV
`define I2C_SLAVE_BASE_SEQ_SV
/**
* Class: i2c_slave_base_seq
*/
class i2c_slave_base_seq extends uvm_sequence #(i2c_transaction, i2c_transaction);
// UVM factory registration
`uvm_object_utils(i2c_slave_base_seq)
// new - constructor
function new(string name = "i2c_slave_base_seq");
super.new(name);
endfunction : new
endclass : i2c_slave_base_seq
`endif

View File

@@ -0,0 +1,18 @@
/****************************************************************************
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
FILE i2c_slave_seq_lib.sv
DESCRIPTION sequence includes
****************************************************************************/
`ifndef I2C_SLAVE_SEQ_LIB_SV
`define I2C_SLAVE_SEQ_LIB_SV
`include "slave/sequences/i2c_slave_base_seq.sv"
`include "slave/sequences/i2c_slave_simple_seq.sv"
`endif

View File

@@ -0,0 +1,38 @@
/****************************************************************************
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
FILE i2c_slave_simple_seq.sv
DESCRIPTION simple sequence; always respond with random data
****************************************************************************/
`ifndef I2C_SLAVE_SIMPLE_SEQ_SV
`define I2C_SLAVE_SIMPLE_SEQ_SV
/**
* Class: i2c_slave_simple_seq
*/
class i2c_slave_simple_seq extends i2c_slave_base_seq;
// UVM factory registration
`uvm_object_utils(i2c_slave_simple_seq)
// new - constructor
function new(string name = "i2c_slave_simple_seq");
super.new(name);
endfunction : new
// sequence generation logic in body
virtual task body();
forever begin
`uvm_do(req)
end
endtask : body
endclass : i2c_slave_simple_seq
`endif