GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/reg_file/tb_axi_lite_reg_file.vhd Lines: 105 105 100.0 %
Date: 2021-06-12 04:12:08 Branches: 426 564 75.5 %

Line Branch Exec Source
1
30
-- -------------------------------------------------------------------------------------------------
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.bus_master_pkg.all;
15
use vunit_lib.axi_slave_pkg.all;
16
context vunit_lib.vunit_context;
17
context vunit_lib.com_context;
18
19
library osvvm;
20
use osvvm.RandomPkg.all;
21
22
library bfm;
23
24
library common;
25
use common.addr_pkg.all;
26
27
library axi;
28
use axi.axi_pkg.all;
29
1
use axi.axi_lite_pkg.all;
30
31




401
use work.reg_file_pkg.all;
32
33
34























735
entity tb_axi_lite_reg_file is
35
  generic (
36
    use_axi_lite_bfm : boolean := true;
37
    runner_cfg : string
38
  );
39
end entity;
40
41
architecture tb of tb_axi_lite_reg_file is
42
43
5
  constant regs : reg_definition_vec_t(0 to 15 - 1) := (
44


2480
    (idx => 0, reg_type => r),
45



4955
    (idx => 1, reg_type => r),
46
    (idx => 2, reg_type => r),
47


230
    (idx => 3, reg_type => w),
48


235
    (idx => 4, reg_type => w),
49
    (idx => 5, reg_type => w),
50
    (idx => 6, reg_type => r_w),
51
    (idx => 7, reg_type => r_w),
52
    (idx => 8, reg_type => r_w),
53
    (idx => 9, reg_type => wpulse),
54
    (idx => 10, reg_type => wpulse),
55
    (idx => 11, reg_type => wpulse),
56
    (idx => 12, reg_type => r_wpulse),
57
    (idx => 13, reg_type => r_wpulse),
58
    (idx => 14, reg_type => r_wpulse)
59
  );
60
61
5
  signal clk : std_logic := '0';
62
63
2005
  signal hardcoded_m2s, axi_lite_m2s : axi_lite_m2s_t;
64
345
  signal axi_lite_s2m : axi_lite_s2m_t;
