GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/axi/axi_pkg.vhd Lines: 192 219 87.7 %
Date: 2021-06-12 04:12:08 Branches: 255 613 41.6 %

Line Branch Exec Source
1




46054
-- -------------------------------------------------------------------------------------------------
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
-- Data types for working with AXI4 interfaces
9
--
10
-- Based on the document "ARM IHI 0022E (ID022613): AMBA AXI and ACE Protocol Specification",
11
-- available here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0022e/index.html
12
-- -------------------------------------------------------------------------------------------------
13
14
library ieee;
15
use ieee.std_logic_1164.all;
16
use ieee.numeric_std.all;
17
18
library math;
19
use math.math_pkg.all;
20
21
22
package axi_pkg is
23
24
  -- Max value
25
4
  constant axi_id_sz : positive := 24;
26
27
4
  constant axi_max_burst_length_beats : positive := 256;
28
4
  constant axi3_max_burst_length_beats : positive := 16;
29
30
31
  ------------------------------------------------------------------------------
32
  -- A (Address Read and Address Write) channels
33
  ------------------------------------------------------------------------------
34
35
  -- Max value
36
4
  constant axi_a_addr_sz : positive := 64;
37
  -- Number of transfers = len + 1
38
4
  constant axi_a_len_sz : positive := 8;
39
  -- Bytes per transfer = 2^size
40
4
  constant axi_a_size_sz : positive := 3;
41
42
  function to_len(burst_length_beats : positive) return unsigned;
43
  function to_size(data_width_bits : positive) return unsigned;
44
45
4
  constant axi_a_burst_sz : positive := 2;
46
4
  constant axi_a_burst_fixed : std_logic_vector(axi_a_burst_sz - 1 downto 0) := "00";
47
4
  constant axi_a_burst_incr : std_logic_vector(axi_a_burst_sz - 1 downto 0) := "01";
48
4
  constant axi_a_burst_wrap : std_logic_vector(axi_a_burst_sz - 1 downto 0) := "10";
49
50
4
  constant axi_a_lock_sz : positive := 1; -- Two bits in AXI3
51
4
  constant axi_a_lock_normal : std_logic_vector(axi_a_lock_sz - 1 downto 0) := "0";
52
4
  constant axi_a_lock_exclusive : std_logic_vector(axi_a_lock_sz - 1 downto 0) := "1";
53
4
  constant axi3_a_lock_normal : std_logic_vector(2 - 1 downto 0) := "00";
54
4
  constant axi3_a_lock_exclusive : std_logic_vector(2 - 1 downto 0) := "01";
55
4
  constant axi3_a_lock_locked : std_logic_vector(2 - 1 downto 0) := "10";
56
57
4
  constant axi_a_cache_sz : positive := 4;
58
4
  constant axi_a_cache_device_non_bufferable : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0000";
59
4
  constant axi_a_cache_device_bufferable : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0001";
60
4
  constant axi_a_cache_normal_non_cacheable_non_bufferable : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0010";
61
4
  constant axi_a_cache_normal_non_cacheable_bufferable : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0011";
62
4
  constant axi_ar_cache_write_through_no_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "1010";
63
4
  constant axi_aw_cache_write_through_no_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0110";
64
4
  constant axi_a_cache_write_through_read_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0110";
65
4
  constant axi_a_cache_write_through_write_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "1010";
66
4
  constant axi_a_cache_write_through_read_and_write_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "1110";
67
4
  constant axi_ar_cache_write_back_no_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "1011";
68
4
  constant axi_aw_cache_write_back_no_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0111";
69
4
  constant axi_a_cache_write_back_read_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "0111";
70
4
  constant axi_a_cache_write_back_write_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "1011";
71
4
  constant axi_a_cache_write_back_read_and_write_allocate : std_logic_vector(axi_a_cache_sz - 1 downto 0) := "1111";
72
73
4
  constant axi_a_prot_sz : positive := 3;
74
4
  constant axi_a_prot_privileged : std_logic_vector(axi_a_prot_sz - 1 downto 0) := "001";
75
4
  constant axi_a_prot_unprivileged : std_logic_vector(axi_a_prot_sz - 1 downto 0) := "000";
76
4
  constant axi_a_prot_secure : std_logic_vector(axi_a_prot_sz - 1 downto 0) := "000";
77
4
  constant axi_a_prot_nonsecure : std_logic_vector(axi_a_prot_sz - 1 downto 0) := "010";
