[i2c,dv] smoke test

Target smoke test

Signed-off-by: Jaedon Kim <jdonjdon@google.com>
diff --git a/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv b/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv
index b193687..8295ce9 100644
--- a/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv
+++ b/hw/dv/sv/i2c_agent/i2c_agent_cfg.sv
@@ -18,8 +18,9 @@
 
   bit     host_scl_start;
   bit     host_scl_stop;
+  event   got_stop;
 
-  // this variables can be configured from test
+  // this variables can be configured from host test
   uint i2c_host_min_data_rw = 1;
   uint i2c_host_max_data_rw = 10;
 
diff --git a/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv b/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv
index 02934be..cb1ed7d 100644
--- a/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv
+++ b/hw/dv/sv/i2c_agent/i2c_agent_pkg.sv
@@ -17,7 +17,8 @@
   // Bus/Transaction types for the agent driver
   typedef enum logic [3:0] {
     None, DevAck, RdData, WrData,
-    HostStart, HostRStart, HostData, HostNAck, HostStop
+    HostStart, HostRStart, HostData, HostAck,
+    HostNAck, HostStop
   } drv_type_e;
 
   // register values
diff --git a/hw/dv/sv/i2c_agent/i2c_driver.sv b/hw/dv/sv/i2c_agent/i2c_driver.sv
index 53ae72d..0b0ad90 100644
--- a/hw/dv/sv/i2c_agent/i2c_driver.sv
+++ b/hw/dv/sv/i2c_agent/i2c_driver.sv
@@ -60,7 +60,6 @@
     end
   endtask : get_and_drive
 
-  // TODO: drive_host_item is WiP
   virtual task drive_host_item(i2c_item req);
     `uvm_info(`gfn, $sformatf("drv: %s", req.drv_type.name), UVM_MEDIUM)
     unique case (req.drv_type)
@@ -76,12 +75,18 @@
         for (int i = $bits(req.wdata) -1; i >= 0; i--) begin
           cfg.vif.host_data(cfg.timing_cfg, req.wdata[i]);
         end
-
-        // wait one more cycle for ack
+        // Wait one more cycle for ack
         cfg.vif.wait_scl(.iter(1), .tc(cfg.timing_cfg));
       end
+      HostAck: begin
+        // Wait for read data and send ack
+        cfg.vif.wait_scl(.iter(8), .tc(cfg.timing_cfg));
+        cfg.vif.host_data(cfg.timing_cfg, 0);
+      end
       HostNAck: begin
-        cfg.vif.host_nack(cfg.timing_cfg);
+        // Wait for read data and send nack
+        cfg.vif.wait_scl(.iter(8), .tc(cfg.timing_cfg));
+        cfg.vif.host_data(cfg.timing_cfg, 1);
       end
       HostStop: begin
         cfg.host_scl_stop = 1;
@@ -152,14 +157,16 @@
   endtask : release_bus
 
   task drive_scl();
+    int scl_spinwait_timeout_ns = 1_000_000; // 1ms
     forever begin
+      @(cfg.vif.cb);
       wait(cfg.host_scl_start);
       while(!cfg.host_scl_stop) begin
-        cfg.vif.scl_o = 1'b0;
+        cfg.vif.scl_o <= 1'b0;
         cfg.vif.wait_for_dly(cfg.timing_cfg.tClockLow);
         cfg.vif.wait_for_dly(cfg.timing_cfg.tSetupBit);
