~ruther/vhdl-i2c

ref: b150548edc2f8f5fcf94de1c27753a48480c0897 vhdl-i2c/tb/i2c/model/i2c_bus_mod.vhd -rw-r--r-- 5.0 KiB
b150548e — Rutherther docs: add presentation 1 year, 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
library ieee;
use ieee.std_logic_1164.all;

library vunit_lib;
context vunit_lib.vunit_context;
context vunit_lib.com_context;

use work.i2c_bus_pkg.all;

entity i2c_bus_mod is

  generic (
    inst_name : string;
    default_stretch_timeout: time;
    default_scl_freq: real);

  port (
    sda_io : inout std_logic;
    scl_io : inout std_logic);

end entity i2c_bus_mod;

architecture behav of i2c_bus_mod is
  constant logger : logger_t := get_logger("i2c_bus_mod::" & inst_name);
  constant checker : checker_t := new_checker(logger);

  signal s_free_sda_req : event_t := new_event("free sda");
  signal s_free_scl_req : event_t := new_event("free scl");

  signal s_start_cond_req : event_t := new_event("start cond gen");
  signal s_stop_cond_req : event_t := new_event("stop cond gen");

  signal s_data_req : event_t := new_event("gen data");
  signal s_clk_req : event_t := new_event("gen data");

  signal s_scl_stretch_timeout : time := default_stretch_timeout;
  signal s_scl_frequency : real := default_scl_freq;

  signal s_request_clks_count : natural;
  signal s_request_data : std_logic_vector(1023 downto 0);

  signal s_auto_ack_req : event_t := new_event("auto ack");
  signal s_auto_ack_address : std_logic_vector(6 downto 0);
  signal s_auto_ack_active : boolean;
  signal s_auto_ack_count : natural;

  procedure wait_for_start (
    signal sda        : inout std_logic;
    signal scl        : inout std_logic;
    constant timeout : in time);

  procedure wait_for_stop (
    signal sda        : inout std_logic;
    signal scl        : inout std_logic;
    constant timeout : in time);

  procedure wait_for_clock (
    signal sda        : inout std_logic;
    signal scl        : inout std_logic;
    constant timeout : in time);

  procedure write_bit (
    signal sda        : inout std_logic;
    signal scl        : inout std_logic;
    constant data     : in    std_logic;
    constant timeout  : in    time;
    variable continue : inout boolean);

  function read_bit (
    signal sda        : inout std_logic;
    signal scl        : inout std_logic;
    constant data     : in    std_logic;
    constant timeout  : in    time;
    variable continue : inout boolean) return std_logic;

  function read_data (
    signal sda        : inout std_logic;
    signal scl        : inout std_logic;
    constant timeout  : in    time;
    variable continue : inout boolean) return std_logic_vector;

begin  -- architecture behav

  message_handler: process is
    constant self : actor_t := new_actor(inst_name);

    variable msg : msg_t;
    variable msg_type : msg_type_t;
  begin  -- process message_handler
    receive(net, self, msg);
    msg_type := message_type(msg);

    if msg_type = free_bus_msg then
      notify(s_free_scl_req);
      notify(s_free_sda_req);
    elsif msg_type = set_scl_freq_msg then
      v_frequency := pop(msg);
      s_scl_frequency <= v_frequency;
      s_scl_period <= get_period(v_frequency);
    elsif msg_type = gen_start_cond_msg then
      notify(s_start_cond_req);
      wait until is_active(s_start_cond_done);
    elsif msg_type = gen_stop_cond_msg then
      s_timeout <= pop(msg);
      notify(s_stop_cond_req);
      wait until is_active(s_stop_cond_done);
    elsif msg_type = gen_clocks_msg then
      s_clk_count <= pop(msg);
      s_timeout <= pop(msg);
      notify(s_gen_clk_req);
      wait until is_active(s_gen_clk_done);
    elsif msg_type = send_data_msg then
      s_data_count <= pop(msg);
      s_data <= pop(msg);
      s_timeout <= pop(msg);
      notify(s_data_req);
      wait until is_active(s_data_req);
    elsif msg_type = send_data_clocks_msg then
      v_count := pop(msg);
      s_data_count <= v_count;
      s_clk_count <= v_count;
      s_data <= pop(msg);
      s_timeout <= pop(msg);
      notify(s_gen_clk_req, s_data_clk_req);
      wait until is_active(s_gen_clk_done);
    elsif msg_type = auto_ack_msg then
      s_auto_ack_active <= pop(msg);
      s_auto_ack_address <= pop(msg);
      s_auto_ack_count <= pop(msg);
      notify(s_auto_ack_req);
    elsif msg_type = wait_start_cond_msg then
      wait_for_start(sda_io, scl_io, pop(msg));
    elsif msg_type = wait_stop_cond_msg then
      wait_for_stop(sda_io, scl_io, pop(msg));
    elsif msg_type = wait_clocks_msg then
      v_count := pop(msg);
      v_timeout := pop(msg);
      for i in 1 to v_count loop
        wait_for_clock(sda_io, scl_io, v_timeout);
      end loop;  -- i
    elsif msg_type = check_data_msg then
      s_data_count <= pop(msg);
      s_data_exp <= pop(msg);
      s_timeout <= pop(msg);
      notify(s_check_data_req);
      wait until is_active(s_check_data_done);
    elsif msg_type = check_data_clocks_msg then
      v_count := pop(msg);
      s_data_count <= v_count;
      s_clk_count <= v_count;
      s_data_exp <= pop(msg);
      s_timeout <= pop(msg);
      notify(s_gen_clk_req, s_check_data_req);
      wait until is_active(s_gen_clk_done);
    elsif msg_type = wait_until_idle then
      acknowledge(net, msg, true);
    end if;

  end process message_handler;

end architecture behav;
Do not follow this link