78
4
  constant axi_a_prot_data : std_logic_vector(axi_a_prot_sz - 1 downto 0) := "000";
79
4
  constant axi_a_prot_instruction : std_logic_vector(axi_a_prot_sz - 1 downto 0) := "100";
80
81
4
  constant axi_a_region_sz : positive := 4;
82
83
  type axi_m2s_a_t is record
84
    valid : std_logic;
85
    id : unsigned(axi_id_sz - 1 downto 0);
86
    addr : unsigned(axi_a_addr_sz - 1 downto 0);
87
    len : unsigned(axi_a_len_sz - 1 downto 0);
88
    size : unsigned(axi_a_size_sz - 1 downto 0);
89
    burst : std_logic_vector(axi_a_burst_sz - 1 downto 0);
90
    -- Excluded members: lock, cache, prot, region.
91
    -- These are typically not changed on a transfer-to-transfer basis.
92
  end record;
93
94


408
  constant axi_m2s_a_init : axi_m2s_a_t := (
95
    valid => '0',
96
    burst => (others => '0'),
97
    others => (others => '0')
98
  );
99
  function axi_m2s_a_sz(id_width : natural; addr_width : positive)  return positive;
100
  type axi_m2s_a_vec_t is array (integer range <>) of axi_m2s_a_t;
101
102
  function to_slv(
103
    data : axi_m2s_a_t; id_width : natural; addr_width : positive
104
  ) return std_logic_vector;
105
  function to_axi_m2s_a(
106
    data : std_logic_vector; id_width : natural; addr_width : positive
107
  ) return axi_m2s_a_t;
108
109
  type axi_s2m_a_t is record
110
    ready : std_logic;
111
  end record;
112
113
4
  constant axi_s2m_a_init : axi_s2m_a_t := (ready => '0');
114
  type axi_s2m_a_vec_t is array (integer range <>) of axi_s2m_a_t;
115
116
117
  ------------------------------------------------------------------------------
118
  -- W (Write Data) channels
119
  ------------------------------------------------------------------------------
120
121
  -- Max values
122
4
  constant axi_data_sz : positive := 128;
123
4
  constant axi_w_strb_sz : positive := axi_data_sz / 8;
124
125
  function to_strb(data_width : positive) return std_logic_vector;
126
127
  type axi_m2s_w_t is record
128
    valid : std_logic;
129
    data : std_logic_vector(axi_data_sz - 1 downto 0);
130
    strb : std_logic_vector(axi_w_strb_sz - 1 downto 0);
131
    last : std_logic;
132
    -- Only available in AXI3. We assume that AXI4 is used most of the time, hence id_width is
133
    -- defaulted to zero in the functions below.
134
    id : unsigned(axi_id_sz - 1 downto 0);
135
  end record;
136
137

676
  constant axi_m2s_w_init : axi_m2s_w_t := (
138
    valid => '0',
139
    data => (others => '-'),
140
    last => '0',
141
    id => (others => '-'),
142
    others => (others => '0')
143
  );
144
  function axi_m2s_w_sz(data_width : positive; id_width : natural := 0) return positive;
145
  type axi_m2s_w_vec_t is array (integer range <>) of axi_m2s_w_t;
146
147
  function axi_w_strb_width(data_width : positive) return positive;
148
149
  function to_slv(
150
    data : axi_m2s_w_t; data_width : positive; id_width : natural := 0
151
  ) return std_logic_vector;
152
  function to_axi_m2s_w(
153
    data : std_logic_vector; data_width : positive; id_width : natural := 0
154
  ) return axi_m2s_w_t;
155
156
  type axi_s2m_w_t is record
157
    ready : std_logic;
158
  end record;
159
  type axi_s2m_w_vec_t is array (integer range <>) of axi_s2m_w_t;
160
161
4
  constant axi_s2m_w_init : axi_s2m_w_t := (ready => '0');
162
163
164
  ------------------------------------------------------------------------------
165
  -- B (Write Response) channels
166
  ------------------------------------------------------------------------------
167
168
  type axi_m2s_b_t is record
169
    ready : std_logic;
170
  end record;
171
172
4
  constant axi_m2s_b_init : axi_m2s_b_t := (ready => '0');
173
174
4
  constant axi_resp_sz : positive := 2;
175
4
  constant axi_resp_okay : std_logic_vector(axi_resp_sz - 1 downto 0) := "00";
176
  -- Exclusive access okay.
177
4
  constant axi_resp_exokay : std_logic_vector(axi_resp_sz - 1 downto 0) := "01";