-        cfg.vif.scl_o = 1'b1;
-        wait(cfg.vif.cb.scl_i === 1'b1);
+        cfg.vif.scl_o <= 1'b1;
+        `DV_WAIT(cfg.vif.scl_i === 1'b1,, scl_spinwait_timeout_ns, "i2c_drv_scl")
         cfg.vif.wait_for_dly(cfg.timing_cfg.tClockPulse);
         if (!cfg.host_scl_stop) cfg.vif.scl_o = 1'b0;
         cfg.vif.wait_for_dly(cfg.timing_cfg.tHoldBit);
diff --git a/hw/dv/sv/i2c_agent/i2c_if.sv b/hw/dv/sv/i2c_agent/i2c_if.sv
index 53de546..a828139 100644
--- a/hw/dv/sv/i2c_agent/i2c_if.sv
+++ b/hw/dv/sv/i2c_agent/i2c_if.sv
@@ -27,10 +27,22 @@
 
   clocking cb @(posedge clk_i);
     input scl_i;
+    input sda_i;
+    output scl_o;
+    output sda_o;
   endclocking
   //---------------------------------
   // common tasks
   //---------------------------------
+
+  // This is literally same as '@(posedge scl_i)'
+  // In target mode, @(posedge scl_i) gives some glitch,
+  // so I have to use clocking block sampled signals.
+  task automatic p_edge_scl();
+    wait(cb.scl_i == 0);
+    wait(cb.scl_i == 1);
+  endtask
+
   task automatic wait_for_dly(int dly);
     repeat (dly) @(posedge clk_i);
   endtask : wait_for_dly
@@ -218,7 +230,7 @@
       @(negedge scl_i);
       wait_for_dly(tc.tHoldBit - tc.tSdaInterference);
     end else begin // target transmits data (rd_data)
-      bit_o = sda_o;
+      bit_o = sda_i;
       wait_for_dly(tc.tClockPulse + tc.tHoldBit);
     end
   endtask: get_bit_data
@@ -231,52 +243,48 @@
   endtask: host_start
 
   task automatic host_rstart(ref timing_cfg_t tc);
-      scl_o = 1'b0;
-      wait_for_dly(tc.tSetupStart);
-      sda_o = 1'b0;
-      scl_o = 1'b1;
-      wait_for_dly(tc.tHoldStart);
-      scl_o = 1'b0;
-      wait_for_dly(tc.tClockStart);
+    wait(scl_i === 1'b1);
+    wait_for_dly(tc.tSetupStart);
+    sda_o = 1'b0;
+    wait_for_dly(tc.tHoldStart);
+    wait_for_dly(tc.tHoldBit);
   endtask: host_rstart
 
   task automatic host_data(ref timing_cfg_t tc, input bit bit_i);
     sda_o = bit_i;
     wait_for_dly(tc.tClockLow);
     wait_for_dly(tc.tSetupBit);
-    wait(cb.scl_i === 1'b1);
+    wait(scl_i === 1'b1);
     wait_for_dly(tc.tClockPulse);
     wait_for_dly(tc.tHoldBit);
+    sda_o = 1;
   endtask: host_data
 
   task automatic host_stop(ref timing_cfg_t tc);
-      sda_o = 1'b0;
-      wait_for_dly(tc.tClockStop);
-      scl_o = 1'b1;
-      wait_for_dly(tc.tSetupStop);
-      sda_o = 1'b0;
-      wait_for_dly(tc.tHoldStop);
+    sda_o = 1'b0;
+    wait_for_dly(tc.tClockStop);
+    scl_o = 1'b1;
+    wait_for_dly(tc.tSetupStop);
+    sda_o = 1'b0;
+    wait_for_dly(tc.tHoldStop);
   endtask: host_stop
 
   task automatic host_nack(ref timing_cfg_t tc);
-      sda_o = 1'b0;
-      wait_for_dly(tc.tClockLow);
-      sda_o = 1'b1;
-      wait_for_dly(tc.tSetupBit);
-      scl_o = 1'b1;
-      wait_for_dly(tc.tClockPulse);
-      scl_o = 1'b0;
-      wait_for_dly(tc.tHoldBit);
+    sda_o = 1'b0;
+    wait_for_dly(tc.tClockLow);
+    sda_o = 1'b1;
+    wait_for_dly(tc.tSetupBit);
+    scl_o = 1'b1;
+    wait_for_dly(tc.tClockPulse);
+    scl_o = 1'b0;
+    wait_for_dly(tc.tHoldBit);
   endtask: host_nack
 
   task automatic wait_scl(int iter = 1, timing_cfg_t tc);
     repeat(iter) begin
-      wait_for_dly(tc.tClockLow);
-      wait_for_dly(tc.tSetupBit);
-      wait(cb.scl_i === 1'b1);
-      wait_for_dly(tc.tClockPulse);
-      wait_for_dly(tc.tHoldBit);
+      wait_for_dly(tc.tClockLow + tc.tSetupBit);
+      wait(scl_i === 1'b1);
+      wait_for_dly(tc.tClockPulse + tc.tHoldBit);
     end
   endtask // wait_scl
-
 endinterface : i2c_if
diff --git a/hw/dv/sv/i2c_agent/i2c_item.sv b/hw/dv/sv/i2c_agent/i2c_item.sv
index 34089fd..ba0fd9d 100644
--- a/hw/dv/sv/i2c_agent/i2c_item.sv
+++ b/hw/dv/sv/i2c_agent/i2c_item.sv
@@ -27,6 +27,9 @@
   logic [7:0]              wdata;
   logic [7:0]              rdata;
 
+  // Use for debug print
+  string                   pname = "";
+
   constraint fbyte_c     { fbyte      inside {[0 : 127] }; }
   constraint rcont_c     {
      solve read, stop before rcont;
@@ -46,15 +49,15 @@
     `uvm_field_int(start,                   UVM_DEFAULT)
     `uvm_field_int(stop,                    UVM_DEFAULT)
     `uvm_field_int(wdata,                   UVM_DEFAULT | UVM_NOCOMPARE)
-    `uvm_field_queue_int(data_q,            UVM_DEFAULT)
+    `uvm_field_queue_int(data_q,            UVM_DEFAULT | UVM_NOPRINT)
     `uvm_field_queue_int(fmt_ovf_data_q,    UVM_DEFAULT | UVM_NOCOMPARE)
     `uvm_field_int(rdata,                   UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
-    `uvm_field_int(rstart,                  UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
+    `uvm_field_int(rstart,                  UVM_DEFAULT | UVM_NOCOMPARE)
     `uvm_field_int(fbyte,                   UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
     `uvm_field_int(ack,                     UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
     `uvm_field_int(nack,                    UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
-    `uvm_field_int(read,                    UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
-    `uvm_field_int(rcont,                   UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
+    `uvm_field_int(read,                    UVM_DEFAULT | UVM_NOCOMPARE)
+    `uvm_field_int(rcont,                   UVM_DEFAULT | UVM_NOCOMPARE)
     `uvm_field_int(nakok,                   UVM_DEFAULT | UVM_NOPRINT | UVM_NOCOMPARE)
     `uvm_field_enum(drv_type_e,  drv_type,  UVM_DEFAULT | UVM_NOCOMPARE)
   `uvm_object_utils_end
@@ -85,4 +88,19 @@
     clear_flag();
   endfunction : clear_all
 
+  virtual function string convert2string();
+    string str = "";
+    str = {str, $sformatf("%s:tran_id  = %0d\n", pname, tran_id)};
+    str = {str, $sformatf("%s:bus_op   = %s\n",    pname, bus_op.name)};
+    str = {str, $sformatf("%s:addr     = 0x%2x\n", pname, addr)};
+    str = {str, $sformatf("%s:num_data = %0d\n", pname, num_data)};
+    str = {str, $sformatf("%s:start    = %1b\n", pname, start)};
+    str = {str, $sformatf("%s:stop     = %1b\n", pname, stop)};
+    str = {str, $sformatf("%s:read     = %1b\n", pname, read)};
+    str = {str, $sformatf("%s:rstart   = %1b\n", pname, rstart)};
+    foreach (data_q[i]) begin
+      str = {str, $sformatf("%s:data_q[%0d]=0x%2x\n", pname, i, data_q[i])};
+    end
+    return str;
+  endfunction
 endclass : i2c_item
diff --git a/hw/dv/sv/i2c_agent/i2c_monitor.sv b/hw/dv/sv/i2c_agent/i2c_monitor.sv
index a9f9c22..0de583d 100644
--- a/hw/dv/sv/i2c_agent/i2c_monitor.sv
+++ b/hw/dv/sv/i2c_agent/i2c_monitor.sv
@@ -34,26 +34,72 @@
 
   virtual task run_phase(uvm_phase phase);
     wait(cfg.vif.rst_ni);
-    forever begin
-      fork
-        begin: iso_fork
-          fork
-            begin
-              collect_thread(phase);
-            end
-            begin // if (on-the-fly) reset is monitored, drop the item
-              wait_for_reset_and_drop_item();
-              `uvm_info(`gfn, $sformatf("\nmonitor is reset, drop item\n%s",
-                  mon_dut_item.sprint()), UVM_DEBUG)
-            end
-          join_any
-          disable fork;
-        end: iso_fork
-      join
+    if (cfg.if_mode == Host) begin
+      bit r_bit = 1'b0;
+      i2c_item full_item;
+      forever 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, "\nmonitor, detect HOST START", UVM_MEDIUM)
+        end else begin
+          mon_dut_item.rstart = 1'b1;
+        end
+        num_dut_tran++;
+        mon_dut_item.start = 1'b1;
+        // collecting address
+        for (int i = cfg.target_addr_mode - 1; i >= 0; i--) begin
+          cfg.vif.p_edge_scl();
+          mon_dut_item.addr[i] = cfg.vif.cb.sda_i;
+          `uvm_info(`gfn, $sformatf("\nmonitor, address[%0d] %b", i, mon_dut_item.addr[i]),
+                    UVM_HIGH)
+        end
+        `uvm_info(`gfn, $sformatf("\nmonitor, address %0x", mon_dut_item.addr), UVM_MEDIUM)
+        cfg.vif.p_edge_scl();
+        r_bit = cfg.vif.cb.sda_i;
+        `uvm_info(`gfn, $sformatf("\nmonitor, rw %d", r_bit), UVM_MEDIUM)
+        mon_dut_item.bus_op = (r_bit) ? BusOpRead : BusOpWrite;
+
+        // expect target ack
+        cfg.vif.p_edge_scl();
+        r_bit = cfg.vif.cb.sda_i;
+        `DV_CHECK_CASE_EQ(r_bit, 1'b0)
+
+        if (mon_dut_item.bus_op == BusOpRead)
+          target_read();
+        else target_write();
+
+        // send rsp_item to scoreboard
+        `downcast(full_item, mon_dut_item.clone());
+        full_item.stop = 1'b1;
+        if (mon_dut_item.bus_op == BusOpRead) begin
+          full_item.read = 1;
+          analysis_port.write(full_item);
+        end
+        mon_dut_item.clear_data();
+      end
+    end else begin
+      forever begin
+        fork
+          begin: iso_fork
+            fork
+              begin
+                collect_thread(phase);
+              end
+              begin // if (on-the-fly) reset is monitored, drop the item
+                wait_for_reset_and_drop_item();
+                `uvm_info(`gfn, $sformatf("\nmonitor is reset, drop item\n%s",
+                                          mon_dut_item.sprint()), UVM_DEBUG)
+              end
+            join_any
+            disable fork;
+          end: iso_fork
+        join
+      end
     end
   endtask : run_phase
 
