~ruther/vhdl-i2c

ref: 068391c6bc2692b546faaabffcd4dcc2e0a5aed8 vhdl-i2c/tb/i2c/rx_tb.vhd -rw-r--r-- 6.2 KiB
068391c6 — Rutherther feat: add slave top 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
library ieee;
use ieee.std_logic_1164.all;

library i2c;

library vunit_lib;
context vunit_lib.vunit_context;

entity rx_tb is

  generic (
    runner_cfg : string);

end entity rx_tb;

architecture a1 of rx_tb is
  signal clk : std_logic := '0';
  constant CLK_PERIOD : time := 10 ns;

  signal rst_n : std_logic := '0';

  signal sda : std_logic := '0';
  signal scl_rising_pulse, scl_falling_pulse : std_logic := '0';

  signal start_read : std_logic := '0';
  signal valid, ready : std_logic;
  signal scl_stretch : std_logic;
  signal sda_enable : std_logic;

  signal confirm_read : std_logic := '0';
  signal read_data : std_logic_vector(7 downto 0);

  procedure trigger_scl_pulse(
    signal scl_rising_pulse : inout std_logic;
    signal scl_falling_pulse : inout std_logic) is
  begin  -- procedure trigger_scl_pulse
    scl_rising_pulse <= '0';
    scl_falling_pulse <= '0';
    wait until falling_edge(clk);
    scl_rising_pulse <= '1';
    wait until falling_edge(clk);
    scl_rising_pulse <= '0';
    scl_falling_pulse <= '1';
    wait until falling_edge(clk);
    scl_rising_pulse <= '0';
    scl_falling_pulse <= '0';
  end procedure trigger_scl_pulse;

  procedure transmit (
    constant data            : in    std_logic_vector(7 downto 0);
    constant check_valid     : in    std_logic;
    constant check_ready     : in    std_logic;
    signal start_read        : inout std_logic;
    signal sda               : inout std_logic;
    signal scl_rising_pulse  : inout std_logic;
    signal scl_falling_pulse : inout std_logic) is
  begin  -- procedure a
    start_read <= '1';
    wait until falling_edge(clk);
    start_read <= '0';
    for i in 7 downto 0 loop
      if check_valid /= 'Z' then
        check_equal(valid, check_valid);
      end if;

      if check_ready /= 'Z' then
        check_equal(ready, check_ready);
      end if;

      check(scl_stretch = '0', "Cannot send when stretch is active", failure);

      sda <= data(i);
      trigger_scl_pulse(scl_rising_pulse, scl_falling_pulse);
    end loop;  -- i

    -- ack
    check_equal(sda_enable, '1');

    trigger_scl_pulse(scl_rising_pulse, scl_falling_pulse);

    check_equal(sda_enable, '0');
  end procedure transmit;
begin  -- architecture a1
  uut : entity i2c.rx
    port map (
      clk_i                 => clk,
      rst_in                => rst_n,
      ss_condition_i        => '0',
      generate_ack_i        => '1',
      start_read_i          => start_read,
      scl_pulse_i           => scl_rising_pulse,
      scl_falling_delayed_i => scl_falling_pulse,
      sda_i                 => sda,
      sda_enable_o          => sda_enable,
      scl_stretch_o         => scl_stretch,
      read_valid_o          => valid,
      read_ready_o          => ready,
      read_data_o           => read_data,
      confirm_read_i        => confirm_read);

  clk <= not clk after CLK_PERIOD / 2;
  rst_n <= '1' after 2 * CLK_PERIOD;

  main: process is
  begin  -- process
    wait until rst_n = '1';
    wait until falling_edge(clk);
    test_runner_setup(runner, runner_cfg);
    set_stop_level(failure);

    while test_suite loop
      if run("simple") then
        transmit("11010100", '0', '1', start_read, sda, scl_rising_pulse, scl_falling_pulse);
        check_equal(valid, '1');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
        check_equal(read_data, std_logic_vector'("11010100"));

        confirm_read <= '1';
        wait until falling_edge(clk);
        confirm_read <= '0';
        check_equal(valid, '0');
        check_equal(ready, '1');
      elsif run("twice") then
        transmit("11010100", '0', '1', start_read, sda, scl_rising_pulse, scl_falling_pulse);
        check_equal(valid, '1');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
        check_equal(read_data, std_logic_vector'("11010100"));
        confirm_read <= '1';
        wait until falling_edge(clk);
        confirm_read <= '0';
        check_equal(valid, '0');
        check_equal(ready, '1');

        transmit("00111100", '0', '1', start_read, sda, scl_rising_pulse, scl_falling_pulse);
        check_equal(valid, '1');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
        check_equal(read_data, std_logic_vector'("00111100"));
        confirm_read <= '1';
        wait until falling_edge(clk);
        confirm_read <= '0';
        check_equal(valid, '0');
        check_equal(ready, '1');
      elsif run("stretching") then
        transmit("11010100", '0', '1', start_read, sda, scl_rising_pulse, scl_falling_pulse);
        check_equal(valid, '1');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
        check_equal(read_data, std_logic_vector'("11010100"));

        transmit("10000001", '1', '1', start_read, sda, scl_rising_pulse, scl_falling_pulse);
        check_equal(valid, '1');
        check_equal(ready, '0');
        check_equal(scl_stretch, '0');
        check_equal(read_data, std_logic_vector'("11010100"));

        start_read <= '1';
        wait until falling_edge(clk);
        start_read <= '0';

        check_equal(read_data, std_logic_vector'("11010100"));
        check_equal(valid, '1');
        check_equal(ready, '0');
        check_equal(scl_stretch, '1');

        for i in 0 to 5 loop
          wait until falling_edge(clk);
          check_equal(scl_stretch, '1');
        end loop;  -- i

        confirm_read <= '1';
        wait until falling_edge(clk);
        confirm_read <= '1';
        check_equal(read_data, std_logic_vector'("10000001"));
        check_equal(valid, '1');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
        wait until falling_edge(clk);
        confirm_read <= '0';
        check_equal(valid, '0');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');

        transmit("00000011", '0', '1', start_read, sda, scl_rising_pulse, scl_falling_pulse);
        check_equal(read_data, std_logic_vector'("00000011"));
        check_equal(valid, '1');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
        confirm_read <= '1';
        wait until falling_edge(clk);
        check_equal(valid, '0');
        check_equal(ready, '1');
        check_equal(scl_stretch, '0');
      end if;
    end loop;

    test_runner_cleanup(runner);
  end process;

end architecture a1;
Do not follow this link