blob: e87628dfd14eab4eb9402182f6e5c838ba1038a4 [file] [log] [blame]
Tung Hoanga0877072019-09-23 19:08:35 -07001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5class i2c_device_driver extends i2c_driver;
6 `uvm_component_utils(i2c_device_driver)
Tung Hoanga0877072019-09-23 19:08:35 -07007 `uvm_component_new
8
Tung Hoang02986542020-07-11 00:24:49 -07009 rand bit [7:0] rd_data[256]; // max length of read transaction
Tung Hoanga0877072019-09-23 19:08:35 -070010
Tung Hoang02986542020-07-11 00:24:49 -070011 // get an array with unique read data
12 constraint rd_data_c {
13 unique { rd_data };
14 }
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070015
Tung Hoanga0877072019-09-23 19:08:35 -070016 virtual task get_and_drive();
Tung Hoang02986542020-07-11 00:24:49 -070017 uint num_stretch_host_clks;
Tung Hoange3749bd2020-07-17 11:33:38 -070018 bit [7:0] rd_data_cnt = 8'd0;
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070019 i2c_item rsp_item;
Tung Hoangf4135862020-06-16 13:22:11 -070020
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070021 @(posedge cfg.vif.rst_ni);
Tung Hoange357e492020-01-28 09:39:35 -080022 forever begin
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070023 cfg.vif.scl_o = 1'b1;
24 cfg.vif.sda_o = 1'b1;
25 // device driver responses to dut
26 seq_item_port.get_next_item(rsp_item);
27 unique case (rsp_item.drv_type)
28 DevAck: begin
Tung Hoangf4135862020-06-16 13:22:11 -070029 fork
30 begin
31 // host clock stretching allows a high-speed host to communicate
32 // with a low-speed device by setting TIMEOUT_CTRL.EN bit
33 // the device ask host clock stretching its clock scl_i by pulling down scl_o
34 // the host clock pulse is extended until device scl_o is pulled up
35 // once scl_o is pulled down longer than TIMEOUT_CTRL.VAL field,
36 // intr_stretch_timeout_o is asserted (ref. https://www.i2c-bus.org/clock-stretching)
37 if (cfg.timing_cfg.enbTimeOut) begin
38 num_stretch_host_clks = gen_num_stretch_host_clks(cfg.timing_cfg);
39 cfg.vif.device_stretch_host_clk(cfg.timing_cfg, num_stretch_host_clks);
40 end
41 end
42 begin
43 cfg.vif.device_send_ack(cfg.timing_cfg);
44 end
45 join
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070046 end
47 RdData: begin
Tung Hoange3749bd2020-07-17 11:33:38 -070048 if (rd_data_cnt == 8'd0) `DV_CHECK_MEMBER_RANDOMIZE_FATAL(rd_data)
Tung Hoang6d5e7c52020-06-11 14:14:14 -070049 for (int i = 7; i >= 0; i--) begin
Tung Hoang02986542020-07-11 00:24:49 -070050 cfg.vif.device_send_bit(cfg.timing_cfg, rd_data[rd_data_cnt][i]);
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070051 end
Tung Hoange3749bd2020-07-17 11:33:38 -070052 // rd_data_cnt is rollled back (no overflow) after reading 256 bytes
53 rd_data_cnt++;
Tung Hoang02986542020-07-11 00:24:49 -070054 `uvm_info(`gfn, $sformatf("driver, trans %0d, byte %0d %0x",
55 rsp_item.tran_id, rsp_item.num_data+1, rd_data[rd_data_cnt]), UVM_DEBUG)
Tung Hoangdd0a2ed2020-05-19 16:12:48 -070056 end
57 default: begin
58 `uvm_fatal(`gfn, $sformatf("driver, received invalid request from monitor/seq"))
59 end
60 endcase
61 seq_item_port.item_done();
Tung Hoange357e492020-01-28 09:39:35 -080062 end
63 endtask : get_and_drive
Tung Hoanga0877072019-09-23 19:08:35 -070064
Tung Hoangf4135862020-06-16 13:22:11 -070065 function int gen_num_stretch_host_clks(ref timing_cfg_t tc);
66 // By randomly pulling down scl_o "offset" within [0:2*tc.tTimeOut],
67 // intr_stretch_timeout_o interrupt would be generated uniformly
68 // To test this feature more regressive, there might need a dedicated vseq (V2)
69 // in which TIMEOUT_CTRL.EN is always set.
70 return $urandom_range(tc.tClockPulse, tc.tClockPulse + 2*tc.tTimeOut);
71 endfunction : gen_num_stretch_host_clks
72
Tung Hoange357e492020-01-28 09:39:35 -080073endclass : i2c_device_driver
74