-  // collect transactions forever
+  // Collect transactions forever
   virtual protected task collect_thread(uvm_phase phase);
     i2c_item full_item;
     wait(cfg.en_monitor);
@@ -196,8 +242,76 @@
   virtual task monitor_ready_to_end();
     forever begin
       @(cfg.vif.scl_i or cfg.vif.sda_i or cfg.vif.scl_o or cfg.vif.sda_o);
-      ok_to_end = (cfg.vif.scl_i == 1'b1) && (cfg.vif.sda_i == 1'b1);
+      if (cfg.if_mode == Host) begin
+        // TODO: set end condition if necessary
+      end else begin
+        ok_to_end = (cfg.vif.scl_i == 1'b1) && (cfg.vif.sda_i == 1'b1);
+      end
     end
   endtask : monitor_ready_to_end
 
+  // Rewrite read / write task using glitch free edge functions.
+  task target_read();
+    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
+      // ask driver response read data
+      mon_dut_item.drv_type = RdData;
+      for (int i = 7; i >= 0; i--) begin
+        cfg.vif.p_edge_scl();
+        mon_data[i] = cfg.vif.cb.sda_i;
+        `uvm_info(`gfn, $sformatf("\nmonitor, target_read, trans %0d, byte %0d, bit[%0d] %0b",
+                  mon_dut_item.tran_id, mon_dut_item.num_data+1, i, mon_data[i]), UVM_HIGH)
+      end
+      mon_dut_item.data_q.push_back(mon_data);
+      mon_dut_item.num_data++;
+      `uvm_info(`gfn, $sformatf("\nmonitor, target_read, trans %0d, byte %0d 0x%0x",
+                                mon_dut_item.tran_id, mon_dut_item.num_data, mon_data), UVM_MEDIUM)
+      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("\nmonitor, target_read detect HOST %s",
+                                (mon_dut_item.ack) ? "ACK" : "NO_ACK"), UVM_MEDIUM)
+      // if nack is issued, next bit must be stop or rstart
+      if (mon_dut_item.nack) begin
+        cfg.vif.wait_for_host_stop_or_rstart(cfg.timing_cfg,
+                                             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("\nmonitor, target_read, detect HOST %s",
+                                  (mon_dut_item.stop) ? "STOP" : "RSTART"), UVM_MEDIUM)
+        if (mon_dut_item.stop) ->cfg.got_stop;
+      end
+    end
+  endtask
+
+  task target_write();
+    bit r_bit;
+    mon_dut_item.stop   = 1'b0;
+    mon_dut_item.rstart = 1'b0;
+    while (!mon_dut_item.stop && !mon_dut_item.rstart) begin
+      mon_dut_item.drv_type = WrData;
+      for (int i = 7; i >= 0; i--) begin
+        cfg.vif.p_edge_scl();
+      end
+      // check for ack
+      cfg.vif.p_edge_scl();
+      r_bit = cfg.vif.cb.sda_i;
+      `uvm_info(`gfn, $sformatf("\nmonitor, target_write detect HOST %s",
+                                (!r_bit) ? "ACK" : "NO_ACK"), UVM_MEDIUM)
+      // if nack is issued, next bit must be stop or rstart
+      if (!r_bit) begin
+        cfg.vif.wait_for_host_stop_or_rstart(cfg.timing_cfg,
+                                             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("\nmonitor, rd_data, detect HOST %s",
+                                  (mon_dut_item.stop) ? "STOP" : "RSTART"), UVM_MEDIUM)
+        if (mon_dut_item.stop) ->cfg.got_stop;
+      end
+    end
+  endtask // target_write
+
 endclass : i2c_monitor
