blob: 81b6ab12b4ea7bd0d3003b2d5a331f6808d2f9ce [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
class spi_monitor extends dv_base_monitor#(
.ITEM_T (spi_item),
.CFG_T (spi_agent_cfg),
.COV_T (spi_agent_cov)
);
`uvm_component_utils(spi_monitor)
spi_item host_item;
spi_item device_item;
// Analysis port for the collected transfer.
uvm_analysis_port #(spi_item) host_analysis_port;
uvm_analysis_port #(spi_item) device_analysis_port;
`uvm_component_new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
host_analysis_port = new("host_analysis_port", this);
device_analysis_port = new("device_analysis_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
collect_trans(phase);
endtask
// collect transactions forever
virtual protected task collect_trans(uvm_phase phase);
host_item = spi_item::type_id::create("host_item", this);
device_item = spi_item::type_id::create("device_item", this);
forever begin
@(negedge cfg.vif.csb);
collect_curr_trans();
end
endtask : collect_trans
virtual protected task collect_curr_trans();
fork
begin: isolation_thread
fork
begin: csb_deassert_thread
wait(cfg.vif.csb[0] == 1'b1);
end
begin: sample_thread
// for mode 1 and 3, get the leading edges out of the way
cfg.wait_sck_edge(LeadingEdge);
forever begin
bit [7:0] host_byte; // from sio
bit [7:0] device_byte; // from sio
int which_bit;
for (int i = 0; i < 8; i++) begin
// wait for the sampling edge
cfg.wait_sck_edge(SamplingEdge);
// check sio not x or z
if (cfg.en_monitor_checks) begin
`DV_CHECK_CASE_NE(cfg.vif.sio[1:0], 2'bxx)
`DV_CHECK_CASE_NE(cfg.vif.sio[1:0], 2'bxx)
end
// sample sio[0] for tx
which_bit = cfg.host_bit_dir ? i : 7 - i;
host_byte[which_bit] = cfg.vif.sio[0];
cfg.vif.host_bit = which_bit;
cfg.vif.host_byte = host_byte;
// sample sio[1] for rx
which_bit = cfg.device_bit_dir ? i : 7 - i;
device_byte[which_bit] = cfg.vif.sio[1];
cfg.vif.device_bit = which_bit;
cfg.vif.device_byte = device_byte;
end
host_item.data.push_back(host_byte);
device_item.data.push_back(device_byte);
// sending transactions when collect a word data
if (host_item.data.size == cfg.num_bytes_per_trans_in_mon &&
device_item.data.size == cfg.num_bytes_per_trans_in_mon) begin
`uvm_info(`gfn, $sformatf("spi_monitor: host packet:\n%0s", host_item.sprint()),
UVM_HIGH)
`uvm_info(`gfn, $sformatf("spi_monitor: device packet:\n%0s", device_item.sprint()),
UVM_HIGH)
host_analysis_port.write(host_item);
device_analysis_port.write(device_item);
host_item = spi_item::type_id::create("host_item", this);
device_item = spi_item::type_id::create("device_item", this);
end
end // forever
end: sample_thread
join_any
disable fork;
end
join
endtask : collect_curr_trans
virtual task monitor_ready_to_end();
forever begin
@(cfg.vif.csb);
ok_to_end = !cfg.vif.csb;
end
endtask : monitor_ready_to_end
endclass : spi_monitor