Tung Hoang | a087707 | 2019-09-23 19:08:35 -0700 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | class i2c_device_driver extends i2c_driver; |
| 6 | `uvm_component_utils(i2c_device_driver) |
Tung Hoang | a087707 | 2019-09-23 19:08:35 -0700 | [diff] [blame] | 7 | `uvm_component_new |
| 8 | |
Tung Hoang | 0298654 | 2020-07-11 00:24:49 -0700 | [diff] [blame] | 9 | rand bit [7:0] rd_data[256]; // max length of read transaction |
Tung Hoang | a087707 | 2019-09-23 19:08:35 -0700 | [diff] [blame] | 10 | |
Tung Hoang | 0298654 | 2020-07-11 00:24:49 -0700 | [diff] [blame] | 11 | // get an array with unique read data |
| 12 | constraint rd_data_c { |
| 13 | unique { rd_data }; |
| 14 | } |
Tung Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 15 | |
Tung Hoang | a087707 | 2019-09-23 19:08:35 -0700 | [diff] [blame] | 16 | virtual task get_and_drive(); |
Tung Hoang | 0298654 | 2020-07-11 00:24:49 -0700 | [diff] [blame] | 17 | uint num_stretch_host_clks; |
Tung Hoang | e3749bd | 2020-07-17 11:33:38 -0700 | [diff] [blame^] | 18 | bit [7:0] rd_data_cnt = 8'd0; |
Tung Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 19 | i2c_item rsp_item; |
Tung Hoang | f413586 | 2020-06-16 13:22:11 -0700 | [diff] [blame] | 20 | |
Tung Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 21 | @(posedge cfg.vif.rst_ni); |
Tung Hoang | e357e49 | 2020-01-28 09:39:35 -0800 | [diff] [blame] | 22 | forever begin |
Tung Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 23 | 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 Hoang | f413586 | 2020-06-16 13:22:11 -0700 | [diff] [blame] | 29 | 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 Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 46 | end |
| 47 | RdData: begin |
Tung Hoang | e3749bd | 2020-07-17 11:33:38 -0700 | [diff] [blame^] | 48 | if (rd_data_cnt == 8'd0) `DV_CHECK_MEMBER_RANDOMIZE_FATAL(rd_data) |
Tung Hoang | 6d5e7c5 | 2020-06-11 14:14:14 -0700 | [diff] [blame] | 49 | for (int i = 7; i >= 0; i--) begin |
Tung Hoang | 0298654 | 2020-07-11 00:24:49 -0700 | [diff] [blame] | 50 | cfg.vif.device_send_bit(cfg.timing_cfg, rd_data[rd_data_cnt][i]); |
Tung Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 51 | end |
Tung Hoang | e3749bd | 2020-07-17 11:33:38 -0700 | [diff] [blame^] | 52 | // rd_data_cnt is rollled back (no overflow) after reading 256 bytes |
| 53 | rd_data_cnt++; |
Tung Hoang | 0298654 | 2020-07-11 00:24:49 -0700 | [diff] [blame] | 54 | `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 Hoang | dd0a2ed | 2020-05-19 16:12:48 -0700 | [diff] [blame] | 56 | 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 Hoang | e357e49 | 2020-01-28 09:39:35 -0800 | [diff] [blame] | 62 | end |
| 63 | endtask : get_and_drive |
Tung Hoang | a087707 | 2019-09-23 19:08:35 -0700 | [diff] [blame] | 64 | |
Tung Hoang | f413586 | 2020-06-16 13:22:11 -0700 | [diff] [blame] | 65 | 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 Hoang | e357e49 | 2020-01-28 09:39:35 -0800 | [diff] [blame] | 73 | endclass : i2c_device_driver |
| 74 | |