178
  -- Slave error. Slave wishes to return error.
179
4
  constant axi_resp_slverr : std_logic_vector(axi_resp_sz - 1 downto 0) := "10";
180
  -- Decode error. There is no slave at transaction address.
181
4
  constant axi_resp_decerr : std_logic_vector(axi_resp_sz - 1 downto 0) := "11";
182
183
  type axi_s2m_b_t is record
184
    valid : std_logic;
185
    id : unsigned(axi_id_sz - 1 downto 0);
186
    resp : std_logic_vector(axi_resp_sz - 1 downto 0);
187
  end record;
188
189

108
  constant axi_s2m_b_init : axi_s2m_b_t := (
190
    valid => '0',
191
    id => (others => '0'),
192
    resp => (others => '0')
193
  );
194
  function axi_s2m_b_sz(id_width : natural) return positive;
195
  type axi_s2m_b_vec_t is array (integer range <>) of axi_s2m_b_t;
196
197
  function to_slv(data : axi_s2m_b_t; id_width : natural) return std_logic_vector;
198
  function to_axi_s2m_b(data : std_logic_vector; id_width : natural) return axi_s2m_b_t;
199
200
201
  ------------------------------------------------------------------------------
202
  -- R (Read Data) channels
203
  ------------------------------------------------------------------------------
204
205
  type axi_m2s_r_t is record
206
    ready : std_logic;
207
  end record;
208
  type axi_m2s_r_vec_t is array (integer range <>) of axi_m2s_r_t;
209
210
4
  constant axi_m2s_r_init : axi_m2s_r_t := (ready => '0');
211
212
  type axi_s2m_r_t is record
213
    valid : std_logic;
214
    id : unsigned(axi_id_sz - 1 downto 0);
215
    data : std_logic_vector(axi_data_sz - 1 downto 0);
216
    resp : std_logic_vector(axi_resp_sz - 1 downto 0);
217
    last : std_logic;
218
  end record;
219
220

620
  constant axi_s2m_r_init : axi_s2m_r_t := (
221
    valid => '0',
222
    last => '0',
223
    id => (others => '0'),
224
    others => (others => '0')
225
  );
226
  function axi_s2m_r_sz(data_width : positive; id_width : natural)  return positive;
227
  type axi_s2m_r_vec_t is array (integer range <>) of axi_s2m_r_t;
228
229
  function to_slv(data : axi_s2m_r_t; data_width : positive; id_width : natural) return std_logic_vector;
230
  function to_axi_s2m_r(data : std_logic_vector; data_width : positive; id_width : natural) return axi_s2m_r_t;
231
232
233
  ------------------------------------------------------------------------------
234
  -- The complete buses
235
  ------------------------------------------------------------------------------
236
237
  type axi_read_m2s_t is record
238
    ar : axi_m2s_a_t;
239
    r : axi_m2s_r_t;
240
  end record;
241
  type axi_read_m2s_vec_t is array (integer range <>) of axi_read_m2s_t;
242
243
4
  constant axi_read_m2s_init : axi_read_m2s_t := (ar => axi_m2s_a_init, r => axi_m2s_r_init);
244
245
  type axi_read_s2m_t is record
246
    ar : axi_s2m_a_t;
247
    r : axi_s2m_r_t;
248
  end record;
249
  type axi_read_s2m_vec_t is array (integer range <>) of axi_read_s2m_t;
250
251
4
  constant axi_read_s2m_init : axi_read_s2m_t := (ar => axi_s2m_a_init, r => axi_s2m_r_init);
252
253
  type axi_write_m2s_t is record
254
    aw : axi_m2s_a_t;
255
    w : axi_m2s_w_t;
256
    b : axi_m2s_b_t;
257
  end record;
258
  type axi_write_m2s_vec_t is array (integer range <>) of axi_write_m2s_t;
259
260
4
  constant axi_write_m2s_init : axi_write_m2s_t := (aw => axi_m2s_a_init, w => axi_m2s_w_init, b => axi_m2s_b_init);
261
262
  type axi_write_s2m_t is record
263
    aw : axi_s2m_a_t;
264
    w : axi_s2m_w_t;
265
    b : axi_s2m_b_t;
266
  end record;
267
  type axi_write_s2m_vec_t is array (integer range <>) of axi_write_s2m_t;
268
269
4
  constant axi_write_s2m_init : axi_write_s2m_t := (aw => axi_s2m_a_init, w => axi_s2m_w_init, b => axi_s2m_b_init);
