-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathaxi_item.svh
461 lines (424 loc) · 14.4 KB
/
axi_item.svh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
`ifndef AXI_ITEM_SVH
`define AXI_ITEM_SVH
/*AXI ITEM*/
class axi_item extends sequence_item_base #(
.CONFIGURATION(dma_axi_configuration),
.STATUS(dma_axi_status)
);
// dma_axi_configuration configuration;
rand axi_access_type access_type;
rand axi_id id;
rand axi_address address;
rand int burst_length;
rand int burst_size;
rand axi_data data[];
rand axi_strobe strobe[];
rand axi_response response[];
rand int start_delay;
rand int write_data_delay[];
rand int response_delay[];
rand int address_ready_delay;
rand int write_data_ready_delay[];
rand int response_ready_delay[];
uvm_event address_begin_event;
time address_begin_time;
uvm_event address_end_event;
time address_end_time;
uvm_event write_data_begin_event;
time write_data_begin_time;
uvm_event write_data_end_event;
time write_data_end_time;
uvm_event response_begin_event;
time response_begin_time;
uvm_event response_end_event;
time response_end_time;
rand bit need_response;
// Event handler
function uvm_event get_event(string name);
uvm_event_pool event_pool = get_event_pool();
return event_pool.get(name);
endfunction : get_event
function bit began();
uvm_event event_handle = get_event("begin");
return event_handle.is_on();
endfunction : began
function bit ended();
uvm_event event_handle = get_event("end");
return event_handle.is_on();
endfunction : ended
task wait_for_begin(bit x=0);
uvm_event begin_event = get_event("begin");
begin_event.wait_on(x);
endtask : wait_for_begin
task wait_for_end(bit y=0);
uvm_event end_event = get_event("end");
end_event.wait_on(y);
endtask : wait_for_end
// `uvm_object_utils(axi_item)
function new(string name="axi_item");
super.new(name);
address_begin_event = get_event("address_begin");
address_end_event = get_event("address_end");
write_data_begin_event = get_event("write_data_begin");
write_data_end_event = get_event("write_data_end");
response_begin_event = get_event("response_begin");
response_end_event = get_event("response_end");
endfunction : new
function bit is_write();
return (access_type == AXI_WRITE) ? 1'b1 : 1'b0;
endfunction : is_write
function bit is_read();
return (access_type == AXI_READ) ? 1'b1 : 1'b0;
endfunction : is_read
function int get_burst_length();
if ((configuration!=null) && (configuration.protocol==AXI4LITE))
return 1;
else
return burst_length;
endfunction : get_burst_length
function axi_burst_length get_packed_burst_length();
return pack_bl(get_burst_length());
endfunction : get_packed_burst_length
function void set_packed_burst_length(axi_burst_length packed_bl);
if ((configuration!=null) && (configuration.protocol==AXI4LITE))
burst_length = 1;
else
burst_length = unpack_bl(packed_bl);
endfunction : set_packed_burst_length
function int get_burst_size();
if ((configuration!=null) && (configuration.protocol==AXI4LITE))
return configuration.data_width/8;
else
return burst_size;
endfunction : get_burst_size
function axi_burst_size get_packed_burst_size();
case (get_burst_size())
8: return 2'b00;
16: return 2'b01;
32: return 2'b10;
64: return 2'b11;
default: return 2'b00;
endcase
endfunction : get_packed_burst_size
function void set_packed_burst_size(axi_burst_size packed_bs);
if ((configuration!=null) && (configuration.protocol==AXI4LITE))
burst_size = configuration.data_width/8;
else
burst_size = get_bs(packed_bs);
endfunction : set_packed_burst_size
// Assign data
function void put_data(const ref axi_data data[$]);
this.data = new[data.size()];
foreach (data[i]) begin
this.data[i] = data[i];
end
endfunction : put_data
function axi_data get_data(int index);
if (index < data.size()) begin
return data[index];
end
else
return '0;
endfunction : get_data
// Assign strobe
function void put_strobe(const ref axi_strobe strobe[$]);
this.strobe = new[strobe.size()];
foreach (strobe[i]) begin
this.strobe[i] = strobe[i];
end
endfunction : put_strobe
function axi_strobe get_strobe (int index);
if (index < strobe.size())
return strobe[index];
else
return '0;
endfunction : get_strobe
// Assign response
function void put_response(const ref axi_response response[$]);
this.response = new[response.size()];
foreach (response[i]) begin
this.response[i] = response[i];
end
endfunction : put_response
function axi_response get_response(int index);
if (index < response.size())
return response[index];
else
return AXI_OKAY;
endfunction : get_response
/*Event Control*/
// Address event control
function void begin_address (time begin_time=0);
if (address_begin_event.is_off()) begin
address_begin_time = (begin_time<=0) ? $time : begin_time;
address_begin_event.trigger();
end
endfunction : begin_address
function void end_address (time end_time=0);
if (address_end_event.is_off()) begin
address_end_time = (end_time<=0) ? $time : end_time;
address_end_event.trigger();
end
endfunction : end_address
function bit address_began();
return address_begin_event.is_on();
endfunction : address_began
function bit address_ended();
return address_end_event.is_on();
endfunction : address_ended
// Write data event control
function void begin_write_data (time begin_time=0);
if (write_data_begin_event.is_off()) begin
write_data_begin_time = (begin_time<=0) ? $time : begin_time;
write_data_begin_event.trigger();
end
endfunction : begin_write_data
function void end_write_data (time end_time=0);
if (write_data_end_event.is_off()) begin
write_data_end_time = (end_time<=0) ? $time : end_time;
write_data_end_event.trigger();
end
endfunction : end_write_data
function bit write_data_began();
return write_data_begin_event.is_on();
endfunction : write_data_began
function bit write_data_ended();
return write_data_end_event.is_on();
endfunction : write_data_ended
// Response event control
function void begin_response (time begin_time=0);
if (response_begin_event.is_off()) begin
response_begin_time = (begin_time<=0) ? $time : begin_time;
response_begin_event.trigger();
end
endfunction : begin_response
function void end_response (time end_time=0);
if (response_end_event.is_off()) begin
response_end_time = (end_time<=0) ? $time : end_time;
response_end_event.trigger();
end
endfunction : end_response
function bit response_began();
return response_begin_event.is_on();
endfunction : response_began
function bit response_ended();
return response_end_event.is_on();
endfunction : response_ended
function bit request_began();
return address_began();
endfunction : request_began
function bit request_ended();
if (is_write()) begin
return (address_ended() && write_data_ended()) ? 1 : 0;
end
else begin
return address_ended();
end
endfunction : request_ended
task wait_for_done();
response_end_event.wait_on();
endtask : wait_for_done
/*Event Control*/
`uvm_object_utils_begin(axi_item)
// `uvm_field_object(configuration, UVM_REFERENCE|UVM_PACK|UVM_NOCOMPARE|UVM_NOPRINT|UVM_NORECORD)
`uvm_field_int(id, UVM_DEFAULT|UVM_HEX)
`uvm_field_enum(axi_access_type, access_type, UVM_DEFAULT)
`uvm_field_int(address, UVM_DEFAULT|UVM_HEX)
`uvm_field_int(burst_length, UVM_DEFAULT|UVM_DEC)
`uvm_field_int(burst_size, UVM_DEFAULT|UVM_DEC)
`uvm_field_array_int(data, UVM_DEFAULT|UVM_HEX)
`uvm_field_array_int(strobe, UVM_DEFAULT|UVM_HEX)
`uvm_field_array_enum(axi_response, response, UVM_DEFAULT)
`uvm_field_int(start_delay, UVM_DEFAULT|UVM_DEC|UVM_NOCOMPARE)
`uvm_field_array_int(write_data_delay, UVM_DEFAULT|UVM_DEC|UVM_NOCOMPARE)
`uvm_field_array_int(response_delay, UVM_DEFAULT|UVM_DEC|UVM_NOCOMPARE)
`uvm_field_int(address_ready_delay, UVM_DEFAULT|UVM_DEC|UVM_NOCOMPARE)
`uvm_field_array_int(write_data_ready_delay, UVM_DEFAULT|UVM_DEC|UVM_NOCOMPARE)
`uvm_field_array_int(response_ready_delay, UVM_DEFAULT|UVM_DEC|UVM_NOCOMPARE)
`uvm_field_int(address_begin_time, UVM_DEFAULT|UVM_TIME|UVM_NOCOMPARE)
`uvm_field_int(address_end_time, UVM_DEFAULT|UVM_TIME|UVM_NOCOMPARE)
`uvm_field_int(write_data_begin_time, UVM_DEFAULT|UVM_TIME|UVM_NOCOMPARE)
`uvm_field_int(write_data_end_time, UVM_DEFAULT|UVM_TIME|UVM_NOCOMPARE)
`uvm_field_int(response_begin_time, UVM_DEFAULT|UVM_TIME|UVM_NOCOMPARE)
`uvm_field_int(response_end_time, UVM_DEFAULT|UVM_TIME|UVM_NOCOMPARE)
`uvm_field_int(need_response, UVM_DEFAULT|UVM_NOCOMPARE|UVM_NOPRINT)
`uvm_object_utils_end
endclass : axi_item
/*AXI ITEM*/
/*AXI MASTER ITEM*/
class axi_master_item extends axi_item;
constraint c_valid_id {
(id >> this.configuration.id_width) == 0;
}
constraint c_valid_address {
(address >> this.configuration.address_width) == 0;
}
constraint c_valid_burst_length {
if (this.configuration.protocol == AXI4LITE)
burst_length == 1;
else
burst_length inside {[1 : this.configuration.max_burst_length]};
}
constraint c_valid_burst_size {
if (this.configuration.protocol == AXI4LITE) {
(8*burst_size) == this.configuration.data_width;
}
else {
burst_size inside {1, 2, 4};
(8*burst_size) <= this.configuration.data_width;
}
}
// 4kb boundary
constraint c_valid_data {
solve access_type before data;
solve burst_length before data;
(access_type==AXI_WRITE) -> data.size()==burst_length;
(access_type==AXI_READ) -> data.size()==0;
foreach(data[i]) {
(data[i] >> this.configuration.data_width) == 0;
}
}
constraint c_valid_strobe {
solve access_type before strobe;
solve burst_length before strobe;
(access_type==AXI_WRITE) -> strobe.size()==burst_length;
(access_type==AXI_READ) -> strobe.size()==0;
foreach(strobe[i]) {
(strobe[i] >> this.configuration.strobe_width) == 0;
}
}
constraint c_start_delay {
`delay_constraint(start_delay, this.configuration.request_start_delay)
}
constraint c_write_data_delay {
solve access_type, burst_length before write_data_delay;
if (access_type==AXI_WRITE)
write_data_delay.size() == burst_length;
else
write_data_delay.size() == 0;
foreach(write_data_delay[i]) {
`delay_constraint(write_data_delay[i], this.configuration.write_data_delay)
}
}
constraint c_response_ready_delay {
solve access_type, burst_length before response_ready_delay;
if (access_type == AXI_WRITE) {
response_ready_delay.size() == 1;
}
else {
response_ready_delay.size() == burst_length;
}
foreach(response_ready_delay[i]) {
if (access_type == AXI_WRITE) {
`delay_constraint(response_ready_delay[i], this.configuration.bready_delay)
}
else {
`delay_constraint(response_ready_delay[i], this.configuration.rready_delay)
}
}
}
constraint c_default_need_response {
soft need_response == 0;
}
function void pre_randomize();
super.pre_randomize();
response.rand_mode(0);
response_delay.rand_mode(0);
address_ready_delay.rand_mode(0);
write_data_ready_delay.rand_mode(0);
//test
/* access_type.rand_mode(0);
id.rand_mode(0);
address.rand_mode(0);
burst_length.rand_mode(0);
burst_size.rand_mode(0);
data.rand_mode(0);
strobe.rand_mode(0);
response.rand_mode(0);
start_delay.rand_mode(0);
write_data_delay.rand_mode(0);
*/ //test
endfunction : pre_randomize
`uvm_object_utils(axi_master_item)
function new(string name="axi_master_item");
super.new(name);
endfunction : new
endclass : axi_master_item
/*AXI MASTER ITEM*/
/*AXI SLAVE ITEM*/
class axi_slave_item extends axi_item;
constraint c_valid_data {
data.size() == burst_length;
foreach(data[i]) {
(data[i]>>this.configuration.data_width) == 0;
}
}
constraint c_valid_response {
(access_type == AXI_WRITE) -> response.size()==1;
(access_type == AXI_READ) -> response.size()==burst_length;
foreach(response[i]) {
response[i] dist{
AXI_OKAY := this.configuration.response_weight_okay,
AXI_EXOKAY := this.configuration.response_weight_exokay,
AXI_SLAVE_ERROR := this.configuration.response_weight_slave_error,
AXI_DECODE_ERROR := this.configuration.response_weight_decode_error
};
}
}
constraint c_address_ready_delay {
if (access_type == AXI_WRITE) {
`delay_constraint(address_ready_delay, this.configuration.awready_delay)
}
else {
`delay_constraint(address_ready_delay, this.configuration.arready_delay)
}
}
constraint c_write_data_ready_delay {
if (access_type == AXI_WRITE) {
write_data_ready_delay.size() == burst_length;
}
else {
write_data_ready_delay.size() == 0;
}
foreach(write_data_ready_delay[i]) {
`delay_constraint(write_data_ready_delay[i], this.configuration.wready_delay)
}
}
constraint c_start_delay {
`delay_constraint(start_delay, this.configuration.response_start_delay)
}
constraint c_response_delay {
if (access_type == AXI_WRITE)
response_delay.size() == 1;
else
response_delay.size() == burst_length;
foreach(response_delay[i]) {
`delay_constraint(response_delay[i], this.configuration.response_delay)
}
}
constraint c_default_need_response {
soft need_response == 1;
}
function void pre_randomize ();
super.pre_randomize();
access_type.rand_mode(0);
id.rand_mode(0);
address.rand_mode(0);
burst_length.rand_mode(0);
burst_size.rand_mode(0);
//burst_type.rand_mode(0);
if (access_type == AXI_WRITE) begin
data.rand_mode(0);
c_valid_data.constraint_mode(0);
end
strobe.rand_mode(0);
write_data_delay.rand_mode(0);
response_ready_delay.rand_mode(0);
endfunction : pre_randomize
`uvm_object_utils(axi_slave_item)
function new(string name="axi_slave_item");
super.new(name);
endfunction : new
endclass : axi_slave_item
/*AXI SLAVE ITEM*/
`endif