GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/axi/tb_axi_lite_mux.vhd Lines: 110 110 100.0 %
Date: 2021-06-12 04:12:08 Branches: 428 593 72.2 %

Line Branch Exec Source
1
18
-- -------------------------------------------------------------------------------------------------
2
-- Copyright (c) Lukas Vik. All rights reserved.
3
--
4
-- This file is part of the tsfpga project.
5
-- https://tsfpga.com
6
-- https://gitlab.com/tsfpga/tsfpga
7
-- -------------------------------------------------------------------------------------------------
8
9
library ieee;
10
use ieee.std_logic_1164.all;
11
use ieee.numeric_std.all;
12
13
library vunit_lib;
14
use vunit_lib.memory_pkg.all;
15
context vunit_lib.vunit_context;
16
context vunit_lib.vc_context;
17
18
library osvvm;
19
use osvvm.RandomPkg.all;
20
21
library bfm;
22
23
library common;
24
use common.addr_pkg.all;
25
26
use work.axi_lite_pkg.all;
27
28
29



























31
entity tb_axi_lite_mux is
30
  generic (
31




401
    use_axi_lite_bfm : boolean := true;
32

69
    runner_cfg : string
33
12
  );
34
end entity;
35
780
36


1596
architecture tb of tb_axi_lite_mux is
37
38


1647
  constant data_width : integer := 32;
39

63
  constant bytes_per_word : integer := data_width / 8;
40
3
  constant num_slaves : integer := 4;
41


603
  subtype slaves_rng is integer range 0 to num_slaves - 1;
42
411
43
3
  constant num_words : integer := 32;
44






4842
  constant addr_offset : integer := 4096; -- Corresponding to the base addresses below
45
834
46
3
  constant slave_addrs : addr_and_mask_vec_t(slaves_rng) := (
47
    (addr => x"0000_0000", mask => x"0000_7000"),
48
    (addr => x"0000_1000", mask => x"0000_7000"),
49
    (addr => x"0000_2000", mask => x"0000_7000"),
50
    (addr => x"0000_3000", mask => x"0000_7000")
51
  );
52
53
3
  constant clk_period : time := 10 ns;
54
3
  signal clk : std_logic := '0';
55
56
1203
  signal axi_lite_m2s, hard_coded_m2s : axi_lite_m2s_t;
57
207
  signal axi_lite_s2m : axi_lite_s2m_t;
58
59
2415
  signal axi_lite_m2s_vec : axi_lite_m2s_vec_t(slaves_rng);
60
831
  signal axi_lite_s2m_vec : axi_lite_s2m_vec_t(slaves_rng);
