[i2c, dv] Updates for both i2c_agent and i2c_sanity
1) i2c_agent
- Add knob to control target address mode (7-bit: current support, 10-bit: RFU)
- Update agent to support re-programming registers from test
- Remove unused macros
2) i2c_sanity
- Support re-programming timing regs during tranceiving tran in i2c_sanity
- Add knob to control target address mode
Signed-off-by: Tung Hoang <tung.hoang.290780@gmail.com>
diff --git a/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv b/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv
index 6c9fc7d..ff7dcec 100644
--- a/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv
+++ b/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv
@@ -4,13 +4,28 @@
class i2c_agent_cfg extends dv_base_agent_cfg;
- bit en_monitor = 1'b1; // enable monitor
+ bit en_monitor = 1'b1; // enable monitor
+ i2c_target_addr_mode_e target_addr_mode = Addr7BitMode;
timing_cfg_t timing_cfg;
+
virtual i2c_if vif;
`uvm_object_utils_begin(i2c_agent_cfg)
- `uvm_field_int(en_monitor, UVM_DEFAULT)
+ `uvm_field_int(en_monitor, UVM_DEFAULT)
+ `uvm_field_enum(i2c_target_addr_mode_e, target_addr_mode, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tSetupStart, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tHoldStart, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tClockStart, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tClockLow, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tSetupBit, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tClockPulse, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tHoldBit, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tClockStop, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tSetupStop, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tHoldStop, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.tTimeOut, UVM_DEFAULT)
+ `uvm_field_int(timing_cfg.enbTimeOut, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new
diff --git a/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv b/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv
index 7e6ba45..df6ebc8 100644
--- a/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv
+++ b/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv
@@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
+// I2C specification: https://www.nxp.com/docs/en/user-guide/UM10204.pdf
+
package i2c_agent_pkg;
// dep packages
import uvm_pkg::*;
@@ -12,10 +14,6 @@
`include "uvm_macros.svh"
`include "dv_macros.svh"
- // local macros
- parameter uint I2C_ADDR_WIDTH = 7;
- parameter uint I2C_DATA_WIDTH = 8;
-
typedef enum logic [3:0] {
None, DevAck, RdData
} drv_type_e;
@@ -37,6 +35,11 @@
bit [30:0] tTimeOut;
} timing_cfg_t;
+ typedef enum int {
+ Addr7BitMode = 7,
+ Addr10BitMode = 10
+ } i2c_target_addr_mode_e;
+
// forward declare classes to allow typedefs below
typedef class i2c_item;
typedef class i2c_agent_cfg;
diff --git a/hw/dv/sv/i2c_agent/i2c_device_driver.sv b/hw/dv/sv/i2c_agent/i2c_device_driver.sv
index a9e9cd9..362880e 100644
--- a/hw/dv/sv/i2c_agent/i2c_device_driver.sv
+++ b/hw/dv/sv/i2c_agent/i2c_device_driver.sv
@@ -6,11 +6,9 @@
`uvm_component_utils(i2c_device_driver)
`uvm_component_new
- bit [I2C_DATA_WIDTH-1:0] data;
+ rand bit [7:0] rd_data;
- rand bit [I2C_DATA_WIDTH-1:0] rd_data;
-
- constraint rd_data_c { rd_data inside {[0 : ((1 << I2C_DATA_WIDTH) - 1)]}; }
+ constraint rd_data_c { rd_data inside {[0 : 127]}; }
virtual task get_and_drive();
i2c_item rsp_item;
@@ -26,7 +24,7 @@
end
RdData: begin
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(rd_data)
- for (int i = I2C_DATA_WIDTH-1; i >= 0; i--) begin
+ for (int i = 7; i >= 0; i--) begin
cfg.vif.device_send_bit(cfg.timing_cfg, rd_data[i]);
end
`uvm_info(`gfn, $sformatf("driver, trans %0d, byte %0d %0b",
diff --git a/hw/dv/sv/i2c_agent/i2c_if.sv b/hw/dv/sv/i2c_agent/i2c_if.sv
index 46c8696..a96a1f8 100644
--- a/hw/dv/sv/i2c_agent/i2c_if.sv
+++ b/hw/dv/sv/i2c_agent/i2c_if.sv
@@ -21,7 +21,7 @@
repeat (dly) @(posedge clk_i);
endtask : wait_for_dly
- task automatic wait_for_host_start(timing_cfg_t tc);
+ task automatic wait_for_host_start(ref timing_cfg_t tc);
forever begin
@(negedge sda_i);
wait_for_dly(tc.tHoldStart);
@@ -31,8 +31,8 @@
end
endtask: wait_for_host_start
- task automatic wait_for_host_rstart(timing_cfg_t tc,
- output bit rstart);
+ task automatic wait_for_host_rstart(ref timing_cfg_t tc,
+ output bit rstart);
rstart = 1'b0;
forever begin
@(posedge scl_i && sda_i);
@@ -48,8 +48,8 @@
end
endtask: wait_for_host_rstart
- task automatic wait_for_host_stop(timing_cfg_t tc,
- output bit stop);
+ task automatic wait_for_host_stop(ref timing_cfg_t tc,
+ output bit stop);
stop = 1'b0;
forever begin
@(posedge scl_i);
@@ -76,7 +76,7 @@
join
endtask: wait_for_host_stop_or_rstart
- task automatic wait_for_host_ack(timing_cfg_t tc);
+ task automatic wait_for_host_ack(ref timing_cfg_t tc);
@(negedge sda_i);
wait_for_dly(tc.tClockLow + tc.tSetupBit);
forever begin
@@ -89,7 +89,7 @@
wait_for_dly(tc.tHoldBit);
endtask: wait_for_host_ack
- task automatic wait_for_host_nack(timing_cfg_t tc);
+ task automatic wait_for_host_nack(ref timing_cfg_t tc);
@(negedge sda_i);
wait_for_dly(tc.tClockLow + tc.tSetupBit);
forever begin
@@ -124,7 +124,7 @@
join
endtask: wait_for_host_ack_or_nack
- task automatic wait_for_device_ack(timing_cfg_t tc);
+ task automatic wait_for_device_ack(ref timing_cfg_t tc);
@(negedge sda_o && scl_o);
wait_for_dly(tc.tSetupBit);
forever begin
@@ -137,8 +137,10 @@
wait_for_dly(tc.tHoldBit);
endtask: wait_for_device_ack
- task automatic device_send_ack(timing_cfg_t tc);
+ task automatic device_send_ack(ref timing_cfg_t tc);
device_stretch_clk(tc);
+ sda_o = 1'b1;
+ wait_for_dly(tc.tClockLow);
sda_o = 1'b0;
wait_for_dly(tc.tSetupBit);
@(posedge scl_i);
@@ -146,8 +148,9 @@
sda_o = 1'b1;
endtask: device_send_ack
- task automatic device_send_bit(timing_cfg_t tc,
- bit bit_i);
+ task automatic device_send_bit(ref timing_cfg_t tc,
+ input bit bit_i);
+ device_stretch_clk(tc);
sda_o = 1'b1;
wait_for_dly(tc.tClockLow);
sda_o = bit_i;
@@ -157,7 +160,7 @@
sda_o = 1'b1;
endtask: device_send_bit
- task automatic device_stretch_clk(timing_cfg_t tc);
+ task automatic device_stretch_clk(ref timing_cfg_t tc);
if (tc.enbTimeOut) begin
scl_o = 1'b0;
wait_for_dly(tc.tTimeOut);
@@ -165,9 +168,9 @@
end
endtask : device_stretch_clk
- task automatic get_bit_data(string src = "host",
- timing_cfg_t tc,
- output bit bit_o);
+ task automatic get_bit_data(string src = "host",
+ ref timing_cfg_t tc,
+ output bit bit_o);
wait_for_dly(tc.tClockLow + tc.tSetupBit);
@(posedge scl_i);
bit_o = (src == "host") ? sda_i : sda_o;
diff --git a/hw/dv/sv/i2c_agent/i2c_item.sv b/hw/dv/sv/i2c_agent/i2c_item.sv
index 001f447..c7301a4 100644
--- a/hw/dv/sv/i2c_agent/i2c_item.sv
+++ b/hw/dv/sv/i2c_agent/i2c_item.sv
@@ -5,8 +5,8 @@
class i2c_item extends uvm_sequence_item;
// transaction data part
- bit [I2C_DATA_WIDTH-1:0] data_q[$];
- bit [I2C_ADDR_WIDTH-1:0] addr;
+ bit [7:0] data_q[$];
+ bit [9:0] addr; // enough to support both 7 & 10-bit target address
int tran_id;
int num_data;
bus_op_e bus_op;
diff --git a/hw/dv/sv/i2c_agent/i2c_monitor.sv b/hw/dv/sv/i2c_agent/i2c_monitor.sv
index 6903306..4706a4f 100644
--- a/hw/dv/sv/i2c_agent/i2c_monitor.sv
+++ b/hw/dv/sv/i2c_agent/i2c_monitor.sv
@@ -13,8 +13,8 @@
uvm_analysis_port #(i2c_item) wr_item_port; // used to send complete wr_tran to sb
uvm_analysis_port #(i2c_item) rd_item_port; // used to send complete rd_tran to sb
- local bit [I2C_DATA_WIDTH-1:0] mon_data;
- local uint num_dut_tran;
+ local bit [7:0] mon_data;
+ local uint num_dut_tran = 0;
`uvm_component_new
function void build_phase(uvm_phase phase);
@@ -22,7 +22,6 @@
mon_item_port = new("mon_item_port", this);
wr_item_port = new("wr_item_port", this);
rd_item_port = new("rd_item_port", this);
- num_dut_tran = 0;
endfunction : build_phase
virtual task wait_for_reset_done();
@@ -39,92 +38,93 @@
// collect transactions forever
virtual protected task collect_thread(uvm_phase phase);
i2c_item complete_item;
- i2c_item partial_item;
+ i2c_item mon_dut_item;
- partial_item = i2c_item::type_id::create("partial_item", this);
+ mon_dut_item = i2c_item::type_id::create("mon_dut_item", this);
forever begin
if (cfg.en_monitor == 1'b1) begin
- if (partial_item.stop || (!partial_item.stop && !partial_item.start && !partial_item.rstart)) begin
+ if (mon_dut_item.stop || (!mon_dut_item.stop && !mon_dut_item.start && !mon_dut_item.rstart)) begin
cfg.vif.wait_for_host_start(cfg.timing_cfg);
`uvm_info(`gfn, $sformatf("monitor, detect HOST START"), UVM_DEBUG)
end else begin
- partial_item.rstart = 1'b1;
+ mon_dut_item.rstart = 1'b1;
end
num_dut_tran++;
- partial_item.start = 1'b1;
+ mon_dut_item.start = 1'b1;
// issue address then rd/wr data
- address_thread(partial_item, num_dut_tran);
- if (partial_item.bus_op == BusOpRead) read_thread(partial_item);
- else write_thread(partial_item);
+ address_thread(mon_dut_item, num_dut_tran);
+ if (mon_dut_item.bus_op == BusOpRead) read_thread(mon_dut_item);
+ else write_thread(mon_dut_item);
// send rsp_item to scoreboard
- `downcast(complete_item, partial_item.clone());
+ `downcast(complete_item, mon_dut_item.clone());
complete_item.stop = 1'b1;
if (complete_item.bus_op == BusOpRead) rd_item_port.write(complete_item);
- else wr_item_port.write(complete_item);
- `uvm_info(`gfn, $sformatf("\nmonitor, complete_item\n%s", complete_item.sprint()), UVM_DEBUG)
- partial_item.clear_data();
+ else wr_item_port.write(complete_item);
+ `uvm_info(`gfn, $sformatf("\nmonitor, complete_item\n%s",
+ complete_item.sprint()), UVM_DEBUG)
+ mon_dut_item.clear_data();
end begin
@(cfg.vif.clk_i);
end
end
endtask: collect_thread
- virtual protected task address_thread(i2c_item partial_item, uint id);
+ virtual protected task address_thread(i2c_item mon_dut_item, uint id);
i2c_item clone_item;
bit rw_req = 1'b0;
-
+
// sample address and r/w bit
- partial_item.tran_id = id;
- for (int i = I2C_ADDR_WIDTH-1; i >= 0; i--) begin
- cfg.vif.get_bit_data("host", cfg.timing_cfg, partial_item.addr[i]);
+ mon_dut_item.tran_id = id;
+ for (int i = cfg.target_addr_mode - 1; i >= 0; i--) begin
+ cfg.vif.get_bit_data("host", cfg.timing_cfg, mon_dut_item.addr[i]);
end
cfg.vif.get_bit_data("host", cfg.timing_cfg, rw_req);
- partial_item.bus_op = (rw_req) ? BusOpRead : BusOpWrite;
+ mon_dut_item.bus_op = (rw_req) ? BusOpRead : BusOpWrite;
// get ack after transmitting address
- partial_item.drv_type = DevAck;
- `downcast(clone_item, partial_item.clone());
+ mon_dut_item.drv_type = DevAck;
+ `downcast(clone_item, mon_dut_item.clone());
mon_item_port.write(clone_item);
cfg.vif.wait_for_device_ack(cfg.timing_cfg);
`uvm_info(`gfn, $sformatf("monitor, address, detect TARGET ACK"), UVM_DEBUG)
endtask : address_thread
- virtual protected task read_thread(i2c_item partial_item);
+ virtual protected task read_thread(i2c_item mon_dut_item);
i2c_item clone_item;
- partial_item.stop = 1'b0;
- partial_item.rstart = 1'b0;
- partial_item.ack = 1'b0;
- partial_item.nack = 1'b0;
- while (!partial_item.stop && !partial_item.rstart) begin
+ mon_dut_item.stop = 1'b0;
+ mon_dut_item.rstart = 1'b0;
+ mon_dut_item.ack = 1'b0;
+ mon_dut_item.nack = 1'b0;
+ while (!mon_dut_item.stop && !mon_dut_item.rstart) begin
fork
begin : iso_fork_read
fork
begin
// ask driver response read data
- partial_item.drv_type = RdData;
- `downcast(clone_item, partial_item.clone());
+ mon_dut_item.drv_type = RdData;
+ `downcast(clone_item, mon_dut_item.clone());
mon_item_port.write(clone_item);
// sample read data
- for (int i = I2C_DATA_WIDTH-1; i >= 0; i--) begin
+ for (int i = 7; i >= 0; i--) begin
cfg.vif.get_bit_data("device", cfg.timing_cfg, mon_data[i]);
`uvm_info(`gfn, $sformatf("monitor, rd_data, trans %0d, byte %0d, bit[%0d] %0b",
- partial_item.tran_id, partial_item.num_data+1, i, mon_data[i]), UVM_DEBUG)
+ mon_dut_item.tran_id, mon_dut_item.num_data+1, i, mon_data[i]), UVM_DEBUG)
end
- partial_item.data_q.push_back(mon_data);
- partial_item.num_data++;
+ mon_dut_item.data_q.push_back(mon_data);
+ mon_dut_item.num_data++;
// sample host ack/nack (in the last byte, nack can be issue if rcont is set)
- cfg.vif.wait_for_host_ack_or_nack(cfg.timing_cfg, partial_item.ack, partial_item.nack);
- `DV_CHECK_NE_FATAL({partial_item.ack, partial_item.nack}, 2'b11)
+ cfg.vif.wait_for_host_ack_or_nack(cfg.timing_cfg, mon_dut_item.ack, mon_dut_item.nack);
+ `DV_CHECK_NE_FATAL({mon_dut_item.ack, mon_dut_item.nack}, 2'b11)
`uvm_info(`gfn, $sformatf("monitor, detect HOST %s",
- (partial_item.ack) ? "ACK" : "NO_ACK"), UVM_DEBUG)
+ (mon_dut_item.ack) ? "ACK" : "NO_ACK"), UVM_DEBUG)
end
begin
cfg.vif.wait_for_host_stop_or_rstart(cfg.timing_cfg,
- partial_item.rstart,
- partial_item.stop);
- `DV_CHECK_NE_FATAL({partial_item.rstart, partial_item.stop}, 2'b11)
+ mon_dut_item.rstart,
+ mon_dut_item.stop);
+ `DV_CHECK_NE_FATAL({mon_dut_item.rstart, mon_dut_item.stop}, 2'b11)
`uvm_info(`gfn, $sformatf("monitor, rd_data, detect HOST %s",
- (partial_item.stop) ? "STOP" : "RSTART"), UVM_DEBUG)
+ (mon_dut_item.stop) ? "STOP" : "RSTART"), UVM_DEBUG)
end
join_any
disable fork;
@@ -133,34 +133,34 @@
end
endtask : read_thread
- virtual protected task write_thread(i2c_item partial_item);
+ virtual protected task write_thread(i2c_item mon_dut_item);
i2c_item clone_item;
- partial_item.stop = 1'b0;
- partial_item.rstart = 1'b0;
- while (!partial_item.stop && !partial_item.rstart) begin
+ mon_dut_item.stop = 1'b0;
+ mon_dut_item.rstart = 1'b0;
+ while (!mon_dut_item.stop && !mon_dut_item.rstart) begin
fork
begin : iso_fork_write
fork
begin
// ask driver's response a write request
- for (int i = I2C_DATA_WIDTH-1; i >= 0; i--) begin
+ for (int i = 7; i >= 0; i--) begin
cfg.vif.get_bit_data("host", cfg.timing_cfg, mon_data[i]);
end
- partial_item.num_data++;
- partial_item.data_q.push_back(mon_data);
- partial_item.drv_type = DevAck;
- `downcast(clone_item, partial_item.clone());
+ mon_dut_item.num_data++;
+ mon_dut_item.data_q.push_back(mon_data);
+ mon_dut_item.drv_type = DevAck;
+ `downcast(clone_item, mon_dut_item.clone());
mon_item_port.write(clone_item);
cfg.vif.wait_for_device_ack(cfg.timing_cfg);
end
begin
cfg.vif.wait_for_host_stop_or_rstart(cfg.timing_cfg,
- partial_item.rstart,
- partial_item.stop);
- `DV_CHECK_NE_FATAL({partial_item.rstart, partial_item.stop}, 2'b11)
+ mon_dut_item.rstart,
+ mon_dut_item.stop);
+ `DV_CHECK_NE_FATAL({mon_dut_item.rstart, mon_dut_item.stop}, 2'b11)
`uvm_info(`gfn, $sformatf("monitor, wr_data, detect HOST %s %0b",
- (partial_item.stop) ? "STOP" : "RSTART", partial_item.stop), UVM_DEBUG)
+ (mon_dut_item.stop) ? "STOP" : "RSTART", mon_dut_item.stop), UVM_DEBUG)
end
join_any
disable fork;
@@ -185,3 +185,4 @@
endtask : process_reset
endclass : i2c_monitor
+
diff --git a/hw/ip/i2c/dv/env/i2c_env_cfg.sv b/hw/ip/i2c/dv/env/i2c_env_cfg.sv
index e7a0dd8..7d6a78f 100644
--- a/hw/ip/i2c/dv/env/i2c_env_cfg.sv
+++ b/hw/ip/i2c/dv/env/i2c_env_cfg.sv
@@ -4,6 +4,8 @@
class i2c_env_cfg extends cip_base_env_cfg #(.RAL_T(i2c_reg_block));
+ i2c_target_addr_mode_e target_addr_mode = Addr7BitMode;
+
// TODO: various knobs to enable certain routines
bit do_rd_overflow = 1'b0;
bit do_wr_overflow = 1'b0;
diff --git a/hw/ip/i2c/dv/env/i2c_env_pkg.sv b/hw/ip/i2c/dv/env/i2c_env_pkg.sv
index b97bbc4..5804cc9 100644
--- a/hw/ip/i2c/dv/env/i2c_env_pkg.sv
+++ b/hw/ip/i2c/dv/env/i2c_env_pkg.sv
@@ -47,7 +47,7 @@
parameter uint I2C_MIN_TIMING = 1; // at least 1
parameter uint I2C_MAX_TIMING = 5;
parameter uint I2C_TIME_RANGE = I2C_MAX_TIMING - I2C_MIN_TIMING;
- parameter uint I2C_TIMEOUT_ENB = 1;
+ parameter uint I2C_TIMEOUT_ENB = 0; // TODO: temporaly disable
parameter uint I2C_MIN_TIMEOUT = 1;
parameter uint I2C_MAX_TIMEOUT = 2;
parameter uint I2C_IDLE_TIME = 1200;
diff --git a/hw/ip/i2c/dv/env/i2c_scoreboard.sv b/hw/ip/i2c/dv/env/i2c_scoreboard.sv
index 12f5ef0..ec380f5 100644
--- a/hw/ip/i2c/dv/env/i2c_scoreboard.sv
+++ b/hw/ip/i2c/dv/env/i2c_scoreboard.sv
@@ -250,7 +250,7 @@
if (cfg.en_scb) begin
str = {$sformatf("\n\n*** SCOREBOARD CHECK\n")};
str = {str, $sformatf(" - Total checked trans %0d\n", num_exp_tran)};
- `uvm_info(`gfn, $sformatf("%s", str), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("%s", str), UVM_DEBUG)
end
endfunction : report_phase
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv
index e8dfef8..36e1d8b 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv
@@ -24,7 +24,7 @@
rand uint num_wr_bytes;
rand uint num_rd_bytes;
rand bit [7:0] wr_data;
- rand bit [6:0] addr;
+ rand bit [9:0] addr; // support both 7-bit and 10-bit target address
rand bit rw_bit;
i2c_item fmt_item;
@@ -128,6 +128,16 @@
end
endtask : host_init
+ virtual task check_host_idle();
+ bit fmtempty, hostidle;
+ bit [TL_DW-1:0] reg_val;
+ do begin
+ csr_rd(.ptr(ral.status), .value(reg_val));
+ fmtempty = bit'(get_field_val(ral.status.fmtempty, reg_val));
+ hostidle = bit'(get_field_val(ral.status.hostidle, reg_val));
+ end while (!fmtempty || !hostidle);
+ endtask : check_host_idle
+
function automatic void get_timing_values();
// derived timing parameters
timing_cfg.enbTimeOut = e_timeout;
@@ -161,14 +171,19 @@
cfg.m_i2c_agent_cfg.timing_cfg = timing_cfg;
// set time to stop test
cfg.m_i2c_agent_cfg.ok_to_end_delay_ns = DELAY_FOR_EOT_NS;
+ // config target address mode of agent to the same
+ cfg.m_i2c_agent_cfg.target_addr_mode = cfg.target_addr_mode;
endtask : program_timing_regs
virtual task program_format_flag(i2c_item item, string msg="");
- bit [TL_DW-1:0] reg_val;
-
csr_spinwait(.ptr(ral.status.fmtfull), .exp_data(1'b0));
- reg_val = {19'd0, item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte};
- csr_wr(.csr(ral.fdata), .value(reg_val));
+ ral.fdata.nakok.set(item.nakok);
+ ral.fdata.rcont.set(item.rcont);
+ ral.fdata.read.set(item.read);
+ ral.fdata.stop.set(item.stop);
+ ral.fdata.start.set(item.start);
+ ral.fdata.fbyte.set(item.fbyte);
+ csr_update(.csr(ral.fdata));
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(fmt_fifo_access_dly)
cfg.m_i2c_agent_cfg.vif.wait_for_dly(fmt_fifo_access_dly);
print_format_flag(item, msg);
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv
index 283aa3d..2805080 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv
@@ -26,16 +26,20 @@
endtask : host_init
virtual task host_send_trans(int num_trans);
- bit last_tran;
+ bit last_tran;
// setup config
force_use_incorrect_config = 1'b0;
fmt_item = new("fmt_item");
- `DV_CHECK_RANDOMIZE_FATAL(this)
- get_timing_values();
- program_timing_regs();
-
for (uint cur_tran = 1; cur_tran <= num_trans; cur_tran++) begin
+ // re-programming timing registers for the first transaction
+ // or when the previous transaction is completed
+ if (fmt_item.stop || cur_tran == 1) begin
+ `DV_CHECK_RANDOMIZE_FATAL(this)
+ get_timing_values();
+ program_timing_regs();
+ end
+
last_tran = (cur_tran == num_trans) ? 1'b1 : 1'b0;
// not program address for chained reads
host_program_target_address();
@@ -46,18 +50,25 @@
`uvm_info(`gfn, $sformatf("finish sending %s transaction, %0s at the end, %0d/%0d, ",
(rw_bit) ? "read" : "write",
(fmt_item.stop) ? "stop" : "rstart", cur_tran, num_trans), UVM_DEBUG)
+
+ // check a completed transaction is programmed to the host/dut (stop bit must be issued)
+ // and check if the host/dut is in idle before allow re-programming the timing registers
+ if (fmt_item.stop) begin
+ check_host_idle();
+ end
end
endtask : host_send_trans
virtual task host_program_target_address();
- // programm fmt flags for address
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(fmt_item)
fmt_item.start = 1'b1;
fmt_item.stop = 1'b0;
fmt_item.read = 1'b0;
- `DV_CHECK_MEMBER_RANDOMIZE_FATAL(addr)
- `DV_CHECK_MEMBER_RANDOMIZE_FATAL(rw_bit)
- fmt_item.fbyte = (rw_bit) ? {addr, BusOpRead} : {addr, BusOpWrite};
+ if (cfg.target_addr_mode == Addr7BitMode) begin
+ fmt_item.fbyte = (rw_bit) ? {addr[6:0], BusOpRead} : {addr[6:0], BusOpWrite};
+ end else begin // Addr10BitMode
+ fmt_item.fbyte = (rw_bit) ? {addr[9:0], BusOpRead} : {addr[9:0], BusOpWrite};
+ end
program_format_flag(fmt_item, "host_program_target_address");
endtask : host_program_target_address
@@ -104,7 +115,7 @@
fmt_item.fbyte = wr_data;
// last write byte of last tran., stop flag must be set to issue stop bit
// last write byte of other tran., stop is randomly set/unset to issue stop/rstart bit
- fmt_item.stop = (i != num_wr_bytes) ? 1'b0 : ((last_tran) ? 1'b1 : fmt_item.stop);
+ fmt_item.stop = (i != num_wr_bytes) ? 1'b0 : ((last_tran) ? 1'b1 : fmt_item.stop);
program_format_flag(fmt_item, "host_write_trans");
end
endtask : host_write_trans