GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/common/tb_width_conversion.vhd Lines: 103 107 96.3 %
Date: 2021-06-12 04:12:08 Branches: 278 430 64.7 %

Line Branch Exec Source
1
84
-- -------------------------------------------------------------------------------------------------
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
context vunit_lib.vunit_context;
15
16
library osvvm;
17
use osvvm.RandomPkg.all;
18
19
use work.types_pkg.all;
20
21
22














148413
entity tb_width_conversion is
23
  generic (
24
    input_width : positive;
25
    output_width : positive;
26
    enable_strobe : boolean;
27
    support_unaligned_burst_length : boolean := false;
28
    data_jitter : boolean := true;
29
    runner_cfg : string
30
  );
31
end entity;
32
33
architecture tb of tb_width_conversion is
34
35
14
  constant input_bytes_per_beat : positive := input_width / 8;
36
14
  constant output_bytes_per_beat : positive := output_width / 8;
37
38
14
  signal clk : std_logic := '0';
39
14
  constant clk_period : time := 10 ns;
40
41
14
  signal input_ready, input_valid, input_last : std_logic := '0';
42
14
  signal output_ready, output_valid, output_last : std_logic := '0';
43
44
262
  signal input_data : std_logic_vector(input_width - 1 downto 0);
45
262
  signal output_data : std_logic_vector(output_width - 1 downto 0);
46
47
14
  constant strobe_unit_width : positive := 8;
48
76
  signal input_strobe : std_logic_vector(input_width / strobe_unit_width - 1 downto 0) :=
49
    (others => '0');
50
76
  signal output_strobe : std_logic_vector(output_width / strobe_unit_width - 1 downto 0) :=
51
14
    (others => '0');
52
53
14
  -- If there is strobing, there will be more words, but the amount of enabled bytes will be
54
14
  -- the same in the end.
55
28
  constant num_bytes_per_test : positive := 64;
56

276
  constant num_test_loops : positive := 100;
57
58


104
  signal num_stimuli_done, num_data_check_done : natural := 0;
59
60
296602
  procedure random_slv(rnd : inout RandomPType; data : out std_logic_vector) is
61
296616
    variable random_sl : std_logic_vector(0 downto 0);
62
14
  begin
63
14
    -- Build up a word from LSB to MSB, which corresponds to little endian when
64


510
    -- comparing wide words with packed thin words.
65
148301
    for i in 0 to data'length - 1 loop
66


1434145
      random_sl := rnd.RandSlv(1);
67

1582353
      data(i) := random_sl(0);
68
    end loop;
69
  end procedure;
70
71
begin
72
73

98
  test_runner_watchdog(runner, 2 ms);
74




513813
  clk <= not clk after clk_period / 2;
75
76
77
  ------------------------------------------------------------------------------
78
14
  main : process
79
14
    variable rnd : RandomPType;
80
81
14
    variable start_time, time_diff : time;
82
83
14
  constant num_input_words_when_no_strobing : positive := num_bytes_per_test / (input_width / 8);
84
14
  constant num_output_words_when_no_strobing : integer :=
85
    num_input_words_when_no_strobing * input_width / output_width;
86
70
  constant num_cycles_when_no_stall_and_no_strobing : integer :=
87
    maximum(num_input_words_when_no_strobing, num_output_words_when_no_strobing);
88
89
  begin
90
42
    test_runner_setup(runner, runner_cfg);