61
62
3
  constant axi_master : bus_master_t := new_bus(data_length => data_width, address_length => axi_lite_m2s.read.ar.addr'length);
63
64
  type memory_vec_t is array (integer range <>) of memory_t;
65
15
  constant memory : memory_vec_t (slaves_rng) := (
66
    0 => new_memory,
67
    1 => new_memory,
68
    2 => new_memory,
69
    3 => new_memory
70
  );
71
72
  type axi_slave_vec_t is array (integer range <>) of axi_slave_t;
73
27
  constant axi_read_slave, axi_write_slave : axi_slave_vec_t(slaves_rng) := (
74
    0 => new_axi_slave(address_fifo_depth => 1, memory => memory(0)),
75
    1 => new_axi_slave(address_fifo_depth => 1, memory => memory(1)),
76
    2 => new_axi_slave(address_fifo_depth => 1, memory => memory(2)),
77
    3 => new_axi_slave(address_fifo_depth => 1, memory => memory(3))
78
  );
79
80
begin
81
82
2381
  test_runner_watchdog(runner, 2 ms);
83
2363
  clk <= not clk after clk_period / 2;
84
85
86
  ------------------------------------------------------------------------------
87
3
  main : process
88
89
  function bank_address(slave, word : integer) return integer is
90
    begin
91
272
      return slave * addr_offset + word * bytes_per_word;
92
    end function;
93
94

51
    procedure hard_coded_read_data(addr : in unsigned(slave_addrs(0).addr'range)) is
95
    begin
96

4
      hard_coded_m2s.read.ar.valid <= '1';
97



260
      hard_coded_m2s.read.ar.addr <= x"0000_0000" & addr;
98

31
      wait until (axi_lite_s2m.read.ar.ready and axi_lite_m2s.read.ar.valid) = '1' and rising_edge(clk);
99

4
      hard_coded_m2s.read.ar.valid <= '0';
100
101

4
      hard_coded_m2s.read.r.ready <= '1';
102

20
      wait until (axi_lite_m2s.read.r.ready and axi_lite_s2m.read.r.valid) = '1' and rising_edge(clk);
103

16
      hard_coded_m2s.read.r.ready <= '0';
104
    end procedure;
105
106


67
    procedure hard_coded_write_data(addr : in unsigned(slave_addrs(0).addr'range);
107
                                    data : in std_logic_vector(data_width - 1 downto 0)) is
108
    begin
109

4
      hard_coded_m2s.write.aw.valid <= '1';
110



260
      hard_coded_m2s.write.aw.addr <= x"0000_0000" & addr;
111

31
      wait until (axi_lite_s2m.write.aw.ready and axi_lite_m2s.write.aw.valid) = '1' and rising_edge(clk);
112

4
      hard_coded_m2s.write.aw.valid <= '0';
113
114

4
      hard_coded_m2s.write.w.valid <= '1';
115



260
      hard_coded_m2s.write.w.data <= x"0000_0000" & data;
116

36
      hard_coded_m2s.write.w.strb <= x"0f";
117

20
      wait until (axi_lite_s2m.write.w.ready and axi_lite_m2s.write.w.valid) = '1' and rising_edge(clk);
118

4
      hard_coded_m2s.write.w.valid <= '0';
119
120

4
      hard_coded_m2s.write.b.ready <= '1';
121

20
      wait until (axi_lite_m2s.write.b.ready and axi_lite_s2m.write.b.valid) = '1' and rising_edge(clk);
122






















2275
      hard_coded_m2s.write.b.ready <= '0';
123
    end procedure;
124
125
3
    variable rnd : RandomPType;
126
99
    variable data : std_logic_vector(data_width - 1 downto 0);
127
3
    variable address : integer;
128
615
    variable buf : buffer_t;
129
130
  begin
131
9
    test_runner_setup(runner, runner_cfg);
132
6
    rnd.InitSeed(rnd'instance_name);
133
134
3
    for slave_idx in memory'range loop
135

12
      buf := allocate(memory(slave_idx), bank_address(slave_idx, num_words));
136
    end loop;
137
138
3
    if run("read_and_write_to_buffer") then
139
1
      for slave_idx in memory'range loop
140
4
        for word in 0 to num_words - 1 loop
141
128
          address := bank_address(slave_idx, word);
142
128
          data := rnd.RandSLV(data'length);
143

256
          set_expected_word(memory(slave_idx), address, data);
144
145
          -- Call is non-blocking. I.e. we will build up a queue of writes.
146

384
          write_bus(net, axi_master, address, data);
147


647
          wait until rising_edge(clk);
148
        end loop;
149
      end loop;
150
5
      wait_until_idle(net, as_sync(axi_master));
151
152
      -- Test that everything was written correctly to memory
153
1
      for slave_idx in memory'range loop
154

16
        check_expected_was_written(memory(slave_idx));
155
      end loop;
156
157
      -- Test reading back data
158
1
      for slave_idx in memory'range loop
159
4
        for word in 0 to num_words - 1 loop
160
128
          address := bank_address(slave_idx, word);
161

128
          data := read_word(memory(slave_idx), address, 4);
162
163


777
          check_bus(net, axi_master, address, data);
164
        end loop;
165
      end loop;
166
167
2
    elsif run("read_from_non_existent_slave_base_address") then
168
10
      hard_coded_read_data(x"0000_4000");
169
2
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_decerr, line_num => 169, file_name => "tb_axi_lite_mux.vhd");
170
171
1
      data := rnd.RandSLV(data'length);
172

2
      write_word(memory(0), bank_address(0, 0), data);
173
11
      hard_coded_read_data(slave_addrs(0).addr);
174
2
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_okay, line_num => 174, file_name => "tb_axi_lite_mux.vhd");
175
2
      check_equal(axi_lite_s2m.read.r.data(data'range), data, line_num => 175, file_name => "tb_axi_lite_mux.vhd");
176
177
11
      hard_coded_read_data(x"0000_5000");
178
2
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_decerr, line_num => 178, file_name => "tb_axi_lite_mux.vhd");
179
180
1
      data := rnd.RandSLV(data'length);
181

2
      write_word(memory(1), bank_address(1, 0), data);
182
11
      hard_coded_read_data(slave_addrs(1).addr);
183
2
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_okay, line_num => 183, file_name => "tb_axi_lite_mux.vhd");
184
3
      check_equal(axi_lite_s2m.read.r.data(data'range), data, line_num => 184, file_name => "tb_axi_lite_mux.vhd");
185
186

4
    elsif run("write_to_non_existent_slave_base_address") then
187
13
      hard_coded_write_data(x"0000_4000", x"0102_0304");
188
2
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_decerr, line_num => 188, file_name => "tb_axi_lite_mux.vhd");
189
190
1
      data := rnd.RandSLV(data'length);
191

2
      set_expected_word(memory(0), bank_address(0, 0), data);
192
14
      hard_coded_write_data(slave_addrs(0).addr, data);
193
2
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_okay, line_num => 193, file_name => "tb_axi_lite_mux.vhd");
194
2
      check_expected_was_written(memory(0));
195
196
14
      hard_coded_write_data(x"0000_5000", x"0102_0304");
197
2
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_decerr, line_num => 197, file_name => "tb_axi_lite_mux.vhd");
198
199
1
      data := rnd.RandSLV(data'length);
200

2
      set_expected_word(memory(1), bank_address(1, 0), data);
201
14
      hard_coded_write_data(slave_addrs(1).addr, data);
202
2
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_okay, line_num => 202, file_name => "tb_axi_lite_mux.vhd");
203
3
      check_expected_was_written(memory(1));
204
    end if;
205
206
1528
    test_runner_cleanup(runner);
207
  end process;
208
209
210
  ------------------------------------------------------------------------------
211
  axi_lite_master_generate : if use_axi_lite_bfm generate
212
4
    axi_lite_master_inst : entity bfm.axi_lite_master
213
      generic map (
214
        bus_handle => axi_master
215
      )
216
      port map (
217
        clk => clk,
218
219
        axi_lite_m2s => axi_lite_m2s,
220
        axi_lite_s2m => axi_lite_s2m
221
      );
222
223
  else generate
224
225











5252
    axi_lite_m2s <= hard_coded_m2s;
226
  end generate;
227
228
229
  ------------------------------------------------------------------------------
230
  axi_lite_slave_gen : for i in axi_read_slave'range generate
231
18
  begin
232

12
    axi_lite_slave_inst : entity bfm.axi_lite_slave
233
      generic map (
234
        axi_read_slave => axi_read_slave(i),
235
        axi_write_slave => axi_write_slave(i),
236
        data_width => data_width
237
      )
238
      port map (
239
        clk => clk,
240
        --
241
        axi_lite_read_m2s => axi_lite_m2s_vec(i).read,
242
        axi_lite_read_s2m => axi_lite_s2m_vec(i).read,
243
        --
244
        axi_lite_write_m2s => axi_lite_m2s_vec(i).write,
245
        axi_lite_write_s2m => axi_lite_s2m_vec(i).write
246
      );
247
  end generate;
248
249
250
  ------------------------------------------------------------------------------
251
3
  dut : entity work.axi_lite_mux
252
    generic map (
253
      slave_addrs => slave_addrs
254
    )
255
    port map (
256
      clk => clk,
257
258
      axi_lite_m2s => axi_lite_m2s,
259
      axi_lite_s2m => axi_lite_s2m,
260
261
      axi_lite_m2s_vec => axi_lite_m2s_vec,
262
      axi_lite_s2m_vec => axi_lite_s2m_vec
263
    );
264
265
end architecture;