init
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|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_master_agent.sv
|
||||
|
||||
DESCRIPTION master agent
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef I2C_MASTER_AGENT_SV
|
||||
`define I2C_MASTER_AGENT_SV
|
||||
|
||||
typedef uvm_sequencer #(i2c_transaction) i2c_master_sequencer;
|
||||
|
||||
/*
|
||||
* Class: i2c_master_agent
|
||||
*/
|
||||
class i2c_master_agent extends uvm_agent;
|
||||
|
||||
// configuration object
|
||||
i2c_master_config cfg;
|
||||
|
||||
// components
|
||||
i2c_monitor mon;
|
||||
i2c_master_driver drv;
|
||||
i2c_master_sequencer seqr;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(i2c_master_agent)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "i2c_master_agent", uvm_component parent);
|
||||
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_master_config)::get(this, "", "i2c_master_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_master_sequencer::type_id::create("seqr", this);
|
||||
drv = i2c_master_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_master_agent
|
||||
|
||||
`endif
|
||||
|
||||
@@ -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_master_config.sv
|
||||
|
||||
DESCRIPTION contains main and default configurations
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef I2C_MASTER_CONFIG_SV
|
||||
`define I2C_MASTER_CONFIG_SV
|
||||
|
||||
/*
|
||||
* Class: i2c_master_config
|
||||
*/
|
||||
class i2c_master_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_master_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_master_config");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
endclass : i2c_master_config
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|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_master_driver.sv
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef I2C_MASTER_DRIVER_SV
|
||||
`define I2C_MASTER_DRIVER_SV
|
||||
|
||||
/*
|
||||
* Class: i2c_master_driver
|
||||
*/
|
||||
class i2c_master_driver extends uvm_driver #(i2c_transaction);
|
||||
|
||||
// i2c virtual interface
|
||||
virtual i2c_if vif;
|
||||
|
||||
// configuration
|
||||
i2c_master_config cfg;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(i2c_master_driver)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "i2c_master_driver", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
virtual function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(i2c_master_config)::get(this, "*", "i2c_master_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
endfunction: build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
virtual 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 drive_transaction(i2c_transaction tr);
|
||||
extern virtual task drive_start(i2c_transaction tr);
|
||||
extern virtual task drive_stop(i2c_transaction tr);
|
||||
extern virtual task drive_bit(input logic bit_to_drive, input int unsigned scl_period);
|
||||
extern virtual task read_bit(output logic bit_read, input int unsigned scl_period);
|
||||
|
||||
endclass : i2c_master_driver
|
||||
|
||||
// UVM run_phase
|
||||
task i2c_master_driver::run_phase(uvm_phase phase);
|
||||
reset(); // init
|
||||
forever begin
|
||||
fork
|
||||
@(posedge vif.rst); // reset is active high
|
||||
forever begin
|
||||
seq_item_port.get_next_item(req);
|
||||
drive_start(req);
|
||||
drive_transaction(req);
|
||||
drive_stop(req);
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
join_any
|
||||
disable fork;
|
||||
reset();
|
||||
end
|
||||
|
||||
endtask : run_phase
|
||||
|
||||
// reset signals
|
||||
task i2c_master_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
|
||||
|
||||
// drive start condition
|
||||
task i2c_master_driver::drive_start(i2c_transaction tr);
|
||||
|
||||
@(posedge vif.clk); // sync
|
||||
|
||||
vif.scl <= 1'b1;
|
||||
vif.sda <= 1'b0;
|
||||
|
||||
repeat(tr.start_hold) @(posedge vif.clk);
|
||||
|
||||
vif.scl <= 1'b1;
|
||||
repeat(tr.scl_period / 2) @(posedge vif.clk);
|
||||
vif.scl <= 1'b0;
|
||||
repeat(tr.scl_period / 4) @(posedge vif.clk);
|
||||
|
||||
endtask : drive_start
|
||||
|
||||
// drive stop condition
|
||||
task i2c_master_driver::drive_stop(i2c_transaction tr);
|
||||
|
||||
@(posedge vif.clk); // sync
|
||||
|
||||
vif.sda <= 1'b0;
|
||||
|
||||
repeat(tr.scl_period / 2) @(posedge vif.clk);
|
||||
vif.scl <= 1'b1;
|
||||
|
||||
repeat(tr.stop_setup) @(posedge vif.clk);
|
||||
vif.sda <= 1'b1;
|
||||
|
||||
repeat(tr.delay) @(posedge vif.clk);
|
||||
|
||||
endtask : drive_stop
|
||||
|
||||
// drive transaction
|
||||
task i2c_master_driver::drive_transaction(i2c_transaction tr);
|
||||
logic ack;
|
||||
|
||||
// drive address (msb first)
|
||||
for(int i = ADDR_WIDTH; i > 0; --i) begin
|
||||
drive_bit(tr.addr[i-1], tr.scl_period);
|
||||
end
|
||||
|
||||
// drive direction
|
||||
drive_bit(tr.dir, tr.scl_period);
|
||||
|
||||
// get ack from slave
|
||||
read_bit(ack, tr.scl_period);
|
||||
if(ack === 1'b0) tr.addr_ack = I2C_ACK;
|
||||
else tr.addr_ack = I2C_NACK;
|
||||
|
||||
// recieved ack - continue
|
||||
if(tr.addr_ack == 1'b0) begin
|
||||
if(tr.dir == I2C_WRITE) begin
|
||||
for(int i = DATA_WIDTH; i > 0; --i) begin
|
||||
drive_bit(tr.data[i - 1], tr.scl_period);
|
||||
end
|
||||
// get ack from slave
|
||||
read_bit(ack, tr.scl_period);
|
||||
if(ack === 1'b0) tr.data_ack = I2C_ACK;
|
||||
else tr.data_ack = I2C_NACK;
|
||||
end
|
||||
else begin // READ
|
||||
// get data - msb first
|
||||
for(int i = DATA_WIDTH; i > 0; --i) begin
|
||||
read_bit(tr.data[i-1], tr.scl_period);
|
||||
end
|
||||
|
||||
// ack or nack
|
||||
drive_bit(tr.data_ack, tr.scl_period);
|
||||
end
|
||||
end
|
||||
|
||||
`uvm_info(get_type_name(), $sformatf("I2C Finished Driving tr \n%s", tr.sprint()), UVM_HIGH)
|
||||
|
||||
endtask : drive_transaction
|
||||
|
||||
// drive one bit
|
||||
task i2c_master_driver::drive_bit(input logic bit_to_drive, input int unsigned scl_period);
|
||||
|
||||
vif.sda <= bit_to_drive;
|
||||
repeat(scl_period / 4) @(posedge vif.clk);
|
||||
vif.scl <= 1'b1;
|
||||
repeat(scl_period / 2) @(posedge vif.clk);
|
||||
vif.scl <= 1'b0;
|
||||
repeat(scl_period / 4) @(posedge vif.clk);
|
||||
|
||||
endtask : drive_bit
|
||||
|
||||
// read one bit
|
||||
task i2c_master_driver::read_bit(output logic bit_read, input int unsigned scl_period);
|
||||
|
||||
vif.sda <= 1'bZ;
|
||||
repeat(scl_period / 4) @(posedge vif.clk);
|
||||
vif.scl <= 1'b1;
|
||||
repeat(scl_period / 4) @(posedge vif.clk);
|
||||
bit_read = vif.sda_wire;
|
||||
repeat(scl_period / 4) @(posedge vif.clk);
|
||||
vif.scl <= 1'b0;
|
||||
repeat(scl_period / 4) @(posedge vif.clk);
|
||||
|
||||
endtask : read_bit
|
||||
|
||||
`endif
|
||||
|
||||
@@ -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_master_base_seq.sv
|
||||
|
||||
DESCRIPTION base sequence to be extended by other sequences
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef I2C_MASTER_BASE_SEQ_SV
|
||||
`define I2C_MASTER_BASE_SEQ_SV
|
||||
|
||||
/*
|
||||
* Class: i2c_master_base_seq
|
||||
*/
|
||||
class i2c_master_base_seq extends uvm_sequence #(i2c_transaction);
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(i2c_master_base_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "i2c_master_base_seq");
|
||||
super.new(name);
|
||||
endfunction: new
|
||||
|
||||
endclass: i2c_master_base_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -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_master_seq_lib.sv
|
||||
|
||||
DESCRIPTION sequence includes
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef I2C_MASTER_SEQ_LIB_SV
|
||||
`define I2C_MASTER_SEQ_LIB_SV
|
||||
|
||||
`include "master/sequences/i2c_master_base_seq.sv"
|
||||
`include "master/sequences/i2c_master_simple_seq.sv"
|
||||
|
||||
`endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|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_master_simple_seq.sv
|
||||
|
||||
DESCRIPTION simple sequence; random transactions
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef I2C_MASTER_SIMPLE_SEQ_SV
|
||||
`define I2C_MASTER_SIMPLE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: i2c_master_simple_seq
|
||||
*/
|
||||
class i2c_master_simple_seq extends i2c_master_base_seq;
|
||||
|
||||
rand int unsigned num_of_tr;
|
||||
|
||||
// constraints
|
||||
constraint num_of_tr_cst { num_of_tr inside {[1 : 10]};}
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(i2c_master_simple_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "i2c_master_simple_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
repeat(num_of_tr) begin
|
||||
`uvm_do(req)
|
||||
end
|
||||
endtask : body
|
||||
|
||||
endclass : i2c_master_simple_seq
|
||||
|
||||
`endif
|
||||
Reference in New Issue
Block a user