65
66
4955
  signal regs_up : reg_vec_t(regs'range) := (others => (others => '0'));
67
2480
  signal regs_down : reg_vec_t(regs'range);
68
155
  signal reg_was_read, reg_was_written : std_logic_vector(regs'range);
69
70
5
  constant axi_master : bus_master_t := new_bus(data_length => reg_width, address_length => axi_lite_m2s.read.ar.addr'length);
71
72
165
  constant reg_zero : reg_t := (others => '0');
73
80
  constant reg_was_accessed_zero : std_logic_vector(reg_was_written'range) := (others => '0');
74
75
begin
76
77
281
  test_runner_watchdog(runner, 2 ms);
78
251
  clk <= not clk after 2 ns;
79
80
81
  ------------------------------------------------------------------------------
82
5
  main : process
83
5
    variable rnd : RandomPType;
84
8090
    variable fabric_data, bus_data : reg_vec_t(0 to regs'length - 1);
85
86

93
    procedure reg_stimuli(reg : reg_definition_t) is
87
    begin
88
15
      if is_write_type(reg.reg_type) then
89

48
        write_bus(net, axi_master, 4 * reg.idx, bus_data(reg.idx));
90
      end if;
91
92
15
      if is_fabric_gives_value_type(reg.reg_type) then
93


273
        regs_up(reg.idx) <= fabric_data(reg.idx);
94
      end if;
95
    end procedure;
96
97










806
    procedure reg_data_check(reg : reg_definition_t) is
98
240
      variable reg_was_accessed_expected : std_logic_vector(reg_was_written'range) := (others => '0');
99
15
      variable read_bus_reference : bus_reference_t;
100
495
      variable read_bus_data : reg_t;
101
    begin
102
15
      reg_was_accessed_expected(reg.idx) := '1';
103
104
15
      if is_write_type(reg.reg_type) then
105
60
        wait_for_write_to_go_through : while true loop
106
48
          if is_write_pulse_type(reg.reg_type) then
107
            -- The value that fabric gets should be zero all cycles except the one where the write happens
108

72
            check_equal(regs_down(reg.idx), reg_zero, line_num => 108, file_name => "tb_axi_lite_reg_file.vhd");
109
          end if;
110
111

192
          wait until rising_edge(clk);
112
48
          if reg_was_written /= reg_was_accessed_zero then
113
24
            check_equal(reg_was_written, reg_was_accessed_expected, line_num => 113, file_name => "tb_axi_lite_reg_file.vhd");
114
48
            exit wait_for_write_to_go_through;
115
          end if;
116
        end loop;
117
118

36
        check_equal(regs_down(reg.idx), bus_data(reg.idx), line_num => 118, file_name => "tb_axi_lite_reg_file.vhd");
119
      end if;
120
121
15
      if is_write_pulse_type(reg.reg_type) then
122

24
        wait until rising_edge(clk);
123
        -- The value that fabric gets should be zero all cycles except the one where the write happens
124

18
        check_equal(regs_down(reg.idx), reg_zero, line_num => 124, file_name => "tb_axi_lite_reg_file.vhd");
125
      end if;
126
127
15
      if is_read_type(reg.reg_type) then
128
        -- Initiate a non-blocking read
129

27
        read_bus(net, axi_master, 4 * reg.idx, read_bus_reference);
130
131


251
        wait until reg_was_read /= reg_was_accessed_zero and rising_edge(clk);
132
18
        check_equal(reg_was_read, reg_was_accessed_expected, line_num => 132, file_name => "tb_axi_lite_reg_file.vhd");
133
134
18
        await_read_bus_reply(net, read_bus_reference, read_bus_data);
135
136
9
        if is_fabric_gives_value_type(reg.reg_type) then
137

18
          check_equal(read_bus_data, fabric_data(reg.idx), line_num => 137, file_name => "tb_axi_lite_reg_file.vhd");
138
        else
139

579
          check_equal(read_bus_data, bus_data(reg.idx), line_num => 139, file_name => "tb_axi_lite_reg_file.vhd");
140
        end if;
141
      end if;
142
    end procedure;
143
144

52
    procedure read_hardcoded(reg_index : integer) is
145
    begin
146



260
      hardcoded_m2s.read.ar.addr <= to_unsigned(4 * reg_index, hardcoded_m2s.read.ar.addr'length);
147

4
      hardcoded_m2s.read.ar.valid <= '1';
148

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

4
      hardcoded_m2s.read.ar.valid <= '0';
150
151

4
      hardcoded_m2s.read.r.ready <= '1';
152

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

16
      hardcoded_m2s.read.r.ready <= '0';
154
    end procedure;
155
156


64
    procedure write_hardcoded(reg_index : integer) is
157
    begin
158



260
      hardcoded_m2s.write.aw.addr <= to_unsigned(4 * reg_index, hardcoded_m2s.write.aw.addr'length);
159

4
      hardcoded_m2s.write.aw.valid <= '1';
160

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

4
      hardcoded_m2s.write.aw.valid <= '0';
162
163

4
      hardcoded_m2s.write.w.valid <= '1';
164

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

4
      hardcoded_m2s.write.w.valid <= '0';
166
167

4
      hardcoded_m2s.write.b.ready <= '1';
168

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














500
      hardcoded_m2s.write.b.ready <= '0';
170
    end procedure;
171
172
  begin
173
15
    test_runner_setup(runner, runner_cfg);
174
10
    rnd.InitSeed(rnd'instance_name);
175
176
5
    if run("random_read_and_write") then
177
1
      for list_idx in regs'range loop
178

15
        fabric_data(list_idx) := rnd.RandSLV(fabric_data(0)'length);
179

15
        bus_data(list_idx) := rnd.RandSLV(bus_data(0)'length);
180
      end loop;
181
182
1
      for list_idx in regs'range loop
183

42
        reg_stimuli(regs(list_idx));
184

276
        reg_data_check(regs(list_idx));
185
      end loop;
186
187
4
    elsif run("read_from_non_existent_register") then
188
10
      read_hardcoded(regs(regs'high).idx + 1);
189
2
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_slverr, line_num => 189, file_name => "tb_axi_lite_reg_file.vhd");
190
191
12
      read_hardcoded(regs(regs'high).idx);
192
3
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_okay, line_num => 192, file_name => "tb_axi_lite_reg_file.vhd");
193
194
3
    elsif run("write_to_non_existent_register") then
195
12
      write_hardcoded(regs(regs'high).idx + 1);
196
2
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_slverr, line_num => 196, file_name => "tb_axi_lite_reg_file.vhd");
197
198
14
      write_hardcoded(regs(regs'high).idx);
199
3
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_okay, line_num => 199, file_name => "tb_axi_lite_reg_file.vhd");
200
201
2
    elsif run("read_from_non_read_type_register") then
202
      assert regs(3).reg_type = w;
203
10
      read_hardcoded(3);
204
2
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_slverr, line_num => 204, file_name => "tb_axi_lite_reg_file.vhd");
205
206
12
      read_hardcoded(regs(regs'high).idx);
207
3
      check_equal(axi_lite_s2m.read.r.resp, axi_resp_okay, line_num => 207, file_name => "tb_axi_lite_reg_file.vhd");
208
209

6
    elsif run("write_to_non_write_type_register") then
210
      assert regs(0).reg_type = r;
211
12
      write_hardcoded(0);
212
2
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_slverr, line_num => 212, file_name => "tb_axi_lite_reg_file.vhd");
213
214
14
      write_hardcoded(regs(regs'high).idx);
215
3
      check_equal(axi_lite_s2m.write.b.resp, axi_resp_okay, line_num => 215, file_name => "tb_axi_lite_reg_file.vhd");
216
    end if;
217
218
219
168
    test_runner_cleanup(runner);
220
  end process;
221
222
223
  ------------------------------------------------------------------------------
224
  axi_lite_master_generate : if use_axi_lite_bfm generate
225
6
    axi_lite_master_inst : entity bfm.axi_lite_master
226
      generic map (
227
        bus_handle => axi_master
228
      )
229
      port map (
230
        clk => clk,
231
232
        axi_lite_m2s => axi_lite_m2s,
233
        axi_lite_s2m => axi_lite_s2m
234
      );
235
236
  else generate
237











6438
    axi_lite_m2s <= hardcoded_m2s;
238
  end generate;
239
240
241
  ------------------------------------------------------------------------------
242

2480
  dut : entity work.axi_lite_reg_file
243
    generic map (
244
      regs => regs
245
    )
246
    port map (
247
      clk => clk,
248
      --
249
      axi_lite_m2s => axi_lite_m2s,
250
      axi_lite_s2m => axi_lite_s2m,
251
      --
252
      regs_up => regs_up,
253
      regs_down => regs_down,
254
      --
255
      reg_was_read => reg_was_read,
256
      reg_was_written => reg_was_written
257
    );
258
259
end architecture;