diff --git a/hw/ip/i2c/data/i2c_testplan.hjson b/hw/ip/i2c/data/i2c_testplan.hjson
index aa262c2..d9fae51 100644
--- a/hw/ip/i2c/data/i2c_testplan.hjson
+++ b/hw/ip/i2c/data/i2c_testplan.hjson
@@ -252,7 +252,7 @@
               - Read and write transfer matching
             '''
       stage: V1
-      tests: [""]
+      tests: ["i2c_target_smoke"]
     }
     {
       name: target_error_intr
diff --git a/hw/ip/i2c/dv/env/i2c_env.sv b/hw/ip/i2c/dv/env/i2c_env.sv
index e0ec79e..be1ad72 100644
--- a/hw/ip/i2c/dv/env/i2c_env.sv
+++ b/hw/ip/i2c/dv/env/i2c_env.sv
@@ -32,6 +32,11 @@
     if (cfg.m_i2c_agent_cfg.if_mode == Host) begin
       virtual_sequencer.target_mode_wr_exp_port.connect(
               scoreboard.target_mode_wr_exp_fifo.analysis_export);
+      virtual_sequencer.target_mode_wr_obs_port.connect(
+              scoreboard.target_mode_wr_obs_fifo.analysis_export);
+      m_i2c_agent.monitor.analysis_port.connect(scoreboard.target_mode_rd_obs_fifo.analysis_export);
+      virtual_sequencer.target_mode_rd_exp_port.connect(
+              scoreboard.target_mode_rd_exp_fifo.analysis_export);
     end
   endfunction
 
diff --git a/hw/ip/i2c/dv/env/i2c_env_cfg.sv b/hw/ip/i2c/dv/env/i2c_env_cfg.sv
index 01baba5..56204bc 100644
--- a/hw/ip/i2c/dv/env/i2c_env_cfg.sv
+++ b/hw/ip/i2c/dv/env/i2c_env_cfg.sv
@@ -16,6 +16,20 @@
 
   tran_type_e trans_type = ReadWrite;
 
+  int        sent_acq_cnt;
+  int        rcvd_acq_cnt;
+
+  // Ratio between write and read
+  int        wr_pct = 1;
+  int        rd_pct = 1;
+
+  // re-start injection rate between 1~10
+  int        rs_pct = 1;
+
+  // dut target mode parameters
+  int        min_data = 1;
+  int        max_data = 60;
+
   `uvm_object_utils_begin(i2c_env_cfg)
     `uvm_field_object(m_i2c_agent_cfg, UVM_DEFAULT)
   `uvm_object_utils_end
diff --git a/hw/ip/i2c/dv/env/i2c_env_pkg.sv b/hw/ip/i2c/dv/env/i2c_env_pkg.sv
index 71a9513..d75f937 100644
--- a/hw/ip/i2c/dv/env/i2c_env_pkg.sv
+++ b/hw/ip/i2c/dv/env/i2c_env_pkg.sv
@@ -61,11 +61,14 @@
 
     item.wdata = data[7:0];
     if (data[9:8] == 2'b11) begin
-      // TODO Re start support
+      item.rstart = 1;
     end else begin
       item.start = data[8];
       item.stop = data[9];
     end
+    if (item.start || item.rcont) begin
+      item.read = data[0];
+    end
     return item;
   endfunction // acq2item
 
diff --git a/hw/ip/i2c/dv/env/i2c_scoreboard.sv b/hw/ip/i2c/dv/env/i2c_scoreboard.sv
index 374c1ad..0cbe681 100644
--- a/hw/ip/i2c/dv/env/i2c_scoreboard.sv
+++ b/hw/ip/i2c/dv/env/i2c_scoreboard.sv
@@ -13,6 +13,8 @@
 
   local i2c_item  exp_rd_item;
   local i2c_item  exp_wr_item;
+  local i2c_item  obs_wr_item;
+  local i2c_item  obs_rd_item;
   local i2c_item  rd_pending_item;
   local uint      rd_wait;
   local bit       host_init = 1'b0;
@@ -33,10 +35,16 @@
 
   // Target mode transactions
   uvm_tlm_analysis_fifo #(i2c_item) target_mode_wr_exp_fifo;
+  uvm_tlm_analysis_fifo #(i2c_item) target_mode_wr_obs_fifo;
+  uvm_tlm_analysis_fifo #(i2c_item) target_mode_rd_exp_fifo;
+  uvm_tlm_analysis_fifo #(i2c_item) target_mode_rd_obs_fifo;
 
   // interrupt bit vector
   local bit [NumI2cIntr-1:0] intr_exp;
 
+  int                        num_obs_rd;
+
+
   `uvm_component_new
 
   function void build_phase(uvm_phase phase);
@@ -46,20 +54,38 @@
     rd_pending_item = new("rd_pending_item" );
     exp_rd_item = new("exp_rd_item");
     exp_wr_item = new("exp_wr_item");
+    obs_wr_item = new("obs_wr_item");
     target_mode_wr_exp_fifo = new("target_mode_wr_exp_fifo", this);
+    target_mode_wr_obs_fifo = new("target_mode_wr_obs_fifo", this);
+    target_mode_rd_exp_fifo = new("target_mode_rd_exp_fifo", this);
+    target_mode_rd_obs_fifo = new("target_mode_rd_obs_fifo", this);
   endfunction : build_phase
 
   task run_phase(uvm_phase phase);
+    string str;
     super.run_phase(phase);
     if (cfg.m_i2c_agent_cfg.if_mode == Host) begin
-      fork begin
+      int obs_wr_id = 0;
+      fork
         forever begin
           target_mode_wr_exp_fifo.get(exp_wr_item);
-          `uvm_info(`gfn, $sformatf("exp_tn%0d\n %s",
+          str = (exp_wr_item.start) ? "addr" : (exp_wr_item.stop) ? "stop" : "wr";
+          `uvm_info(`gfn, $sformatf("exp_%s_txn%0d\n %s", str,
                                     exp_wr_item.tran_id, exp_wr_item.sprint()), UVM_MEDIUM)
-          process_target_write(exp_wr_item);
+          target_mode_wr_obs_fifo.get(obs_wr_item);
+          obs_wr_item.tran_id = obs_wr_id++;
+          target_txn_comp(obs_wr_item, exp_wr_item, str);
         end
-      end join_none
+        forever begin
+          target_mode_rd_exp_fifo.get(exp_rd_item);
+          exp_rd_item.pname = "exp_rd";
+          `uvm_info(`gfn, $sformatf("\n%s", exp_rd_item.convert2string()), UVM_MEDIUM)
+          target_mode_rd_obs_fifo.get(obs_rd_item);
+          obs_rd_item.pname = "obs_rd";
+          obs_rd_item.tran_id = num_obs_rd++;
+          target_rd_comp(obs_rd_item, exp_rd_item);
+        end
+      join_none
     end else begin
       forever begin
         `DV_SPINWAIT_EXIT(
@@ -409,31 +435,27 @@
     `DV_EOT_PRINT_TLM_FIFO_CONTENTS(i2c_item, wr_item_fifo)
   endfunction
 
-  task process_target_write(i2c_item exp);
-    uvm_reg_data_t read_data;
-    i2c_item obs;
-
-    // polling status.acqempty == 0
-    csr_spinwait(.ptr(ral.status.acqempty), .exp_data(1'b0),
-                 .timeout_ns(10_000));
-
-    // read one entry and compare
-    csr_rd(.ptr(ral.acqdata), .value(read_data));
-    `uvm_create_obj(i2c_item, obs);
-    obs = acq2item(read_data);
-    obs.tran_id = this.tran_id++;
-    target_txn_comp(obs, exp);
-
-  endtask // process_target_write
-
   // Compare start, stop and wdata only
-  function void target_txn_comp(i2c_item obs, i2c_item exp);
-    `uvm_info(`gfn, $sformatf("comp:target wr_txn %0d", obs.tran_id), UVM_MEDIUM)
+  function void target_txn_comp(i2c_item obs, i2c_item exp, string str);
+    `uvm_info(`gfn, $sformatf("comp:target obs_%s_txn %0d\n%s", str, obs.tran_id, obs.sprint()),
+              UVM_MEDIUM)
+
+    `DV_CHECK_EQ(obs.tran_id, exp.tran_id)
     `DV_CHECK_EQ(obs.start, exp.start)
     `DV_CHECK_EQ(obs.stop, exp.stop)
-    if (obs.stop == 0) begin
+    if (obs.stop == 0 && obs.rstart == 0) begin
       `DV_CHECK_EQ(obs.wdata, exp.wdata)
     end
   endfunction // target_txn_comp
 
+  function void target_rd_comp(i2c_item obs, i2c_item exp);
+    `uvm_info(`gfn, $sformatf("comp:target obs_rd %0d\n%s", obs.tran_id, obs.convert2string()),
+              UVM_MEDIUM)
+    `DV_CHECK_EQ(obs.tran_id, exp.tran_id)
+    `DV_CHECK_EQ(obs.num_data, exp.num_data)
+    `DV_CHECK_EQ(obs.data_q.size(), exp.data_q.size())
+    foreach (exp.data_q[i]) begin
+      `DV_CHECK_EQ(obs.data_q[i], exp.data_q[i])
+    end
+  endfunction // target_rd_comp
 endclass : i2c_scoreboard
diff --git a/hw/ip/i2c/dv/env/i2c_seq_cfg.sv b/hw/ip/i2c/dv/env/i2c_seq_cfg.sv
index f150fe6..1355b45 100644
--- a/hw/ip/i2c/dv/env/i2c_seq_cfg.sv
+++ b/hw/ip/i2c/dv/env/i2c_seq_cfg.sv
@@ -53,10 +53,6 @@
   // set en_sda_interference to allow sda_interference irq is triggered
   bit en_sda_interference        = 1'b0;
 
-  // dut target mode parameters
-  int min_data = 1;
-  int max_data = 1;
-
   `uvm_object_new
 
 endclass : i2c_seq_cfg
diff --git a/hw/ip/i2c/dv/env/i2c_virtual_sequencer.sv b/hw/ip/i2c/dv/env/i2c_virtual_sequencer.sv
index 2084454..f3e4939 100644
--- a/hw/ip/i2c/dv/env/i2c_virtual_sequencer.sv
+++ b/hw/ip/i2c/dv/env/i2c_virtual_sequencer.sv
@@ -6,6 +6,8 @@
                                                                  .COV_T(i2c_env_cov));
   i2c_sequencer    i2c_sequencer_h;
   uvm_analysis_port #(i2c_item) target_mode_wr_exp_port;
+  uvm_analysis_port #(i2c_item) target_mode_wr_obs_port;
+  uvm_analysis_port #(i2c_item) target_mode_rd_exp_port;
 
   `uvm_component_utils(i2c_virtual_sequencer)
   `uvm_component_new
@@ -13,5 +15,7 @@
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
     target_mode_wr_exp_port = new("target_mode_wr_exp_port", this);
+    target_mode_wr_obs_port = new("target_mode_wr_obs_port", this);
+    target_mode_rd_exp_port = new("target_mode_rd_exp_port", this);
   endfunction
 endclass : i2c_virtual_sequencer
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 597442f..3638de6 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
@@ -58,7 +58,16 @@
   rand uint                   prob_scl_interference;
 
   // host timeout ctrl value
-   bit [31:0]                 host_timeout_ctrl = 32'hffff;
+  bit [31:0]                  host_timeout_ctrl = 32'hffff;
+  // Start counter including restart. Starting from 1 to match rtl value
+  // and easy to trace.
+  int start_cnt = 1;
+  int read_rcvd[$];
+  int full_txn_num = 0;
+  int exp_rd_id = 0;
+  int exp_wr_id = 0;
+  i2c_item read_txn_q[$];
+  int tran_id = 0;
 
   // constraints
   constraint addr_c {
@@ -250,9 +259,9 @@
       csr_update(ral.ctrl);
       // TODO: more initialization for the host running Target mode
       ral.target_id.address0.set(target_addr0);
-      ral.target_id.mask0.set(7'h3f);
+      ral.target_id.mask0.set(7'h7f);
       ral.target_id.address1.set(target_addr1);
-      ral.target_id.mask1.set(7'h3f);
+      ral.target_id.mask1.set(7'h7f);
       csr_update(ral.target_id);
       // Host timeout control
       ral.host_timeout_ctrl.set(this.host_timeout_ctrl);
@@ -518,4 +527,298 @@
      csr_wr(.ptr(ral.stretch_ctrl.en_addr_acq), .value(en_addr_acq));
      csr_wr(.ptr(ral.stretch_ctrl.en_addr_tx), .value(en_addr_tx));
   endtask : program_stretch_ctrl
+
+  // Use for debug only
+  function void print_time_property();
+    `uvm_info(`gfn, $sformatf("timing_prop"), UVM_MEDIUM)
+    // high period of the SCL in clock units
+    `uvm_info(`gfn, $sformatf("thigh:%0d", thigh), UVM_MEDIUM);
+    // low period of the SCL in clock units
+    `uvm_info(`gfn, $sformatf("tlow:%0d", tlow), UVM_MEDIUM);
+    // rise time of both SDA and SCL in clock units
+    `uvm_info(`gfn, $sformatf("t_r:%0d", t_r), UVM_MEDIUM);
+    // fall time of both SDA and SCL in clock units
+    `uvm_info(`gfn, $sformatf("t_f:%0d", t_f), UVM_MEDIUM);
+    // hold time for (repeated) START in clock units
+    `uvm_info(`gfn, $sformatf("thd_sta:%0d", thd_sta), UVM_MEDIUM);
+    // setup time for repeated START in clock units
+    `uvm_info(`gfn, $sformatf("tsu_sta:%0d", tsu_sta), UVM_MEDIUM);
+    // setup time for STOP in clock units
+    `uvm_info(`gfn, $sformatf("tsu_sto:%0d", tsu_sto), UVM_MEDIUM);
+    // data setup time in clock units
+    `uvm_info(`gfn, $sformatf("tsu_dat:%0d", tsu_dat), UVM_MEDIUM);
+    // data hold time in clock units
+    `uvm_info(`gfn, $sformatf("thd_dat:%0d", thd_dat), UVM_MEDIUM);
+    // bus free time between STOP and START in clock units
+    `uvm_info(`gfn, $sformatf("t_buf:%0d", t_buf), UVM_MEDIUM);
+    // max time target may stretch the clock
+    `uvm_info(`gfn, $sformatf("t_timeout:%0d", t_timeout), UVM_MEDIUM);
+    // max time target may stretch the clock
+    `uvm_info(`gfn, $sformatf("e_timeout:%0d", e_timeout), UVM_MEDIUM);
+    // sda unstable time during the posedge_clock
+    `uvm_info(`gfn, $sformatf("t_sda_unstable:%0d", t_sda_unstable), UVM_MEDIUM);
+    // sda interference time during the posedge_clock
+    `uvm_info(`gfn, $sformatf("t_sda_interference:%0d", t_sda_interference), UVM_MEDIUM);
+    // scl interference time during the posedge_clock
+    `uvm_info(`gfn, $sformatf("t_scl_interference:%0d", t_scl_interference), UVM_MEDIUM);
+    `uvm_info(`gfn, $sformatf("error intrs probability"), UVM_MEDIUM)
+    `uvm_info(`gfn, $sformatf("prob_sda_unstable:%0d    ", prob_sda_unstable), UVM_MEDIUM);
+    `uvm_info(`gfn, $sformatf("prob_sda_interference:%0d", prob_sda_interference), UVM_MEDIUM);
+    `uvm_info(`gfn, $sformatf("prob_scl_interference:%0d", prob_scl_interference), UVM_MEDIUM);
+  endfunction
+
+  // Print i2c_item.data_q with RS command notation
+  function void print_wr_data(i2c_item myq[$]);
+    int idx = 1;
+    `uvm_info("seq", $sformatf("q size:%0d", myq.size()), UVM_MEDIUM)
+    foreach (myq[i]) begin
+      if (myq[i].rstart) begin
+        `uvm_info("seq", $sformatf("idx %0d RS rw:%0d", start_cnt++, myq[i].read), UVM_MEDIUM)
+        idx = 1;
+      end else begin
+        `uvm_info("seq", $sformatf("%2d: 0x%2x", idx++, myq[i].wdata), UVM_MEDIUM)
+      end
+    end
+  endfunction
+
+  // set rw bit based on cfg rd/wr pct
+  function bit get_read_write();
+    bit rw;
+    randcase
+      cfg.wr_pct: rw = 0;
+      cfg.rd_pct: rw = 1;
+    endcase
+    return rw;
+  endfunction // get_read_write
+
+  // Read acqdata and pass to scoreboard until
+  // send and rcv cnt become the same.
+  virtual task process_acq();
+    uvm_reg_data_t read_data;
+    i2c_item obs;
+    bit is_read;
+
+    wait(cfg.sent_acq_cnt > 0);
+
+    while (cfg.sent_acq_cnt != cfg.rcvd_acq_cnt) begin
+      // polling status.acqempty == 0
+      csr_rd(.ptr(ral.status.acqempty), .value(read_data));
+      if (read_data == 0) begin
+
+        // read one entry and compare
+        csr_rd(.ptr(ral.acqdata), .value(read_data));
+        `uvm_info("process_acq", $sformatf("acq data %x", read_data), UVM_MEDIUM)
+        `uvm_create_obj(i2c_item, obs);
+        obs = acq2item(read_data);
+        is_read = obs.read;
+
+        obs.tran_id = cfg.rcvd_acq_cnt++;
+        p_sequencer.target_mode_wr_obs_port.write(obs);
+      end else begin // if (read_data == 0)
+        cfg.clk_rst_vif.wait_clks(1);
+        `uvm_info("process_acq", $sformatf("acq_dbg: sent:%0d rcvd:%0d acq_is_empty",
+                                           cfg.sent_acq_cnt, cfg.rcvd_acq_cnt), UVM_HIGH)
+      end
+    end
+  endtask
+
+  // Polling read_rcvd q and fetch read data to txdata fifo
+  virtual task process_txq();
+    uvm_reg_data_t data;
+    int read_size;
+    int rd_txfifo_timeout_ns = 50_000;
+
+    forever begin
+      @(cfg.m_i2c_agent_cfg.vif.cb);
+      if (read_rcvd.size() > 0) begin
+        read_size = read_rcvd.pop_front();
+      end
+      while (read_size > 0) begin
+        @(cfg.m_i2c_agent_cfg.vif.cb);
+        if (read_txn_q.size() > 0) begin
+          i2c_item item;
+          //check tx fifo is full
+          csr_spinwait(.ptr(ral.status.txfull), .exp_data(1'b0),
+                       .timeout_ns(rd_txfifo_timeout_ns));
+          `uvm_create_obj(i2c_item, item)
+          item = read_txn_q.pop_front();
+          `uvm_info("process_txq", $sformatf("send rdata:%x", item.wdata), UVM_MEDIUM)
+          csr_wr(.ptr(ral.txdata), .value(item.wdata));
+          read_size--;
+        end
+      end
+    end
+  endtask
+
+  // Create byte transaction (payload) to read or write.
+  // Restart can be stuffed in between bytes except first and the last bytes.
+  // While normal transaction type (read, write) is decided in 'fetch_txn',
+  // Restat transaction type is set here to make io trace easier.
+  virtual function void create_txn(ref i2c_item myq[$]);
+    bit [7:0] wdata_q[$];
+    i2c_item  txn;
+    bit       rs_avl;
+
+    `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(wdata_q,
+                                       wdata_q.size() inside {
+                           [cfg.min_data : cfg.max_data]};)
+
+    for (int i = 0; i < wdata_q.size(); i++) begin
+      if ($urandom_range(0,9) < cfg.rs_pct) rs_avl = 1;
+      else rs_avl = 0;
+      // restart entry
+      if (rs_avl == 1 && wdata_q.size() > 1 &&
+          i inside {[1:wdata_q.size() -1]}) begin
+        `uvm_info("seq", $sformatf("RS inserted before data %0d", i), UVM_MEDIUM)
+        `uvm_create_obj(i2c_item, txn)
+        txn.drv_type = HostRStart;
+        txn.rstart = 1;
+        txn.stop = 0;
+        txn.read = get_read_write();
+        myq.push_back(txn);
+      end
+      `uvm_create_obj(i2c_item, txn)
+      txn.drv_type = HostData;
+      txn.wdata = wdata_q[i];
+      myq.push_back(txn);
+    end
+  endfunction
+
+  // Receive byte stream from 'create_txn' and forward to driver's request q,
+  // with adding 'Start and Stop'.
+  // Expected transaction is created in the task.
+  // For write transaction and address transaction, expected transaction mimics acq read data.
+  // For read transaction, all read bytes for one transaction is accumulated to 'full_txn'
+  // and compared with received transaction at the scoreboard.
+  // TODO : target address will be randomly picked between target_addr0 nad target_addr1.
+  virtual function void fetch_txn(ref i2c_item src_q[$], i2c_item dst_q[$]);
+    i2c_item txn;
+    i2c_item rs_txn;
+    i2c_item exp_txn;
+    i2c_item full_txn;
+    int read_size;
+    bit is_read = get_read_write();
+
+    `uvm_info("seq", $sformatf("idx %0d:is_read:%0b size:%0d fetch_txn:%0d", start_cnt++, is_read,
+                               src_q.size(), full_txn_num++), UVM_MEDIUM)
+    print_wr_data(src_q);
+    `uvm_create_obj(i2c_item, full_txn)
+
+    // Add 'START' to the front
+    `uvm_create_obj(i2c_item, txn)
+    txn.drv_type = HostStart;
+    dst_q.push_back(txn);
+    full_txn.start = 1;
+    if (is_read) full_txn.tran_id = this.exp_rd_id++;
+    // Address
+    `uvm_create_obj(i2c_item, txn)
+    `uvm_create_obj(i2c_item, exp_txn)
+    txn.drv_type = HostData;
+    txn.start = 1;
+    txn.wdata[7:1] = target_addr0;
+    txn.wdata[0] = is_read;
+    txn.tran_id = this.tran_id++;
+    `downcast(exp_txn, txn.clone());
+    dst_q.push_back(txn);
+    full_txn.addr = txn.wdata[7:1];
+    full_txn.read = is_read;
+
+    p_sequencer.target_mode_wr_exp_port.write(exp_txn);
+    cfg.sent_acq_cnt++;
+
+    if (is_read) begin
+      read_size = src_q.size();
+      read_rcvd.push_back(read_size);
+    end
+    // Data
+    while (src_q.size() > 0) begin
+      `uvm_create_obj(i2c_item, txn)
+      txn = src_q.pop_front();
+      if (txn.drv_type != HostRStart) begin
+        // Restart only has empty data for address holder
+        full_txn.data_q.push_back(txn.wdata);
+      end
+
+      // RS creates 2 extra acq entry
+      // one for RS
+      // the other for a new start acq_entry with address
+      if (txn.drv_type == HostRStart) begin
+        bit prv_read = 0;
+        `uvm_create_obj(i2c_item, exp_txn)
+        exp_txn.drv_type = HostRStart;
+        exp_txn.rstart = 1;
+        exp_txn.tran_id = this.tran_id++;
+        p_sequencer.target_mode_wr_exp_port.write(exp_txn);
+        cfg.sent_acq_cnt++;
+        `uvm_create_obj(i2c_item, rs_txn)
+        `downcast(rs_txn, txn.clone())
+        dst_q.push_back(txn);
+
+        rs_txn.drv_type = HostData;
+        rs_txn.start = 1;
+        rs_txn.rstart = 0;
+        rs_txn.wdata[7:1] = target_addr1;
+        prv_read = is_read;
+        is_read = rs_txn.read;
+        rs_txn.wdata[0] = is_read;
+        dst_q.push_back(rs_txn);
+        // create a separate stat/addr entry for exp
+        `uvm_create_obj(i2c_item, exp_txn)
+        `downcast(exp_txn, rs_txn.clone());
+        exp_txn.tran_id = this.tran_id++;
+        p_sequencer.target_mode_wr_exp_port.write(exp_txn);
+        cfg.sent_acq_cnt++;
+        // fetch previous full_txn and creat a new one
+        if (prv_read) begin
+          full_txn.stop = 1;
+          p_sequencer.target_mode_rd_exp_port.write(full_txn);
+        end
+        `uvm_create_obj(i2c_item, full_txn)
+        `downcast(full_txn, rs_txn);
+        if (is_read) begin
+          full_txn.tran_id = exp_rd_id++;
+        end
+      end else begin
+        if (is_read) begin
+          i2c_item read_txn;
+          `uvm_create_obj(i2c_item, read_txn)
+          `downcast(read_txn, txn.clone())
+          full_txn.num_data++;
+          if (src_q.size() == 0) begin
+            txn.drv_type = HostNAck;
+          end else begin
+            // if your next item is restart Do nack
+            if (src_q[0].drv_type == HostRStart) txn.drv_type = HostNAck;
+            else txn.drv_type = HostAck;
+          end
+          dst_q.push_back(txn);
+          read_txn_q.push_back(read_txn);
+        end else begin
+          `downcast(exp_txn, txn.clone());
+          // Add RS transaction to driver only
+          // and create address transaction after
+          dst_q.push_back(txn);
+          exp_txn.tran_id = this.tran_id++;
+          p_sequencer.target_mode_wr_exp_port.write(exp_txn);
+          cfg.sent_acq_cnt++;
+        end
+      end
+    end // while (src_q.size() > 0)
+
+    // Stop
+    `uvm_create_obj(i2c_item, txn)
+    `uvm_create_obj(i2c_item, exp_txn)
+    txn.tran_id = this.tran_id++;
+    txn.stop = 1;
+    txn.drv_type = HostStop;
+    `downcast(exp_txn, txn.clone());
+    dst_q.push_back(txn);
+    full_txn.stop = 1;
+    p_sequencer.target_mode_wr_exp_port.write(exp_txn);
+    cfg.sent_acq_cnt++;
+    if (is_read) begin
+      p_sequencer.target_mode_rd_exp_port.write(full_txn);
+    end
+  endfunction
+
 endclass : i2c_base_vseq
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_target_smoke_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_target_smoke_vseq.sv
index 754c268..58042c1 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_target_smoke_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_target_smoke_vseq.sv
@@ -7,110 +7,39 @@
   `uvm_object_utils(i2c_target_smoke_vseq)
   `uvm_object_new
 
-  int tran_id;
-
   virtual task body();
     i2c_target_base_seq m_i2c_host_seq;
+    i2c_item txn_q[$];
 
     // Intialize dut in device mode and agent in host mode
     initialization(Device);
+    `uvm_info("cfg_summary", $sformatf("target_addr0:0x%x target_addr1:0x%x num_trans:%0d",
+                             target_addr0, target_addr1, num_trans), UVM_MEDIUM)
+    print_time_property();
 
-    for (int i = 0; i < 2; i++) begin
-      get_timing_values();
-      program_registers();
+    fork
+      begin
+        for (int i = 0; i < num_trans; i++) begin
+          get_timing_values();
+          if (i > 0) begin
+            // wait for previous stop before program a new timing param.
+            @(cfg.m_i2c_agent_cfg.got_stop);
+          end
+          program_registers();
 
-      `uvm_create_obj(i2c_target_base_seq, m_i2c_host_seq)
-
-      create_write_txn(m_i2c_host_seq);
-      m_i2c_host_seq.start(p_sequencer.i2c_sequencer_h);
-    end
+          `uvm_create_obj(i2c_target_base_seq, m_i2c_host_seq)
+          create_txn(txn_q);
+          fetch_txn(txn_q, m_i2c_host_seq.req_q);
+          m_i2c_host_seq.start(p_sequencer.i2c_sequencer_h);
+        end
+      end
+      begin
+        process_acq();
+      end
+      begin
+        process_txq();
+      end
+    join_none
   endtask : body
 
-  // Use for debug only
-  function void print_time_property();
-    `uvm_info(`gfn, $sformatf("timing_prop"), UVM_MEDIUM)
-    // high period of the SCL in clock units
-    `uvm_info(`gfn, $sformatf("thigh:%0d", thigh), UVM_MEDIUM);
-    // low period of the SCL in clock units
-    `uvm_info(`gfn, $sformatf("tlow:%0d", tlow), UVM_MEDIUM);
-    // rise time of both SDA and SCL in clock units
-    `uvm_info(`gfn, $sformatf("t_r:%0d", t_r), UVM_MEDIUM);
-    // fall time of both SDA and SCL in clock units
-    `uvm_info(`gfn, $sformatf("t_f:%0d", t_f), UVM_MEDIUM);
-    // hold time for (repeated) START in clock units
-    `uvm_info(`gfn, $sformatf("thd_sta:%0d", thd_sta), UVM_MEDIUM);
-    // setup time for repeated START in clock units
-    `uvm_info(`gfn, $sformatf("tsu_sta:%0d", tsu_sta), UVM_MEDIUM);
-    // setup time for STOP in clock units
-    `uvm_info(`gfn, $sformatf("tsu_sto:%0d", tsu_sto), UVM_MEDIUM);
-    // data setup time in clock units
-    `uvm_info(`gfn, $sformatf("tsu_dat:%0d", tsu_dat), UVM_MEDIUM);
-    // data hold time in clock units
-    `uvm_info(`gfn, $sformatf("thd_dat:%0d", thd_dat), UVM_MEDIUM);
-    // bus free time between STOP and START in clock units
-    `uvm_info(`gfn, $sformatf("t_buf:%0d", t_buf), UVM_MEDIUM);
-    // max time target may stretch the clock
-    `uvm_info(`gfn, $sformatf("t_timeout:%0d", t_timeout), UVM_MEDIUM);
-    // max time target may stretch the clock
-    `uvm_info(`gfn, $sformatf("e_timeout:%0d", e_timeout), UVM_MEDIUM);
-    // sda unstable time during the posedge_clock
-    `uvm_info(`gfn, $sformatf("t_sda_unstable:%0d", t_sda_unstable), UVM_MEDIUM);
-    // sda interference time during the posedge_clock
-    `uvm_info(`gfn, $sformatf("t_sda_interference:%0d", t_sda_interference), UVM_MEDIUM);
-    // scl interference time during the posedge_clock
-    `uvm_info(`gfn, $sformatf("t_scl_interference:%0d", t_scl_interference), UVM_MEDIUM);
-    `uvm_info(`gfn, $sformatf("error intrs probability"), UVM_MEDIUM)
-    `uvm_info(`gfn, $sformatf("prob_sda_unstable:%0d    ", prob_sda_unstable), UVM_MEDIUM);
-    `uvm_info(`gfn, $sformatf("prob_sda_interference:%0d", prob_sda_interference), UVM_MEDIUM);
-    `uvm_info(`gfn, $sformatf("prob_scl_interference:%0d", prob_scl_interference), UVM_MEDIUM);
-  endfunction
-
-   task create_write_txn(ref i2c_target_base_seq seq);
-      bit [7:0] wdata_q[$];
-      i2c_item txn;
-      i2c_item exp_txn;
-
-      int txn_size;
-
-      `uvm_create_obj(i2c_item, txn)
-      `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(wdata_q,
-                                     wdata_q.size() inside {
-                                     [cfg.seq_cfg.min_data : cfg.seq_cfg.max_data]};)
-      // data + address
-      `uvm_info(`gfn, $sformatf("byte0:0x%x (addr:0x%x) wdataq:%p",
-                                {target_addr0, 1'b0}, target_addr0, wdata_q), UVM_MEDIUM)
-      txn_size = wdata_q.size() + 1;
-      txn.drv_type = HostStart;
-      // skip the first transaction to pass sb because
-      // start and address are coalescing in acq fifo.
-     seq.req_q.push_back(txn);
-     for (int i = 0; i < txn_size; i++) begin
-       `uvm_create_obj(i2c_item, txn)
-       `uvm_create_obj(i2c_item, exp_txn)
-       txn.drv_type = HostData;
-       txn.stop = 0;
-       txn.tran_id = this.tran_id++;
-       if (i == 0) begin
-         txn.start = 1;
-         txn.wdata[7:1] = target_addr0;
-         txn.wdata[0] = 1'b0;
-
-       end else begin
-         txn.start = 0;
-         txn.wdata = wdata_q[i-1];
-       end
-
-       `downcast(exp_txn, txn.clone());
-       seq.req_q.push_back(txn);
-       p_sequencer.target_mode_wr_exp_port.write(exp_txn);
-     end
-     `uvm_create_obj(i2c_item, txn)
-     `uvm_create_obj(i2c_item, exp_txn)
-     txn.tran_id = this.tran_id++;
-     txn.stop = 1;
-     txn.drv_type = HostStop;
-     `downcast(exp_txn, txn.clone());
-     seq.req_q.push_back(txn);
-     p_sequencer.target_mode_wr_exp_port.write(exp_txn);
-   endtask
 endclass : i2c_target_smoke_vseq
diff --git a/hw/ip/i2c/dv/i2c_sim_cfg.hjson b/hw/ip/i2c/dv/i2c_sim_cfg.hjson
index a3189de..9efa40d 100644
--- a/hw/ip/i2c/dv/i2c_sim_cfg.hjson
+++ b/hw/ip/i2c/dv/i2c_sim_cfg.hjson
@@ -123,7 +123,7 @@
     {
       name: i2c_target_smoke
       uvm_test_seq: i2c_target_smoke_vseq
-      run_opts: ["+i2c_agent_mode=Host", "+test_timeout_ns=100_000"]
+      run_opts: ["+i2c_agent_mode=Host", "+test_timeout_ns=10_000_000"]
     }
   ]