blob: 3436c23293e5afad25c49d476523aa834772b4c1 [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_agent_cfg extends dv_base_agent_cfg;
// agent cfg knobs
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
time sck_period_ps = 50_000; // 20MHz
bit sck_polarity; // aka CPOL
bit sck_phase; // aka CPHA
bit host_bit_dir; // 1 - lsb -> msb, 0 - msb -> lsb
bit device_bit_dir; // 1 - lsb -> msb, 0 - msb -> lsb
bit sck_on; // keep sck on
// how many bytes monitor samples per transaction
int num_bytes_per_trans_in_mon = 4;
// enable randomly injecting extra delay between 2 sck/word
bit en_extra_dly_btw_sck;
uint max_extra_dly_ns_btw_sck = 100; // small delay to avoid transfer timeout
uint extra_dly_chance_pc_btw_sck = 5; // percentage of extra delay btw each spi clock edge
// Note: can't handle word delay, if a word is splitted into multiple csb.
// In that case, control delay in seq level
bit en_extra_dly_btw_word;
uint max_extra_dly_ns_btw_word = 1000; // no timeout btw word
uint extra_dly_chance_pc_btw_word = 5; // percentage of extra delay btw each word
// interface handle used by driver, monitor & the sequencer
virtual spi_if vif;
`uvm_object_utils_begin(spi_agent_cfg)
`uvm_field_int (is_active, UVM_DEFAULT)
`uvm_field_int (en_cov, UVM_DEFAULT)
`uvm_field_enum(if_mode_e, mode, UVM_DEFAULT)
`uvm_field_int (sck_period_ps, UVM_DEFAULT)
`uvm_field_int (sck_polarity, UVM_DEFAULT)
`uvm_field_int (sck_phase, UVM_DEFAULT)
`uvm_field_int (host_bit_dir, UVM_DEFAULT)
`uvm_field_int (device_bit_dir, UVM_DEFAULT)
`uvm_field_int (en_extra_dly_btw_sck, UVM_DEFAULT)
`uvm_field_int (max_extra_dly_ns_btw_sck, UVM_DEFAULT)
`uvm_field_int (extra_dly_chance_pc_btw_sck, UVM_DEFAULT)
`uvm_field_int (en_extra_dly_btw_word, UVM_DEFAULT)
`uvm_field_int (max_extra_dly_ns_btw_word, UVM_DEFAULT)
`uvm_field_int (extra_dly_chance_pc_btw_word, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new
virtual task wait_sck_edge(sck_edge_type_e sck_edge_type);
bit [1:0] sck_mode = {sck_polarity, sck_phase};
bit wait_posedge;
// sck polarity slk_phase mode
// 0 0 0: sample at leading podedge (drive @ prev negedge)
// 1 0 2: sample at leading negedge (drive @ prev posedge)
// 0 1 1: sample at trailing negedge (drive @ curr posedge)
// 1 1 3: sample at trailing posedge (drive @ curr negedge)
case (sck_edge_type)
LeadingEdge: begin
// wait for leading edge applies to mode 1 and 3 only
if (sck_mode inside {2'b00, 2'b10}) return;
if (sck_mode == 2'b01) wait_posedge = 1'b1;
end
DrivingEdge: wait_posedge = (sck_mode inside {2'b01, 2'b10});
SamplingEdge: wait_posedge = (sck_mode inside {2'b00, 2'b11});
endcase
if (wait_posedge) @(posedge vif.sck);
else @(negedge vif.sck);
endtask
endclass