[spi_device/dv] Fix extra cycle driving when CPHA=1
1. Remove exact cycle in spi_host_driver
2. Add checking for x/z data in monitor
diff --git a/hw/dv/sv/spi_agent/spi_agent_cfg.sv b/hw/dv/sv/spi_agent/spi_agent_cfg.sv
index c06c882..cfad135 100755
--- a/hw/dv/sv/spi_agent/spi_agent_cfg.sv
+++ b/hw/dv/sv/spi_agent/spi_agent_cfg.sv
@@ -5,8 +5,10 @@
class spi_agent_cfg extends uvm_object;
// agent cfg knobs
- bit is_active = 1'b1; // active driver or passive monitor
- bit en_cov = 1'b1; // enable coverage
+ bit is_active = 1'b1; // active driver or passive monitor
+ bit en_cov = 1'b1; // enable coverage
+ bit en_monitor_collect_trans = 1'b1; // enable monitor to collect trans on-the-fly
+ bit en_monitor_checks = 1'b1; // enable checkers in monitor
if_mode_e mode; // host or device mode
// host mode cfg knobs
diff --git a/hw/dv/sv/spi_agent/spi_host_driver.sv b/hw/dv/sv/spi_agent/spi_host_driver.sv
index fc8a11c..f38d5d0 100644
--- a/hw/dv/sv/spi_agent/spi_host_driver.sv
+++ b/hw/dv/sv/spi_agent/spi_host_driver.sv
@@ -68,16 +68,16 @@
rsp.set_id_info(req);
`uvm_info(`gfn, $sformatf("spi_host_driver: rcvd item:\n%0s", req.sprint()), UVM_HIGH)
cfg.vif.csb <= 1'b0;
- sck_pulses = req.data.size() * 8 + (cfg.sck_phase ? 1 : 0);
+ sck_pulses = req.data.size() * 8;
// for mode 1 and 3, get the leading edges out of the way
cfg.wait_sck_edge(LeadingEdge);
// drive data
for (int i = 0; i < req.data.size(); i++) begin
- bit [7:0] host_byte;
- bit [7:0] device_byte;
- int which_bit;
+ logic [7:0] host_byte;
+ logic [7:0] device_byte;
+ int which_bit;
host_byte = req.data[i];
for (int j = 0; j < 8; j++) begin
// drive mosi early so that it is stable at the sampling edge
@@ -88,7 +88,7 @@
which_bit = cfg.device_bit_dir ? j : 7 - j;
device_byte[which_bit] = cfg.vif.miso;
// wait for driving edge to complete 1 cycle
- cfg.wait_sck_edge(DrivingEdge);
+ if (i != req.data.size() - 1 || j != 7) cfg.wait_sck_edge(DrivingEdge);
end
rsp.data[i] = device_byte;
end
diff --git a/hw/dv/sv/spi_agent/spi_monitor.sv b/hw/dv/sv/spi_agent/spi_monitor.sv
index cf17cbe..e8a1ea2 100755
--- a/hw/dv/sv/spi_agent/spi_monitor.sv
+++ b/hw/dv/sv/spi_agent/spi_monitor.sv
@@ -6,6 +6,8 @@
`uvm_component_utils(spi_monitor)
spi_agent_cfg cfg;
+ spi_item host_item;
+ spi_item device_item;
// Analysis port for the collected transfer.
uvm_analysis_port #(spi_item) host_analysis_port;
@@ -25,18 +27,18 @@
// 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);
phase.raise_objection(this);
- collect_curr_trans();
+ if (cfg.en_monitor_collect_trans) collect_curr_trans();
phase.drop_objection(this);
end
endtask
virtual protected task collect_curr_trans();
- spi_item host_item = spi_item::type_id::create("host_item", this);
- spi_item device_item = spi_item::type_id::create("device_item", this);
-
// for mode 1 and 3, get the leading edges out of the way
cfg.wait_sck_edge(LeadingEdge);
@@ -53,6 +55,13 @@
for (int i = 0; i < 8; i++) begin
// wait for the sampling edge
cfg.wait_sck_edge(SamplingEdge);
+ // check mosi/miso not x or z
+ if (cfg.en_monitor_checks) begin
+ `DV_CHECK_CASE_NE(cfg.vif.mosi, 1'bx)
+ `DV_CHECK_CASE_NE(cfg.vif.mosi, 1'bz)
+ `DV_CHECK_CASE_NE(cfg.vif.miso, 1'bx)
+ `DV_CHECK_CASE_NE(cfg.vif.miso, 1'bz)
+ end
// sample mosi
which_bit = cfg.host_bit_dir ? i : 7 - i;
host_byte[which_bit] = cfg.vif.mosi;