AXI muckbucket
axi_pkg.sv
Go to the documentation of this file.
1 //
3 // Copyright (C) 2017, Matt Dew @ Dew Technologies, LLC
4 //
5 // This program is free software (logic verification): you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public License (LGPL)
7 // as published by the Free Software Foundation, either version 3 of the License,
8 // or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 // for more details.
14 //
15 // License: LGPL, v3, as defined and found on www.gnu.org,
16 // http://www.gnu.org/licenses/lgpl.html
17 //
18 //
19 // Author's intent: If you use this AXI verification code and find or fix bugs
20 // or make improvements, then share those fixes or improvements.
21 // If you use this in a bigger project, I don't care about,
22 // or want, any changes or code outside this block.
23 // Example: If you use this in an SoC simulation/testbench
24 // I don't want, or care about, your SoC or other blocks.
25 // I just care about the enhancements to these AXI files.
26 // That's why I have choosen the LGPL instead of the GPL.
28 
33 // Ugh, we now have a dependency on uvm in the RTL.
34 // @Todo: check if abstract class can be a simple class and not a component or object
35 
36 #include "uvm_macros.svh"
37 
38 
39 
40 
76 typedef enum {e_1BYTE = 0b000,
77  e_2BYTES = 0b001,
78  e_4BYTES = 0b010,
79  e_8BYTES = 0b011,
80  e_16BYTES = 0b100,
81  e_32BYTES = 0b101,
82  e_64BYTES = 0b110,
83  e_128BYTES = 0b111
84  } burst_size_t;
85 
89 typedef enum {e_FIXED = 0b00,
90  e_INCR = 0b01,
91  e_WRAP = 0b10,
92  e_RESERVED = 0b11
93  } burst_type_t;
94 
98 typedef enum {e_OKAY = 0b00,
99  e_EXOKAY = 0b01,
100  e_SLVERR = 0b10,
101  e_DECERR = 0b11
102  } response_type_t;
103 
104 
105 
106 
107 
113 typedef struct {
114  logic <C_AXI_ID_WIDTH-1:0> awid;
115  logic <C_AXI_ADDR_WIDTH-1:0> awaddr;
116  logic awvalid;
117  logic awready;
118  logic <C_AXI_LEN_WIDTH-1:0> awlen;
119  logic <2:0> awsize;
120  logic <1:0> awburst;
121  logic <0:0> awlock;
122  logic <3:0> awcache;
123  logic <2:0> awprot;
124  logic <3:0> awqos;
127 
133 
134 
135 
141 typedef struct {
142  logic <C_AXI_DATA_WIDTH-1:0> wdata;
143  logic <C_AXI_DATA_WIDTH/8-1:0> wstrb;
144  logic wlast;
145  logic wvalid;
146  logic <C_AXI_ID_WIDTH-1:0> wid;
149 
155 
156 
162 typedef struct {
163  logic <C_AXI_ID_WIDTH-1:0> bid;
164  logic <1:0> bresp;
166 
172 
178 typedef struct {
179  logic <C_AXI_ID_WIDTH-1:0> arid;
180  logic <C_AXI_ADDR_WIDTH-1:0> araddr;
181  logic arvalid;
182  logic arready;
183  logic <C_AXI_LEN_WIDTH-1:0> arlen;
184  logic <2:0> arsize;
185  logic <1:0> arburst;
186  logic <0:0> arlock;
187  logic <3:0> arcache;
188  logic <2:0> arprot;
189  logic <3:0> arqos;
192 
198 
199 
205 typedef struct {
206  logic <C_AXI_DATA_WIDTH-1:0> rdata;
207  logic <1:0> rresp;
208  logic rlast;
209  logic rvalid;
210  logic <C_AXI_ID_WIDTH-1:0> rid;
213 
219 
231  input bit <C_AXI_ADDR_WIDTH-1:0> address,
232  input bit <2:0> burst_size) {
233 
234 
235  bit <C_AXI_ADDR_WIDTH-1:0> aligned_address;
236 
237  // This can be done in a nice function, but this case
238  // is immediatly understandable.
239  aligned_address = address;
240  case (burst_size) {
241  e_1BYTE : aligned_address = address;
242  e_2BYTES : aligned_address[0] = 0b0;
243  e_4BYTES : aligned_address[2] = 0b00;
244  e_8BYTES : aligned_address[3] = 0b000;
245  e_16BYTES : aligned_address[4] = 0b0000;
246  e_32BYTES : aligned_address[5] = 0b0_0000;
247  e_64BYTES : aligned_address[6] = 0b00_0000;
248  e_128BYTES : aligned_address[7] = 0b000_0000;
249  }
250 
251  uvm_info("axi_pkg::calculatate-aligned_adress",
252  $sformatf("address: 0x%0x burst_size:%0d alignedaddress: 0x%0x",
253  address, burst_size, aligned_address),
254  UVM_HIGH)
255 
256  return aligned_address;
257 
258 }
259 
260 
273  input bit <C_AXI_ADDR_WIDTH-1:0> addr,
274  input int bus_size) {
275 
276  bit <C_AXI_ADDR_WIDTH-1:0> aligned_address;
277 
278  string msg_s;
279 
280  aligned_address = addr;
281 
282  case (bus_size) {
283  2**e_1BYTE : aligned_address = addr;
284  2**e_2BYTES : aligned_address[0] = 0b0;
285  2**e_4BYTES : aligned_address[2] = 0b00;
286  2**e_8BYTES : aligned_address[3] = 0b000;
287  2**e_16BYTES : aligned_address[4] = 0b0000;
288  2**e_32BYTES : aligned_address[5] = 0b0_0000;
289  2**e_64BYTES : aligned_address[6] = 0b00_0000;
290  2**e_128BYTES : aligned_address[7] = 0b000_0000;
291  }
292 
293 
294  msg_s="";
295  $sformat(msg_s, "%s addr: 0x%0x", msg_s, addr);
296  $sformat(msg_s, "%s aligned_address: 0x%0x", msg_s, aligned_address);
297  $sformat(msg_s, "%s bus_size: 0x%0x", msg_s, bus_size);
298 
299 
300 
301  uvm_info("calculate_bus_aligned_address", msg_s,UVM_HIGH)
302 
303  return aligned_address;
304 
305 }
306 
307 
321  input bit <C_AXI_ADDR_WIDTH-1:0> addr,
322  input bit <2:0> burst_size,
323  input shortint burst_length) {
324 
325 
326  byte unalignment_offset;
327  shortint total_length;
328  shortint shifter;
329  shortint ishifter;
330  bit <C_AXI_LEN_WIDTH-1:0> beats;
331 
332  string msg_s;
333 
334  unalignment_offset = calculate_unalignment_offset(
335  .addr(addr),
336  .burst_size(burst_size));
337 
338  total_length=burst_length + unalignment_offset;
339 
340  shifter = shortint(total_length/(2**burst_size));
341 
342  ishifter = shifter*(2**burst_size);
343 
344  if (ishifter != total_length) {
345  shifter += 1;
346  }
347 
348  beats = shifter - 1;
349 
350 
351  msg_s="";
352  $sformat(msg_s, "%s addr: 0x%0x", msg_s, addr);
353  $sformat(msg_s, "%s burst_size: %0d", msg_s, burst_size);
354  $sformat(msg_s, "%s unalignment_offset: %0d", msg_s, unalignment_offset);
355  $sformat(msg_s, "%s burst_length: %0d", msg_s, burst_length);
356  $sformat(msg_s, "%s total_length: %0d", msg_s, total_length);
357  $sformat(msg_s, "%s shifter: %0d", msg_s, shifter);
358  $sformat(msg_s, "%s ishifter: %0d", msg_s, ishifter);
359 
360  uvm_info("axi_pkg::calculate_beats",
361  msg_s,
362  UVM_HIGH)
363 
364  return beats;
365 
366 }
367 
375  input bit <C_AXI_ADDR_WIDTH-1:0> addr,
376  input byte burst_size) {
377 
378  byte unalignment_offset;
379 
380  case (burst_size) {
381  e_1BYTE : unalignment_offset = 0;
382  e_2BYTES : unalignment_offset = byte(addr[0]);
383  e_4BYTES : unalignment_offset = byte(addr[2]);
384  e_8BYTES : unalignment_offset = byte(addr[3]);
385  e_16BYTES : unalignment_offset = byte(addr[4]);
386  e_32BYTES : unalignment_offset = byte(addr[5]);
387  e_64BYTES : unalignment_offset = byte(addr[6]);
388  e_128BYTES : unalignment_offset = byte(addr[7]);
389  }
390 
391  return unalignment_offset;
392 
393 
394 }
395 
396 
407  input bit <C_AXI_ADDR_WIDTH-1:0> addr,
408  input bit <2:0> burst_size,
409  input shortint burst_length,
410  output bit <C_AXI_ADDR_WIDTH-1:0> Lower_Wrap_Boundary,
411  output bit <C_AXI_ADDR_WIDTH-1:0> Upper_Wrap_Boundary) {
412 
413 
414  int max_beat_cnt;
415  int dtsize;
416  bit <C_AXI_ADDR_WIDTH-1:0> Aligned_Address;
417 
418  max_beat_cnt = calculate_axlen(.addr (addr),
419  .burst_size (burst_size),
420  .burst_length (burst_length)) + 1;
421 
422  Aligned_Address=calculate_burst_aligned_address(.address(addr),
423  .burst_size(burst_size));
424 
425 
426  dtsize = (2**burst_size) * max_beat_cnt;
427 
428  Lower_Wrap_Boundary = (int(Aligned_Address/dtsize) * dtsize);
429  Upper_Wrap_Boundary = Lower_Wrap_Boundary + dtsize;
430 
431 }
432 
433 
448  input bit <C_AXI_ADDR_WIDTH-1:0> addr,
449  input bit <2:0> burst_size,
450  input shortint burst_length,
451  input bit <1:0> burst_type,
452  input int beat_cnt,
453  input int lane,
454  input int data_bus_bytes) {
455 
456  bit <C_AXI_ADDR_WIDTH-1:0> tmp_addr;
457 
458  int Lower_Byte_Lane;
459  int Upper_Byte_Lane;
460  int data_offset;
461  int Lower_Wrap_Boundary;
462  int Upper_Wrap_Boundary;
463  string s;
464  string msg_s;
465 
466 
467  calculate_wrap_boundary(.addr (addr),
468  .burst_size (burst_size),
469  .burst_length (burst_length),
470  .Lower_Wrap_Boundary (Lower_Wrap_Boundary),
471  .Upper_Wrap_Boundary (Upper_Wrap_Boundary));
472 
473  get_beat_N_byte_lanes(.addr (addr),
474  .burst_size (burst_size),
475  .burst_length (burst_length),
476  .burst_type (burst_type),
477  .beat_cnt (beat_cnt),
478  .data_bus_bytes(data_bus_bytes),
479  .Lower_Byte_Lane(Lower_Byte_Lane),
480  .Upper_Byte_Lane(Upper_Byte_Lane),
481  .offset(data_offset));
482 
483  if (burst_type == e_FIXED) {
484  tmp_addr=addr+(lane - Lower_Byte_Lane);
485  } else if (burst_type == e_INCR) {
486  tmp_addr=addr+data_offset+(lane - Lower_Byte_Lane);
487 
488  } else if (burst_type == e_WRAP) {
489 
490  tmp_addr=addr+data_offset+(lane - Lower_Byte_Lane);
491 
492  if (tmp_addr >= Upper_Wrap_Boundary) {
493  tmp_addr = Lower_Wrap_Boundary+(tmp_addr-Upper_Wrap_Boundary);
494  }
495 // \todo:do we have to worry about double-wrap?
496  } else {
497  uvm_error("AXI_PKG::get_next_address", $sformatf("Unknown burst_type: %0d", burst_type))
498  }
499 
500  msg_s="";
501 
502  $sformat(msg_s, "%s beat_cnt:%0d", msg_s, beat_cnt);
503  // $sformat(msg_s, "%s max_beat_cnt:%0d", msg_s, max_beat_cnt);
504  $sformat(msg_s, "%s lane:%0d", msg_s, lane);
505  $sformat(msg_s, "%s Lower_Byte_Lane:%0d", msg_s, Lower_Byte_Lane);
506  $sformat(msg_s, "%s Upper_Byte_Lane:%0d", msg_s, Upper_Byte_Lane);
507  $sformat(msg_s, "%s Lower_Wrap_Boundary:%0d(0x%0x)", msg_s, Lower_Wrap_Boundary, Lower_Wrap_Boundary);
508  $sformat(msg_s, "%s Upper_Wrap_Boundary:%0d(0x%0x)", msg_s, Upper_Wrap_Boundary, Upper_Wrap_Boundary);
509  $sformat(msg_s, "%s number_bytes:%0d", msg_s, (2**burst_size));
510  $sformat(msg_s, "%s data_offset:%0d", msg_s, data_offset);
511  $sformat(msg_s, "%s tmp_addr:%0d(0x%0x)", msg_s, tmp_addr, tmp_addr);
512 
513  uvm_info("axi_seq_item::get_next_address", msg_s, UVM_HIGH)
514 
515  return tmp_addr;
516 
517 }
518 
519 
520 
521 
539  input bit <C_AXI_ADDR_WIDTH-1:0> addr,
540  input bit <2:0> burst_size,
541  input shortint burst_length,
542  input bit <1:0> burst_type,
543  input int beat_cnt,
544  input int data_bus_bytes,
545  output int Lower_Byte_Lane,
546  output int Upper_Byte_Lane,
547  output int offset) {
548 
549 
550 
551  bit <63:0> Aligned_Start_Address;
552  bit <63:0> Address_N;
553  bit <63:0> Bus_Aligned_Address;
554  bit <63:0> Bus_Aligned_Address_N;
555 
556  string s;
557  string msg_s;
558 
559  int a;
560  int b;
561 
562  Aligned_Start_Address=calculate_burst_aligned_address(.address(addr),
563  .burst_size(burst_size));
564  Address_N = Aligned_Start_Address+(beat_cnt*(2**burst_size));
565 
566 
567 
568  // **********************
569  // a = int'(addr/data_bus_bytes) * data_bus_bytes;
570  Bus_Aligned_Address = calculate_bus_aligned_address(.addr(addr),
571  .bus_size(data_bus_bytes));
572  Bus_Aligned_Address_N = calculate_bus_aligned_address(.addr(Address_N),
573  .bus_size(data_bus_bytes));
574 
575 
576  // Adjust Lower_Byte_lane up if unaligned.
577  if (burst_type == e_FIXED) {
578  // if (beat_cnt==0) begin
579  Lower_Byte_Lane = addr - Bus_Aligned_Address;
580  Upper_Byte_Lane = Aligned_Start_Address + (2**burst_size) - 1 -
581  Bus_Aligned_Address;
582 
583  offset = beat_cnt*(2**burst_size);
584 
585 
586  } else {
587 
588  if (beat_cnt==0) {
589  Lower_Byte_Lane = addr - Bus_Aligned_Address;
590  Upper_Byte_Lane = Aligned_Start_Address + (2**burst_size) - 1 -
591  Bus_Aligned_Address;
592 
593  offset = 0;
594 
595  } else {
596  Lower_Byte_Lane = Address_N - Bus_Aligned_Address_N;
597  Upper_Byte_Lane = Lower_Byte_Lane + (2**burst_size) - 1;
598 
599  offset = Address_N - addr;
600  }
601  }
602 
603  msg_s="";
604  $sformat(msg_s, "%s beat_cnt:%0d", msg_s, beat_cnt);
605  $sformat(msg_s, "%s data_bus_bytes:%0d", msg_s, data_bus_bytes);
606  $sformat(msg_s, "%s NumberBytes (2**burst_size):%0d", msg_s, (2**burst_size));
607 
608  $sformat(msg_s, "%s addr:%0d", msg_s, addr);
609  $sformat(msg_s, "%s Aligned_Start_Address:%0d", msg_s, Aligned_Start_Address);
610  $sformat(msg_s, "%s Address_N:%0d", msg_s, Address_N);
611  $sformat(msg_s, "%s Lower_Byte_Lane:%0d", msg_s, Lower_Byte_Lane);
612  $sformat(msg_s, "%s Upper_Byte_Lane:%0d", msg_s, Upper_Byte_Lane);
613  $sformat(msg_s, "%s offset:%0d", msg_s, offset);
614 
615  uvm_info("axi_seq_item::get_beat_N_byte_lanes", msg_s, UVM_HIGH)
616 
617 
618 }
619 
620 
621 
622 
623 #include "axi_if_abstract.svh"
624 
625 
bit< AXI_SEQ_ITEM_W_NUM_BITS-1:0 > axi_seq_item_w_vector_t
Bit vector containing packed write data channel values.
Definition: axi_pkg.sv:154
logic< 1:0 > rresp
Definition: axi_pkg.sv:207
byte calculate_unalignment_offset(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input byte burst_size)
calculate how unaligned the address is from the burst size
Definition: axi_pkg.sv:374
logic< 2:0 > awprot
Definition: axi_pkg.sv:123
bit< C_AXI_LEN_WIDTH-1:0 > calculate_axlen(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length)
calculate awlen or arlen
Definition: axi_pkg.sv:320
parameter C_AXI_LEN_WIDTH
Definition: axi_pkg.sv:65
bit< AXI_SEQ_ITEM_AW_NUM_BITS-1:0 > axi_seq_item_aw_vector_t
Bit vector containing packed write address channel values.
Definition: axi_pkg.sv:132
localparam int AXI_SEQ_ITEM_R_NUM_BITS
Definition: axi_pkg.sv:214
logic< 1:0 > arburst
Definition: axi_pkg.sv:185
logic< C_AXI_ID_WIDTH-1:0 > bid
Definition: axi_pkg.sv:163
logic< C_AXI_ID_WIDTH-1:0 > awid
Definition: axi_pkg.sv:114
logic< 2:0 > arsize
Definition: axi_pkg.sv:184
logic< C_AXI_DATA_WIDTH/8-1:0 > wstrb
Definition: axi_pkg.sv:143
logic< 3:0 > awqos
Definition: axi_pkg.sv:124
This packed struct is used to send read data channel information between the DUT and TB...
Definition: axi_pkg.sv:205
logic< 0:0 > awlock
Definition: axi_pkg.sv:121
This packed struct is used to send write address channel information between the DUT and TB...
Definition: axi_pkg.sv:113
localparam int AXI_SEQ_ITEM_W_NUM_BITS
Definition: axi_pkg.sv:150
logic< 1:0 > bresp
Definition: axi_pkg.sv:164
parameter AXI_ID_WIDTH
Definition: params_pkg.sv:44
logic< 2:0 > awsize
Definition: axi_pkg.sv:119
logic< C_AXI_DATA_WIDTH-1:0 > wdata
Definition: axi_pkg.sv:142
logic< C_AXI_DATA_WIDTH-1:0 > rdata
Definition: axi_pkg.sv:206
parameter C_AXI_ID_WIDTH
Definition: axi_pkg.sv:41
logic< 2:0 > arprot
Definition: axi_pkg.sv:188
bit< C_AXI_ADDR_WIDTH-1:0 > get_next_address(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length, input bit< 1:0 > burst_type, input int beat_cnt, input int lane, input int data_bus_bytes)
Get next address for reading/writing to memory.
Definition: axi_pkg.sv:447
bit< C_AXI_ADDR_WIDTH-1:0 > calculate_burst_aligned_address(input bit< C_AXI_ADDR_WIDTH-1:0 > address, input bit< 2:0 > burst_size)
calculate burst_size aligned address
Definition: axi_pkg.sv:230
logic< 3:0 > arcache
Definition: axi_pkg.sv:187
logic< 3:0 > arqos
Definition: axi_pkg.sv:189
bit< AXI_SEQ_ITEM_R_NUM_BITS-1:0 > axi_seq_item_r_vector_t
Bit vector containing packed read data channel values.
Definition: axi_pkg.sv:218
parameter AXI_LEN_WIDTH
Definition: params_pkg.sv:47
logic< C_AXI_ID_WIDTH-1:0 > arid
Definition: axi_pkg.sv:179
burst_type_t
Does the address stay fixed, increment, or wrap during the burst?
Definition: axi_pkg.sv:89
response_type_t
Write response values.
Definition: axi_pkg.sv:98
logic< 3:0 > awcache
Definition: axi_pkg.sv:122
parameter C_AXI_DATA_WIDTH
Definition: axi_pkg.sv:48
logic< C_AXI_ID_WIDTH-1:0 > wid
Definition: axi_pkg.sv:146
logic< C_AXI_ID_WIDTH-1:0 > rid
Definition: axi_pkg.sv:210
burst_size_t
Size of beat in bytes. (How many bytes of the data bus are used each beat(clk).
Definition: axi_pkg.sv:76
logic< C_AXI_ADDR_WIDTH-1:0 > araddr
Definition: axi_pkg.sv:180
bit< AXI_SEQ_ITEM_B_NUM_BITS-1:0 > axi_seq_item_b_vector_t
Bit vector containing packed write response channel values.
Definition: axi_pkg.sv:171
parameter AXI_ADDR_WIDTH
Definition: params_pkg.sv:45
logic< C_AXI_ADDR_WIDTH-1:0 > awaddr
Definition: axi_pkg.sv:115
parameter C_AXI_ADDR_WIDTH
Definition: axi_pkg.sv:59
localparam int AXI_SEQ_ITEM_B_NUM_BITS
Definition: axi_pkg.sv:167
logic< C_AXI_LEN_WIDTH-1:0 > awlen
Definition: axi_pkg.sv:118
This packed struct is used to send write data channel information between the DUT and TB...
Definition: axi_pkg.sv:141
void get_beat_N_byte_lanes(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length, input bit< 1:0 > burst_type, input int beat_cnt, input int data_bus_bytes, output int Lower_Byte_Lane, output int Upper_Byte_Lane, output int offset)
return byte lanes that contain valid data
Definition: axi_pkg.sv:538
logic< C_AXI_LEN_WIDTH-1:0 > arlen
Definition: axi_pkg.sv:183
void calculate_wrap_boundary(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length, output bit< C_AXI_ADDR_WIDTH-1:0 > Lower_Wrap_Boundary, output bit< C_AXI_ADDR_WIDTH-1:0 > Upper_Wrap_Boundary)
calculate the wrap boundaries for a given burst
Definition: axi_pkg.sv:406
logic< 0:0 > arlock
Definition: axi_pkg.sv:186
bit< C_AXI_ADDR_WIDTH-1:0 > calculate_bus_aligned_address(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input int bus_size)
calculate bus-siz aligned address
Definition: axi_pkg.sv:272
This packed struct is used to send write response channel information between the DUT and TB...
Definition: axi_pkg.sv:162
localparam int AXI_SEQ_ITEM_AW_NUM_BITS
Definition: axi_pkg.sv:128
logic< 1:0 > awburst
Definition: axi_pkg.sv:120
parameter AXI_DATA_WIDTH
Definition: params_pkg.sv:46
localparam int AXI_SEQ_ITEM_AR_NUM_BITS
Definition: axi_pkg.sv:193
bit< AXI_SEQ_ITEM_AR_NUM_BITS-1:0 > axi_seq_item_ar_vector_t
Bit vector containing packed read address channel values.
Definition: axi_pkg.sv:197
This packed struct is used to send read address channel information between the DUT and TB...
Definition: axi_pkg.sv:178