270
271
  type axi_m2s_t is record
272
    read : axi_read_m2s_t;
273
    write : axi_write_m2s_t;
274
  end record;
275
  type axi_m2s_vec_t is array (integer range <>) of axi_m2s_t;
276
277
4
  constant axi_m2s_init : axi_m2s_t := (read => axi_read_m2s_init, write => axi_write_m2s_init);
278
279
  type axi_s2m_t is record
280
    read : axi_read_s2m_t;
281
    write : axi_write_s2m_t;
282
  end record;
283
  type axi_s2m_vec_t is array (integer range <>) of axi_s2m_t;
284
285
4
  constant axi_s2m_init : axi_s2m_t := (read => axi_read_s2m_init, write => axi_write_s2m_init);
286
287
  function combine_response(resp1, resp2 : std_logic_vector(axi_resp_sz - 1 downto 0))
288
    return std_logic_vector;
289
290
end;
291
292
package body axi_pkg is
293
294
  function to_len(burst_length_beats : positive) return unsigned is
295
    variable result : unsigned(axi_a_len_sz - 1 downto 0);
296
  begin
297
    -- burst_length_beats is number of transfers
298
    result := to_unsigned(burst_length_beats - 1, result'length);
299
    return result;
300
  end function;
301
302
  function to_size(data_width_bits : positive) return unsigned is
303
    variable result : unsigned(axi_a_size_sz - 1 downto 0);
304
  begin
305
    result := to_unsigned(log2(data_width_bits / 8), result'length);
306
    return result;
307
  end function;
308
309
  function axi_m2s_a_sz(id_width : natural; addr_width : positive) return positive is
310
  begin
311
    -- Exluded member: valid
312
4004
    return id_width + addr_width + axi_a_len_sz + axi_a_size_sz + axi_a_burst_sz;
313
  end function;
314
315
  function to_slv(
316
    data : axi_m2s_a_t; id_width : natural; addr_width : positive
317
  ) return std_logic_vector is
318

92092
    variable result : std_logic_vector(axi_m2s_a_sz(id_width, addr_width) - 1 downto 0);
319
2002
    variable lo, hi : natural := 0;
320
  begin
321
2002
    lo := 0;
322
2002
    if id_width > 0 then
323
      hi := id_width - 1;
324
      result(hi downto lo) := std_logic_vector(data.id(hi downto lo));
325
      lo := hi + 1;
326
    end if;
327
2002
    hi := lo + addr_width - 1;
328



2002
    result(hi downto lo) := std_logic_vector(data.addr(addr_width - 1 downto 0));
329
2002
    lo := hi + 1;
330
2002
    hi := lo + data.len'length - 1;
331


2002
    result(hi downto lo) := std_logic_vector(data.len);
332
2002
    lo := hi + 1;
333
2002
    hi := lo + data.size'length - 1;
334


2002
    result(hi downto lo) := std_logic_vector(data.size);
335
2002
    lo := hi + 1;
336
2002
    hi := lo + data.burst'length - 1;
337


2002
    result(hi downto lo) := data.burst;
338

2002
    assert hi = result'high severity failure;
339
2002
    return result;
340
  end function;
341
342
  function to_axi_m2s_a(
343
    data : std_logic_vector; id_width : natural; addr_width : positive
344
  ) return axi_m2s_a_t is
345
2002
    constant offset : natural := data'low;
346
2002
    variable result : axi_m2s_a_t := axi_m2s_a_init;
347
2002
    variable lo, hi : natural := 0;
348
  begin
349
2002
    lo := 0;
350
2002
    if id_width > 0 then
351
      hi := id_width - 1;
352
      result.id(hi downto lo) := unsigned(data(hi + offset downto lo + offset));
353
      lo := hi + 1;
354
    end if;
355
2002
    hi := lo + addr_width - 1;
356




2002
    result.addr(addr_width - 1 downto 0) := unsigned(data(hi + offset downto lo + offset));
357
2002
    lo := hi + 1;
358
2002
    hi := lo + result.len'length - 1;
359


2002
    result.len := unsigned(data(hi + offset downto lo + offset));
360
2002
    lo := hi + 1;
361
2002
    hi := lo + result.size'length - 1;
362


2002
    result.size := unsigned(data(hi + offset downto lo + offset));
363
2002
    lo := hi + 1;
364
2002
    hi := lo + result.burst'length - 1;
365


2002
    result.burst := data(hi + offset downto lo + offset);
366

2002
    assert hi + offset = data'high severity failure;
367
2002
    return result;
368
  end function;
369
370
  function to_strb(data_width : positive) return std_logic_vector is
371
    variable result : std_logic_vector(axi_w_strb_sz - 1 downto 0) := (others => '0');
372
  begin
373
    result(data_width / 8 - 1 downto 0) := (others => '1');
374
    return result;
375
  end function;
376
377
  function axi_w_strb_width(data_width : positive) return positive is
378
  begin
379
12012
    return data_width / 8;
380
  end function;
381
382
  function axi_m2s_w_sz(data_width : positive; id_width : natural := 0) return positive is
383
  begin
384
    -- Exluded member: valid.
385
    -- The 1 is "last".
386
4004
    return data_width + axi_w_strb_width(data_width) + 1 + id_width;
387
  end function;
388
389
  function to_slv(
390
    data : axi_m2s_w_t; data_width : positive; id_width : natural := 0
391
  ) return std_logic_vector is
392

76076
    variable result :
393
      std_logic_vector(axi_m2s_w_sz(data_width=>data_width, id_width=>id_width) - 1 downto 0) :=
394
      (others => '0');
395
2002
    variable lo, hi : natural := 0;
396
  begin
397
2002
    lo := 0;
398
399
2002
    hi := lo + data_width - 1;
400



2002
    result(hi downto lo) := data.data(data_width - 1 downto 0);
401
2002
    lo := hi + 1;
402
403
2002
    hi := lo + axi_w_strb_width(data_width) - 1;
404



2002
    result(hi downto lo) := data.strb(axi_w_strb_width(data_width) - 1 downto 0);
405
2002
    lo := hi + 1;
406
407
2002
    hi := lo + id_width - 1;
408



2002
    result(hi downto lo) := std_logic_vector(data.id(id_width - 1 downto 0));
409
2002
    lo := hi + 1;
410
411
2002
    hi := lo;
412
2002
    result(hi) := data.last;
413

2002
    assert hi = result'high severity failure;
414
2002
    return result;
415
  end function;
416
417
  function to_axi_m2s_w(
418
    data : std_logic_vector; data_width : positive; id_width : natural := 0
419
  ) return axi_m2s_w_t is
420
2002
    constant offset : natural := data'low;
421
2002
    variable result : axi_m2s_w_t := axi_m2s_w_init;
422
2002
    variable lo, hi : natural := 0;
423
  begin
424
2002
    lo := 0;
425
426
2002
    hi := lo + data_width - 1;
427




2002
    result.data(data_width - 1 downto 0) := data(hi + offset downto lo + offset);
428
2002
    lo := hi + 1;
429
430
2002
    hi := lo + axi_w_strb_width(data_width) - 1;
431




2002
    result.strb(axi_w_strb_width(data_width) - 1 downto 0) := data(hi + offset downto lo + offset);
432
2002
    lo := hi + 1;
433
434
2002
    hi := lo + id_width - 1;
435




2002
    result.id(id_width - 1 downto 0) := unsigned(data(hi + offset downto lo + offset));
436
2002
    lo := hi + 1;
437
438
2002
    hi := lo;
439

2002
    result.last := data(hi + offset);
440

2002
    assert hi + offset = data'high severity failure;
441
2002
    return result;
442
  end function;
443
444
  function axi_s2m_b_sz(id_width : natural) return positive is
445
  begin
446
    -- Exluded member: valid
447
4004
    return id_width + axi_resp_sz;
448
  end function;
449
450
  function to_slv(data : axi_s2m_b_t; id_width : natural) return std_logic_vector is
451

6006
    variable result : std_logic_vector(axi_s2m_b_sz(id_width) - 1 downto 0);
452
2002
    variable lo, hi : natural := 0;
453
  begin
454
2002
    lo := 0;
455
2002
    if id_width > 0 then
456
      hi := id_width - 1;
457
      result(hi downto lo) := std_logic_vector(data.id(hi downto lo));
458
      lo := hi + 1;
459
    end if;
460
2002
    hi := lo + axi_resp_sz - 1;
461


2002
    result(hi downto lo) := data.resp;
462

2002
    assert hi = result'high severity failure;
463
2002
    return result;
464
  end function;
465
466
  function to_axi_s2m_b(data : std_logic_vector; id_width : natural) return axi_s2m_b_t is
467
2002
    constant offset : natural := data'low;
468
2002
    variable result : axi_s2m_b_t := axi_s2m_b_init;
469
2002
    variable lo, hi : natural := 0;
470
  begin
471
2002
    lo := 0;
472
2002
    if id_width > 0 then
473
      hi := id_width - 1;
474
      result.id(hi downto lo) := unsigned(data(hi + offset downto lo + offset));
475
      lo := hi + 1;
476
    end if;
477
2002
    hi := lo + axi_resp_sz - 1;
478


2002
    result.resp := data(hi + offset downto lo + offset);
479

2002
    assert hi + offset = data'high severity failure;
480
2002
    return result;
481
  end function;
482
483
  function axi_s2m_r_sz(data_width : positive; id_width : natural) return positive is
484
  begin
485
    -- Exluded member: valid.
486
    -- The 1 is "last".
487
4004
    return data_width + id_width + axi_resp_sz + 1;
488
  end function;
489
490
  function to_slv(data : axi_s2m_r_t; data_width : positive; id_width : natural) return std_logic_vector is
491

72072
    variable result : std_logic_vector(axi_s2m_r_sz(data_width, id_width) - 1 downto 0);
492
2002
    variable lo, hi : natural := 0;
493
  begin
494
2002
    lo := 0;
495
2002
    if id_width > 0 then
496
      hi := id_width - 1;
497
      result(hi downto lo) := std_logic_vector(data.id(hi downto lo));
498
      lo := hi + 1;
499
    end if;
500
2002
    hi := lo + data_width - 1;
501



2002
    result(hi downto lo) := data.data(data_width - 1 downto 0);
502
2002
    lo := hi + 1;
503
2002
    hi := lo + axi_resp_sz - 1;
504


2002
    result(hi downto lo) := data.resp;
505
2002
    lo := hi + 1;
506
2002
    hi := lo;
507
2002
    result(hi) := data.last;
508

2002
    assert hi = result'high severity failure;
509
2002
    return result;
510
  end function;
511
512
  function to_axi_s2m_r(data : std_logic_vector; data_width : positive; id_width : natural) return axi_s2m_r_t is
513
2002
    constant offset : natural := data'low;
514
2002
    variable result : axi_s2m_r_t := axi_s2m_r_init;
515
2002
    variable lo, hi : natural := 0;
516
  begin
517
2002
    lo := 0;
518
2002
    if id_width > 0 then
519
      hi := id_width - 1;
520
      result.id(hi downto lo) := unsigned(data(hi + offset downto lo + offset));
521
      lo := hi + 1;
522
    end if;
523
2002
    hi := lo + data_width - 1;
524




2002
    result.data(data_width - 1 downto 0) := data(hi + offset downto lo + offset);
525
2002
    lo := hi + 1;
526
2002
    hi := lo + axi_resp_sz - 1;
527


2002
    result.resp := data(hi + offset downto lo + offset);
528
2002
    lo := hi + 1;
529
2002
    hi := lo;
530

2002
    result.last := data(hi + offset);
531

2002
    assert hi + offset = data'high severity failure;
532
2002
    return result;
533
  end function;
534
535
  -- Combine responses, with the "worst" response taking priority. OKAY may be considered
536
  -- an error if an exclusive access was desired, so OKAY takes priority over EXOKAY.
537
  function combine_response(
538
    resp1, resp2 : std_logic_vector(axi_resp_sz - 1 downto 0)
539
  ) return std_logic_vector is
540
6006
    variable resp : std_logic_vector(axi_resp_sz - 1 downto 0);
541
  begin
542
2002
    resp := resp1;
543
544



3494
    case resp is
545
      when axi_resp_exokay =>
546
        -- All values take priority over EXOKAY
547
510
        resp := resp2;
548
549
      when axi_resp_okay =>
550
        -- Errors take priority over OKAY
551
504
        if resp2 = axi_resp_slverr then
552
116
          resp := axi_resp_slverr;
553
        end if;
554
504
        if resp2 = axi_resp_decerr then
555
504
          resp := axi_resp_decerr;
556
        end if;
557
558
      when axi_resp_slverr =>
559
        -- Only DECERR takes priority over SLVERR
560
496
        if resp2 = axi_resp_decerr then
561
496
          resp := axi_resp_decerr;
562
        end if;
563
564
      when others =>
565
        -- DECERR
566
492
        resp := axi_resp_decerr;
567
568
    end case;
569
570

2006
    return resp;
571
  end function;
572
end;