91
28
    rnd.InitSeed(rnd'instance_name);
92
93
14
    if run("test_data") then
94


232153
      wait until
95
        num_stimuli_done = num_test_loops
96
        and num_data_check_done = num_test_loops
97
        and rising_edge(clk);
98
99
26
    elsif run("test_full_throughput") then
100
2
      start_time := now;
101


26010
      wait until
102
        num_stimuli_done = num_test_loops
103
        and num_data_check_done = num_test_loops
104
        and rising_edge(clk);
105
2
      time_diff := now - start_time;
106
107

6
      check_relation(
108
        time_diff < (num_test_loops * num_cycles_when_no_stall_and_no_strobing + 2) * clk_period
109
      , line_num => 107, file_name => "tb_width_conversion.vhd", context_msg => "Expected time_diff < (num_test_loops * num_cycles_when_no_stall_and_no_strobing + 2) * clk_period. Left is " & to_string(time_diff) & ". Right is " & to_string((num_test_loops * num_cycles_when_no_stall_and_no_strobing + 2) * clk_period) & ".");
110
    end if;
111
112








850210
    test_runner_cleanup(runner);
113
  end process;
114
115
116
  ------------------------------------------------------------------------------
117
14
  stimuli : process
118
14
    variable rnd_jitter, rnd_data : RandomPType;
119
262
    variable input_data_v : std_logic_vector(input_data'range);
120
121
14
    variable num_strobes_in_word : positive := input_bytes_per_beat;
122
14
    variable num_bytes_remaining : natural := 0;
123
124
293
    variable num_input_words_sent, num_padding_words : natural := 0;
125
  begin
126

28
    rnd_jitter.InitSeed("stimuli" & rnd_jitter'instance_name);
127
28
    rnd_data.InitSeed("rnd_data");
128
129
1428
    while num_stimuli_done < num_test_loops loop
130
1414
      num_bytes_remaining := num_bytes_per_test;
131
1414
      num_input_words_sent := 0;
132
133
61510
      while num_bytes_remaining > 0 loop
134
58696
        if enable_strobe then
135

26682
          num_strobes_in_word :=
136
            minimum(rnd_jitter.RandInt(1, input_bytes_per_beat), num_bytes_remaining);
137
138


128770
          input_strobe <= (others => '0');
139



103516
          input_strobe(num_strobes_in_word - 1 downto 0) <= (others => '1');
140
141
          -- Reset the data word to zero. Only the appropriate bytes will be assigned below.
142
467048
          input_data_v := (others => '0');
143
        end if;
144
145


117392
        random_slv(rnd_data, input_data_v(num_strobes_in_word * 8 - 1 downto 0));
146
147

58696
        input_valid <= '1';
148
149


876896
        input_data <= input_data_v;
150
58696
        num_bytes_remaining := num_bytes_remaining - num_strobes_in_word;
151
152

58696
        input_last <= to_sl(num_bytes_remaining = 0);
153

370810
        wait until (input_ready and input_valid) = '1' and rising_edge(clk);
154
58687
        num_input_words_sent := num_input_words_sent + 1;
155
156
58687
        if data_jitter then
157

49084
          input_valid <= '0';
158
49084
          for wait_cycle in 1 to rnd_jitter.FavorSmall(0, 2) loop
159

246186
            wait until rising_edge(clk);
160
          end loop;
161
        end if;
162
      end loop;
163
164

1400
      if output_width > input_width and not support_unaligned_burst_length then
165
        -- Pad so that we send the input burst length is a multiple of the output data width.
166
400
        num_padding_words := num_input_words_sent mod (output_width / input_width);
167
168
400
        for padding_word_idx in 1 to num_padding_words loop
169
          input_valid <= '1';
170
          input_last <= '0';
171
          input_data <= (others => '0');
172
          input_strobe <= (others => '0');
173


400
          wait until (input_ready and input_valid) = '1' and rising_edge(clk);
174
        end loop;
175
      end if;
176
177

1400
      input_valid <= '0';
178









2249071
      num_stimuli_done <= num_stimuli_done + 1;
179
    end loop;
180
  end process;
181
182
183
  ------------------------------------------------------------------------------
184
14
  data_check : process
185
14
    variable rnd_jitter, rnd_data : RandomPType;
186
187
14
    variable num_bytes_remaining : natural := 0;
188
189
126
    variable expected_byte : std_logic_vector(8 - 1 downto 0) := (others => '0');
190
  begin
191

28
    rnd_jitter.InitSeed("data_check" & rnd_jitter'instance_name);
192
28
    rnd_data.InitSeed("rnd_data");
193
194
1428
    while num_data_check_done < num_test_loops loop
195
1414
      num_bytes_remaining := num_bytes_per_test;
196
197
66156
      while num_bytes_remaining > 0 loop
198

63342
        output_ready <= '1';
199

373202
        wait until (output_ready and output_valid) = '1' and rising_edge(clk);
200
201
63332
        for byte_lane_idx in 0 to output_bytes_per_beat - 1 loop
202

102317
          if (not enable_strobe) or output_strobe(byte_lane_idx) = '1' then
203
            -- Build up the expected output data vector in same way that input data
204
            -- is generated above. Note that the same random seed is used.
205
179210
            random_slv(rnd_data, expected_byte);
206



179210
            check_equal(
207
              output_data((byte_lane_idx + 1) * 8 - 1 downto byte_lane_idx * 8),
208
              expected_byte,
209
              "byte_lane_idx=" & to_string(byte_lane_idx)
210
              & ",num_bytes_remaining=" & to_string(num_bytes_remaining)
211
            , line_num => 206, file_name => "tb_width_conversion.vhd");
212
213

294239
            num_bytes_remaining := num_bytes_remaining - 1;
214
          end if;
215
        end loop;
216
217

126664
        check_equal(
218
          output_last,
219
          to_sl(num_bytes_remaining = 0),
220
          "num_bytes_remaining=" & to_string(num_bytes_remaining)
221
        , line_num => 217, file_name => "tb_width_conversion.vhd");
222
223
63332
        if data_jitter then
224

53731
          output_ready <= '0';
225
53731
          for wait_cycle in 1 to rnd_jitter.FavorSmall(0, 2) loop
226

266869
            wait until rising_edge(clk);
227
          end loop;
228
        end if;
229
      end loop;
230
231

1400
      output_ready <= '0';
232

1401348
      num_data_check_done <= num_data_check_done + 1;
233
    end loop;
234
  end process;
235
236
237
  ------------------------------------------------------------------------------
238
14
  dut : entity work.width_conversion
239
    generic map (
240
      input_width => input_width,
241
      output_width => output_width,
242
      enable_strobe => enable_strobe,
243
      strobe_unit_width => strobe_unit_width,
244
      support_unaligned_burst_length => support_unaligned_burst_length
245
    )
246
    port map (
247
      clk => clk,
248
      --
249
      input_ready => input_ready,
250
      input_valid => input_valid,
251
      input_last => input_last,
252
      input_data => input_data,
253
      input_strobe => input_strobe,
254
      --
255
      output_ready => output_ready,
256
      output_valid => output_valid,
257
      output_last => output_last,
258
      output_data => output_data,
259
      output_strobe => output_strobe
260
    );
261
262
end architecture;