You are on page 1of 162

1 -------------------------------------------------------==========-------------------------------------------------

2 //======================================================MEMORIES==================================================
3 -------------------------------------------------------==========-------------------------------------------------
4 class
5
6
7 //Declaring and Initializing Fixed-Size Arrays
8 ------------------------------------------------
9 In verilog in array declaration we have to mention LSB(lower limit) & MSB(Higher limit)
10 But in SYstem Verilog we can declare a array by just giving array size.
11
12 Eg.
13 Verilog int array[0:15] ; //16 array [0]......[15]
14 SYstem V int array[16] ;
15
16 Eg.
17 int array2 [0:7] [0:3] ; //Verbose Declaration
18 int array2 [8][4] //Compact Declaration
19
20 /* If your code accidently tries to read from an out-of-bounds address, SystemVerilog
21 will return the default value for the array element type. That just means that an array
22 of 4-state types, such as logic, will return X’s, whereas an array of 2-state types,
23 such as int or bit, will return 0. This applies for all array types – fixed, dynamic,
24 associative, or queue, and also if your address has an X or Z.
25 */
26
27 ==================
28 //DYNAMIC ARRAY
29 ==================
30
31 1. A dynamic array is declared with empty word subscripts [] or square bracket.
32 2. You .do .not .specify the array size at compile time; instead, you give it at run-time.
33 3. The array is initially empty, and so you must call the new[] constructor to allocate space, passing
34 in the number of entries in the square brackets
35
36
37
38
39
40
41
42
43
44 module dynamic;
45 .-------------------------------------------. o
46 | int dyn[], d2[]; | // Empty dynamic arrays
47 | |
48 | initial |
49 | begin |
50 | dyn = new[5]; | // Allocate 5 elements
51 | foreach (dyn[j]) |
52 | dyn[j] = j; | // Initialize the elements
53 | d2 = dyn; | // Copy a dynamic array
54 | d2[0] = 5; | // Modify the copy
55 | |
56 | $display(dyn[0],d2[0]); | // See both values (0 & 5)
57 | dyn = new[20](dyn); | // Expand and copy
58 | dyn = new[100]; | // Allocate 100 new integers ,Old values are lost
59 | dyn.size | // Size of dyn is 100
60 | dyn.delete; | // Delete all elements
61 | end |
62 '-------------------------------------------'
63 endmodule
64
65 //Adding New Element to Existing Dynamic Arrays:
66 -------------------------------------------------
67 module dynamic;
68 int dyn[];
69
70 initial
71 begin
72 dyn=new[5];
73 dyn= '{1, 2, 3, 4, 5};
74
75 dyn=new[dyn.size()+1](dyn); //Expand and copy
76
77 dyn[dyn.size()-1]=6; //dyn[5]=6
78 $display ("New dyn = %p", dyn); // New dyn='{1,2,3,4,5,6}
79 end
80
81 endmodule
82
83
84
85
86
87 //QUEUES
88 ==========
89 /*
90 1. SystemVerilog introduces a new data type, the queue, which provides easy
91 searching and sorting in a structure that is as fast as a fixed-size array but as
92 versatile as a linked list.
93
94 2. Like a dynamic array, queues can grow and shrink, but with a queue you
95 can easily add and remove elements anywhere
96 */
97 module queue;
98
99 int j = 1,
100 b[$] = {3,4},
101 q[$] = {0,2,5}; // {0,2,5} Initial queue
102
103 initial
104 begin
105 q.insert(1, j); // {0,1,2,5} Insert 1 before 2
106 q.insert(3, b); // {0,1,2,3,4,5} Insert whole q.
107 q.delete(1); // {0,2,3,4,5} Delete elem. #1
108 q.push_front(6); // {6,0,2,3,4,5} Insert at front
109 j = q.pop_back; // {6,0,2,3,4} j = 5
110 q.push_back(8); // {6,0,2,3,4,8} Insert at back
111 j = q.pop_front; // {0,2,3,4,8} j = 6
112 foreach (q[i])
113 $display(q[i]);
114 q.delete(); /*{}*/
115 end
116 endmodule
117 /* 3. If you add enough elements so that the queue
118 runs out of space, SystemVerilog automatically allocates additional space.
119
120 4. It is very efficient to push and pop elements from the front and back of a
121 queue, taking a fixed amount of time no matter how large the queue.
122
123 5. Adding and deleting elements in the middle is slower as
124 SystemVerilog has to shift up to half of the elements.
125
126 6. The LRM does not allow inserting a queue in another queue using the above methods.
127
128 7. You can use word subscripts and concatenation instead of methods. As a shortcut,
129 if you put a $ on the left side of a range, such as [$:2] , the $ stands for the
130 minimum value, [0:2] . A $ on the right side, as in [1:$] , stands for the maximum
131 value, [1:2]
132
133 */
134 /*
135 int j = 1,
136 q2[$] = {3,4}, // Queue literals do not use Õ
137 q[$] = {0,2,5}; // {0,2,5}
138 initial
139 begin // Result
140
141 q = {q[0], j, q[1:$]}; // {0,1,2,5} Insert 1 before 2
142 q = {q[0:2], q2, q[3:$]}; // {0,1,2,3,4,5} Insert queue in q
143 q = {q[0], q[2:$]}; // {0,2,3,4,5} Delete elem. #1
144 q = {6, q}; // {6,0,2,3,4,5} Insert at front
145 j = q[$]; // j = 5 Equivalent of pop_back
146 q = q[0:$-1]; // {6,0,2,3,4}
147 q = {q, 8}; // {6,0,2,3,4,8} Insert at back
148 j = q[0]; // j = 6 Equivalent of pop_front
149 q = q[1:$]; // {0,2,3,4,8}
150 q = {}; // {} Delete entire queue
151
152 end
153
154 int j = 1,
155 q2[$] = {3,4}, // Queue literals do not use Õ
156 q[$] = {0,2,5}; // {0,2,5}
157
158 initial | initial
159 begin | begin // Result
160 |
161 q = {q[0], j, q[1:$]}; | q.insert(1, j); // {0,1,2,5} Insert 1 before 2
162 q = {q[0:2], q2, q[3:$]}; | q.insert(3, q2); // {0,1,2,3,4,5} Insert queue in q
163 q = {q[0], q[2:$]}; | q.delete(1); // {0,2,3,4,5} Delete elem. #1
164 q = {6, q}; | q.push_front(6); // {6,0,2,3,4,5} Insert at front
165 j = q[$]; | j = q.pop_back; // j = 5 Equivalent of pop_back
166 q = q[0:$-1]; | // {6,0,2,3,4}
167 q = {q, 8}; | q.push_back(8); // {6,0,2,3,4,8} Insert at back
168 j = q[0]; | j = q.pop_front; // j = 6 Equivalent of pop_front
169 q = q[1:$]; | // {0,2,3,4,8}
170 q = {}; | q.delete(); // {} Delete entire queue
171 |
172 end | end
173 */
174
175 //ASSOCIATIVE ARRAY
176 ====================
177
178 /*
179 1. When size of a collection is unknown or the data space is sparse, an associative array is
180 a better option.
181 2. Associative arrays do not have any storage allocated until it is used.
182 3. Index expression is not restricted to integral expressions, but can be of any type.
183
184 */
185 SYNTAX:
186 --------
187
188 data_type array_identifier [ index_type ];
189
190
191 int array1 [int]; // An integer array with integer index
192 int array2 [string]; // An integer array with string index
193
194 string array3 [string]; // A string array with string index
195
196
197 _______________________________________________________________________
198
199 ||| ||| ||| ||| ||| |||
200 DATA ||| ||| ||| ||| ||| |||
201 ||| ||| ||| ||| ||| |||
202 _______________________________________________________________________
203
204 INDEX 3 5 100 1245 6544 200,000,000
205
206
207
208
209
210
211
212
213
214
215
216 // EXAMPLE:
217 ----------
218 module tb;
219
220 int array1 [int];
221 int array2 [string];
222 string array3 [string];
223
224 initial
225 begin
226 // Initialize each dynamic array with some values
227 array1 = '{ 1 : 22,6 : 34 };
228 array2 = '{ "Ross" : 100,"Joey" : 60 };
229 array3 = '{ "Apples" : "Oranges","Pears" : "44" };
230
231 // Print each array
232 $display ("array1 = %p", array1);
233 $display ("array2 = %p", array2);
234 $display ("array3 = %p", array3);
235 end
236 endmodule
237
238 /* OUTPUT:
239
240 array1 = '{ 1 : 22,6 : 34 }
241 array2 = '{ "Ross" : 100,"Joey" : 60 }
242 array3 = '{ "Apples" : "Oranges","Pears" : "44" }
243 */
244
245 //Associative Array Methods
246 -----------------------------
247
248 .========================================.===============================================================.
249 | /* FUNCTION */ |/* DESCRIPTION */ |
250 |========================================================================================================|
251 /* | | |.
252 | function int num (); | Returns the number of entries in the associative array |
253 | | |
254 | function int size (); | Also returns the number of entries, .if empty 0 is returned |.
255 | | |
256 | function void delete ([input index] ); | index when specified deletes the entry at that index, |
257 | | .else the whole array is deleted |
258 | | |.
259 | function int exists (input index); | Checks whether an element exists at specified index; |
260 | | returns 1 .if it does, .else 0 |
261 | | |.
262 | function int first (ref index); | Assigns to the given index variable the value of the first |
263 | | index; returns 0 .for empty array |
264 | | |.
265 | function int last (ref index); | Assigns to given index variable the value of the last index |
266 | | returns 0 .for empty array |
267 | | |.
268 | function int next (ref index); | Finds the smallest index whose value is greater than the |
269 | | given index |
270 | | |.
271 | function int prev (ref index); | Finds the largest index whose value is smaller than the |
272 | | given index |
273 | | |
274 '----------------------------------------'---------------------------------------------------------------'
275
276 */
277 //Methods Example:
278 -------------------
279
280 module associative_array;
281
282 int fruits_l0 [string];
283
284 initial
285 begin
286 fruits_l0 = '{ "apple" : 4,"orange" : 10,"plum" : 9,"guava" : 1 };
287
288 // size() : Print the number of items in the given associative array
289 $display ("fruits_l0.size() = %0d", fruits_l0.size());
290
291 // num() : Another function to print number of items in given array
292 $display ("fruits_l0.num() = %0d", fruits_l0.num());
293
294 // exists() : Check if a particular key exists in this dynamic array
295 if (fruits_l0.exists ("orange"))
296 $display ("Found %0d orange !", fruits_l0["orange"]);
297 if (!fruits_l0.exists ("apricots"))
298 $display ("Sorry, season for apricots is over ...");
299 // Note: String indices are taken in alphabetical order
300 // first() : Get the first element in the array
301 begin
302 string f;
303 // This function returns true if it succeeded and first key is stored
304 //in the provided string "f"
305 if (fruits_l0.first (f))
306 $display ("fruits_l0.first [%s] = %0d", f, fruits_l0[f]);
307 end
308 // last() : Get the last element in the array
309 begin
310 string f;
311
312 if (fruits_l0.last (f))
313 $display ("fruits_l0.last [%s] = %0d", f, fruits_l0[f]);
314 end
315
316 // prev() : Get the previous element in the array
317 begin
318 string f = "orange";
319
320 if (fruits_l0.prev (f))
321 $display ("fruits_l0.prev [%s] = %0d", f, fruits_l0[f]);
322 end
323
324 // next() : Get the next item in the array
325 begin
326 string f = "orange";
327
328 if (fruits_l0.next (f))
329 $display ("fruits_l0.next [%s] = %0d", f, fruits_l0[f]);
330 end
331 end
332 endmodule
333
334 /*OUTPUT:
335
336 fruits_l0.size() = 4
337 fruits_l0.num() = 4
338 Found 10 orange !
339 Sorry, season for apricots is over ...
340 fruits_l0.first [apple] = 4
341 fruits_l0.last [plum] = 9
342 fruits_l0.prev [guava] = 1
343 fruits_l0.next [plum] = 9
344
345 */
346
347 ===================================
348 //SystemVerilog Array Manipulation
349 ===================================
350 /*
351 1. Array manipulation methods simply iterate through the array elements.
352 2. Each element is used to evaluate the expression specified by the with clause.
353 3. The iterator argument specifies a local variable that can be used within the with expression to
354 refer to the current element in the iteration.
355 4. If an argument is not provided, item is the name used by default.
356 */
357
358 //Array Locator Methods
359 -----------------------
360
361 The with clause and expresison is mandatory for some of these methods and for
362 some others its optional.
363
364
365 //Mandatory 'with' clause
366 ---------------------------
367
368 1. These methods are used to filter out certain elements from an existing array based
369 on a given expression.
370 2. All such elements that satisfy the given expression is put into an array and returned.
371 3. Hence the with clause is mandatory for the following methods.
372
373 .=================================================================================================.
374 |/* METHOD NAME */|/* DESCRIPTION */|
375 |=================================================================================================|
376 | find() | Returns all elements satisfying the given expression |
377 | | |
378 | find_index() | Returns the indices of all elements satisfying the given expression |
379 | | |
380 | find_first() | Returns the first element satisfying the given expression |
381 | | |
382 | find_first_index() | Returns the index of the first element satisfying the given expression|
383 | | |
384 | find_last() | Returns the last element satisfying the given expression |
385 | | |
386 | find_last_index() | Returns the index of the last element satisfying the given expression |
387 '-------------------------------------------------------------------------------------------------'
388
389
390 //EXAMPLE:
391 -----------
392
393 module tb;
394
395 int array[9] = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
396 int res[$];
397
398 initial
399 begin
400 res = array.find(x) with (x > 3);
401 $display ("find(x) : %p", res);
402
403 res = array.find_index with (item == 4);
404 $display ("find_index : res[%0d] = 4", res[0]);
405
406 res = array.find_first with (item < 5 & item >= 3);
407 $display ("find_first : %p", res);
408
409 res = array.find_first_index(x) with (x > 5);
410 $display ("find_first_index: %p", res);
411
412 res = array.find_last with (item <= 7 & item > 3);
413 $display ("find_last : %p", res);
414
415 res = array.find_last_index(x) with (x < 3);
416 $display ("find_last_index : %p", res);
417 end
418 endmodule
419
420 /*OUTPUT
421
422 find(x) : '{4, 7, 5, 7, 6}
423 find_index : res[0] = 4
424 find_first : '{4}
425 find_first_index: '{1}
426 find_last : '{6}
427 find_last_index : '{8}
428
429 */
430
431 //Optional 'with' clause
432 ------------------------
433
434 .=================================================================================================.
435 |/* METHOD NAME */|/* DESCRIPTION */|
436 |=================================================================================================|
437 | min() | Returns the element with minimum value or whose expression |
438 | | evaluates to a minimum |
439 | | |
440 | max() | Returns the element with maximum value or whose expression |
441 | | evaluates to a maximum |
442 | | |
443 | unique() | Returns all elements with unique values or whose expression |
444 | | evaluates to a unique value |
445 | | |
446 | unique_index() | Returns the indices of all elements with unique values or |
447 | | whose expression evaluates to a unique value |
448 '-------------------------------------------------------------------------------------------------'
449
450 //EXAMPLE:
451 -----------
452
453 module tb;
454
455 int array[9] = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
456 int res[$];
457
458 initial
459 begin
460 res = array.min();
461 $display ("min : %p", res);
462
463 res = array.max();
464 $display ("max : %p", res);
465
466 res = array.unique();
467 $display ("unique : %p", res);
468
469 res = array.unique(x) with (x < 3);
470 $display ("unique : %p", res);
471
472 res = array.unique_index;
473 $display ("unique_index : %p", res);
474 end
475 endmodule
476
477 /*OUTPUT
478
479 min : '{1}
480 max : '{7}
481 unique : '{4, 7, 2, 5, 1, 6, 3}
482 unique : '{4, 2}
483 unique_index : '{0, 1, 2, 3, 5, 6, 7}
484
485 */
486
487 =========================
488 //Array Ordering Methods
489 =========================
490
491 .===============================================================================================.
492 |/* METHOD NAME */|/* DESCRIPTION */|
493 |===============================================================================================|
494 | reverse() | Reverses the order of elements in the array |
495 | sort() | Sorts the array in ascending order, optionally using with clause |
496 | rsort() | Sorts the array in descending order, optionally using with clause |
497 | shuffle() | Randomizes the order of the elements in the array. with clause is not |
498 | | allowed here |
499 '-----------------------------------------------------------------------------------------------'
500
501 //EXAMPLE:
502 ----------
503
504 module tb;
505
506 int array[9] = '{4, 7, 2, 5, 7, 1, 6, 3, 1};
507
508 initial
509 begin
510 array.reverse();
511 $display ("reverse : %p", array);
512
513 array.sort();
514 $display ("sort : %p", array);
515
516 array.rsort();
517 $display ("rsort : %p", array);
518
519 for (int i = 0; i < 5; i++)
520 begin
521 array.shuffle();
522 $display ("shuffle Iter:%0d = %p", i, array);
523 end
524 end
525 endmodule
526
527 /*OUTPUT
528
529 reverse : '{1, 3, 6, 1, 7, 5, 2, 7, 4}
530 sort : '{1, 1, 2, 3, 4, 5, 6, 7, 7}
531 rsort : '{7, 7, 6, 5, 4, 3, 2, 1, 1}
532
533 shuffle Iter:0 = '{6, 7, 1, 7, 3, 2, 1, 4, 5}
534 shuffle Iter:1 = '{5, 1, 3, 4, 2, 7, 1, 7, 6}
535 shuffle Iter:2 = '{3, 1, 7, 4, 6, 7, 1, 2, 5}
536 shuffle Iter:3 = '{6, 4, 7, 3, 1, 7, 5, 2, 1}
537 shuffle Iter:4 = '{3, 6, 2, 5, 4, 7, 7, 1, 1}
538 */
539
540
541 ==========================
542 //Array Reduction Methods
543 ==========================
544
545 .===========================================================================.
546 |/* METHOD NAME */|/* DESCRIPTION */|
547 |===========================================================================|
548 | sum() | Returns the sum of all array elements |
549 | product() | Returns the product of all array elements |
550 | and() | Returns the bitwise AND (&) of all array elements |
551 | or() | Returns the bitwise OR (|) of all array elements |
552 | xor() | Returns the bitwise XOR (^) of all array elements |
553 '---------------------------------------------------------------------------'
554
555
556 //EXAMPLE:
557 ----------
558
559 module tb;
560
561 int array[4] = '{1, 2, 3, 4};
562 int res[$];
563
564 initial
565 begin
566 $display ("sum = %0d", array.sum());
567 $display ("product = %0d", array.product());
568 $display ("xor = 0x%0h", array.xor());
569 $display ("and = 0x%0h", array.and());
570 $display ("or = 0x%0h", array.or());
571 end
572 endmodule
573
574 /*OUTPUT
575 Operation || binary ||value
576 -------------------------------------------------------------
577 sum = 10 A=1 | | || 0001 | | || 1 | |
578 product = 24 B=2 | | || 0010 | | || 2 | |
579 xor = 0xC C=A^B |(A&B) |(A|B) || 0011 |0000 | 0011 || 3 | 0| 3
580 and = 0x0 D=3 | | || 0011 | | 0011 || | |
581 or = 0x7 E=C^D |(C&D) |(C|D) || 0110 |0000 | 0011 || 6 | 0| 3
582 F=4 | | || 0100 | | 0100 || 4 | |
583 -------------------------------------------------------------
584 G=E^F |(E&F) |(E|F) || 1010 |0000 | 0111 || 12| 0| 7
585 -------------------------------------------------------------
586 */
587
588
589 1. When you combine an array reduction such as sum using the with clause, the results
590 may surprise you.
591 2. sum operator totals the number of times that the expression is true
592
593 //EXAMPLE:
594 -----------
595
596 int count, total, d[] = '{9,1,8,3,4,4};
597
598 count = d.sum with (int'(item > 7)); // 2 = sum{1,0,1,0,0,0}
599 total = d.sum with ((item > 7) * item); // 17 = sum{9,0,8,0,0,0}
600 count = d.sum with (int'(item < 8)); // 4 = sum{0,1,0,1,1,1}
601 total = d.sum with (item < 8 ? item : 0); // 12 = sum{0,1,0,3,4,4}
602 count = d.sum with (int'(item == 4)); // 2 = sum{0,0,0,0,1,1}
603
604
605 / count = d.sum with (int'(item > 7)); VS count = d.sum with (item > 7);
606
607 If you want a count of then number of elements greater than 7.
608 Then you need to write
609
610 count = d.sum with (int'(item > 7)); // 2 = sum{1,0,1,0,0,0}
611
612 That's because the type of item>5 is a 1-bit expression,
613 and sum of 1-bit expressions is a 1-bit result.
614
615
616 count = d.sum with (item > 7); // 0 = sum{1,0,1,0,0,0}
617
618 */
619
620
621 endclass
622
623
624 ------------------------------------------------------===========-------------------------------------------------
625 //=====================================================DATA TYPE==================================================
626 ------------------------------------------------------===========-------------------------------------------------
627 class
628
629 ===============
630 //WIRE AND REG
631 ===============
632
633 1. Structural data types called nets, which model hardware connections between circuit components.
634 2. The wire nets act like real wires in circuits.
635 3. The reg type holds their values until another value is put on them, just like a register hardware component.
636 4. The declarations for wire and reg signals are inside a module but outside any initial or always block.
637
638 //Default Value
639 reg is x unknown
640 wire is z.
641
642
643 ==========================
644 //TWO-STATE INTEGER TYPES
645 ==========================
646 .==============================================================.
647 | TYPE | Description | Example |
648 '=============================================================='
649 | bit | user-defined size | bit [3:0] a_nibble; |
650 | byte | 8 bits, signed | byte a, b; |
651 | shortint | 16 bits, signed | shortint c, d; |
652 | int | 32 bits, signed | int i,j; |
653 | longint | 64 bits, signed | longint lword; |
654 '--------------------------------------------------------------'
655
656 ==========================
657 //FOUR-STATE INTEGER TYPES
658 ==========================
659
660 .==============================================================.
661 | TYPE | Description | Example |
662 '=============================================================='
663 | reg | user-defined size | reg [7:0] a_byte; |
664 | logic | identical to reg | logic [7:0] a_byte; |
665 | | in every way | |
666 | integer | 32 bits, signed | integer i, j, k; |
667 '--------------------------------------------------------------'
668
669 logic is a better name than reg, so is preferred.
670 As we shall see, you can use logic where in the past,
671 you have may have used reg or where you may have used wire
672
673 ====================
674 //NON-INTEGER TYPES
675 ====================
676
677 .=============================================================. o
678 | TYPE | Description | Example |
679 '============================================================='
680 | time | 64-bit unsigned | time now; |
681 | shortreal | 32-bit like float in C | shortreal f; |
682 | real | 64-bit like double in C | real g; |
683 | realtime | identical to real | realtime now; |
684 '-------------------------------------------------------------'
685
686 ===========================
687 //PACKED & UNPACKED ARRAY
688 ===========================
689
690 Packed || Unpacked
691 ------------- || ----------------
692 ||
693 1. The term packed is used to refer to the || 1. The term packed is used to refer to the
694 dimensions declared before the data || dimensions declared after the data
695 identifier name || identifier name
696 ||
697 eg. bit [7:0] var; || eg. bit var [7:0];
698 .---.---.---.---.---.---.---.---. || var[0], var[1], var[2], var[3],
699 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | var || var[4], var[5], var[6], var[7]
700 '---'---'---'---'---'---'---'---' || //there is 8 var each 1 bit
701 ||
702 2. It can be of data type || 2. It can be of any data type mentioned in
703 1. bit || SV LRM.
704 2. logic ||
705 3. reg ||
706 4. enum ||
707 5. struct ||
708 ||
709 ||
710 /*EXAMPLE */ ||
711 ||
712 eg. I have a variable of 12 bit wide ||
713 ||
714 Q. I want 12 bits as 3 group of 4 bits || Q. I want 4 variables of 12 bit wide
715 bit[2:0][3:0] var || bit[11:0] var[3:0]
716 ||
717 ||
718 |12|11|10|9|8|7|6|5|4|3|2|1|0| var || |12|11|10|9|8|7|6|5|4|3|2|1|0| var[0]
719 ||
720 || |12|11|10|9|8|7|6|5|4|3|2|1|0| var[1]
721 var[2] var[1] var[0] ||
722 |3|2|1|0| |3|2|1|0| |3|2|1|0| || |12|11|10|9|8|7|6|5|4|3|2|1|0| var[2]
723 ||
724 || |12|11|10|9|8|7|6|5|4|3|2|1|0| var[3]
725 ||
726 3. For some data types, you may want both to ||
727 access the entire value and also to divide it ||
728 into smaller elements. For example, you may have||
729 a 32-bit register that sometimes you want to ||
730 treat as four 8-bit values and at other times ||
731 as a single, unsigned value ||
732
733
734 ============================
735 //SystemVerilog Enumeration
736 ============================
737
738 /*1. An enumerated type defines a set of named values.
739
740 2. In the following example,
741 light_* is an enumerated variable that can store one of the three possible values (0,1, 2).
742 By default, the first name in the enumerated list gets the value 0 and the following names
743 get incremental values like 1 and 2
744 */
745
746 enum {RED, YELLOW, GREEN} light_1; // int type; RED = 0,YELLOW=1,GREEN=2
747
748 enum bit[1:0] {RED, YELLOW, GREEN} light_2; // bit type; RED = 0, YELLOW=1,GREEN=2
749
750 /*3. The user can assign any integer value for any of the enumerated names.
751 4. If any name does not have an assigned value, then it automatically takes
752 the incremented value of the previous name.
753 */
754
755 enum {RED=3, YELLOW, GREEN} light_3; // RED = 3, YELLOW = 4, GREEN=5
756 enum {RED = 4, YELLOW = 9, GREEN} light_4; // RED = 4, YELLOW = 9, GREEN=10
757
758 enum {RED = 2, YELLOW, GREEN = 3} light_5; //Error : YELLOW and GREEN are both assigned 3
759
760
761
762 ---------------------
763 *******WARNING*******
764 ---------------------
765
766 //Note that an enumeration name cannot start with a number !
767
768 enum {1WAY, 2TIMES, SIXPACK=6} e_formula; // Compilation error on 1WAY ,2TIMES
769 enum {ONEWAY, TIMES2, SIXPACK=6} e_formula; // Correct way -> change 1 to ONE,2 to TWO, etc
770 enum {ONEWAY, TWOTIMES, SIXPACK=6} e_formula;
771
772
773
774 ================
775 //TYPEDEF ENUM
776 ================
777
778 A custom data-type can be created so that the same data-type may be used to
779 declare other variables
780
781 module tb;
782
783 typedef enum {TRUE, FALSE} e_true_false;
784
785 // "e_true_false" is a new data-type with two valid values: TRUE and FALSE
786
787 initial
788 begin
789
790 // Declare a variable of type "e_true_false" that can store TRUE or FALSE
791 e_true_false answer;
792
793 // Assign TRUE/FALSE to the enumerated variable
794 answer = TRUE;
795
796 // Display string value of the variable
797 $display ("answer = %s", answer.name);
798 end
799 endmodule
800
801 /*OUTPUT
802 answer = TRUE
803 */
804
805 typedef enum {RED, YELLOW, GREEN} e_light;
806
807 initial
808 begin
809
810 e_light light;
811
812 light = RED; // Initialize light to RED
813
814
815 if (light == RED)
816 $display ("Light = %s", light.name());
817 end
818
819
820
821
822
823
824
825 ============
826 //STRUCTURE
827 ============
828
829 1. A structure can contain elements of different data types which can be referenced
830 as a whole or individually by their names.
831 2. This is quite different from arrays where the elements are of the same data-type
832
833 // Normal arrays -> a collection of variables of same data type
834 int array [10]; // all elements are of int type
835 bit [7:0] mem [256]; // all elements are of bit type
836
837 // Structures -> a collection of variables of different data types
838 struct {
839 byte val1;
840 int val2;
841 string val3;
842 } struct_name;
843
844 //Syntax:
845 ---------
846
847 struct {
848 [list of variables];
849 } struct_name;
850
851
852
853 //Structure Example:
854 ---------------------
855
856 module tb;
857 // Create a structure called "st_fruit"
858 // which to store the fruit's name, count and expiry date in days.
859 // Note: this structure declaration can also be placed outside the module
860
861 struct {
862 string fruit;
863 int count;
864 byte expiry;
865 } st_fruit;
866
867 initial
868 begin
869
870 st_fruit = '{"apple", 4, 15}; //let's initialize it
871
872 $display ("st_fruit = %p", st_fruit); // Display the structure variable
873
874 // Change fruit to pineapple, and expiry to 7
875
876 st_fruit.fruit = "pineapple";
877 st_fruit.expiry = 7;
878
879 $display ("st_fruit = %p", st_fruit);
880 end
881 endmodule
882 /*OUTPUT
883
884 st_fruit = '{fruit:"apple", count:4, expiry:'hf}
885 st_fruit = '{fruit:"pineapple", count:4, expiry:'h7}
886 */
887
888 //What is the need to typedef a structure ???
889 -----------------------------------------------
890 1. Only one variable was created in the example above, but if there's a need to create
891 multiple structure variables with the same constituents,
892 2. it'll be better to create a user defined data type of the structure by typedef.
893 3. Then st_fruit will become a data-type which can then be used to create variables of that type
894
895 module tb;
896 // Create a structure called "st_fruit"
897 // which to store the fruit's name, count and expiry date in days.
898
899 typedef struct {
900 string fruit;
901 int count;
902 byte expiry;
903 } st_fruit;
904 initial
905 begin
906 // st_fruit is a data type, so we need to declare a variable of this data type
907
908 st_fruit fruit1 = '{"apple", 4, 15};
909 st_fruit fruit2;
910
911 $display ("fruit1 = %p fruit2 = %p", fruit1, fruit2);
912
913 fruit2 = fruit1; //contents of fruit1 variable is copied into fruit2
914 $display ("fruit1 = %p fruit2 = %p", fruit1, fruit2);
915
916 fruit1.fruit = "orange"; // Change fruit1 to see if fruit2 is affected
917 $display ("fruit1 = %p fruit2 = %p", fruit1, fruit2);
918 end
919 endmodule
920
921 /*OUTPUT
922
923 fruit1 ='{fruit:"apple",count:4,expiry:'hf} fruit2 ='{fruit:"",count:0,expiry:’h0}
924
925 fruit1 ='{fruit:"apple",count:4,expiry:'hf} fruit2 ='{fruit:"apple",count:4,expiry:’hf}
926
927 fruit1 ='{fruit:"orange",count:4,expiry:'hf} fruit2 ='{fruit:"apple",count:4,expiry:’hf}
928
929 */
930
931 class //DETAIL VIEW OF Structure
932
933 WHAT IS A SYSTEMVERILOG STRUCT (URE)?
934 =====================================
935 /*
936 A SystemVerilog struct is a way to group several data types
937 The entire group can be referenced as a whole, or the individual data type can be referenced by name
938 It is handy in RTL coding when you have a collection of signals you need to pass around the design together, but
939 want to retain the readability and accessibility of each separate signal
940
941 When used in RTL code,
942
943 1. a packed SystemVerilog struct is the most useful
944 2. A packed struct is treated as a single vector, and each data type in the structure is represented as a bit field
945 3. The entire structure is then packed together in memory without gaps
946 4. Only packed data types and integer data types are allowed in a packed struct
947 5. Because it is defined as a vector, the entire structure can also be used as a whole with arithmetic and logical
948 operators
949
950 AN UNPACKED SYSTEMVERILOG STRUCT
951
952 1. on the other hand, does not define a packing of the data types
953 2. It is tool-dependent how the structure is packed in memory
954 3. Unpacked struct probably will not synthesize by your synthesis tool, so I would avoid it in RTL code
955 4. It is, however, the default mode of a structure if the packed keyword is not used when defining the structure
956 */
957 SystemVerilog struct is often defined with the typedef keyword to give the structure type a name so it can be
958 more easily reused across multiple files. Here is an example:
959
960 typedef enum logic[15:0]
961 {
962 ADD = 16'h0000,
963 SUB = 16'h0001
964 } my_opcode_t;
965
966 typedef enum logic[15:0]
967 {
968 REG = 16'h0000,
969 MEM = 16'h0001
970 } my_dest_t;
971
972 typedef struct packed
973 {
974 my_opcode_t opcode; // 16-bit opcode, enumerated type
975 my_dest_t dest; // 16-bit destination, enumerated type
976 logic [15:0] opA;
977 logic [15:0] opB;
978 } my_opcode_struct_t;
979
980 my_opcode_struct_t cmd1;
981
982 initial
983 begin
984 // Access fields by name
985 cmd1.opcode <= ADD;
986 cmd1.dest <= REG;
987 cmd1.opA <= 16'h0001;
988 cmd1.opB <= 16'h0002;
989
990 // Access fields by bit position coz packed in a single 64 bit vector
991 cmd1[63:48] <= 16'h0000
992 cmd1[47:32] <= 16'h0000;
993 cmd1[31:16] <= 16'h0003;
994 cmd1[15: 0] <= 16'h0004;
995
996 // Assign fields at once
997 cmd1 <= '{SUB, REG, 16'h0005, 16'h0006};
998 end
999
1000 endclass
1001
1002
1003 ==============================
1004 //STRUCTURE IN SYSTEMVERILOG
1005 ==============================
1006
1007 1. A structure can contain different members of different data types
1008 2. An array contains elements of the same data type
1009 3. This makes structures different from an array.
1010
1011 SYNTAX:
1012 --------
1013 struct {
1014 <Data type> <member 1>;
1015 <Data type> <member 2>;
1016 ...;
1017 } <struct_name>;
1018
1019 //SIGNIFICANCE OF TYPEDEF IN STRUCTURES
1020 -----------------------------------------
1021
1022 Structure example without typedef
1023 Let’s see an example where the typedef keyword is not used
1024
1025 module struct_example;
1026 struct {
1027 string name;
1028 bit[31:0] salary;
1029 integer id;
1030 } employee;
1031
1032 initial begin
1033 employee.name = "Alex";
1034 employee.salary = 'h10000;
1035 employee.id = 'd1234;
1036 $display("employee: %p", employee);
1037
1038 // Accessing individual struct member
1039 $display("employee: name = %s, salary = 0x%0h, id = %0d", employee.name, employee.salary,
1040 employee.id);
1041 end
1042 endmodule
1043 /*OUTPUT:
1044
1045 employee: '{name:"Alex", salary:'h10000, id:1234}
1046 employee: name = Alex, salary = 0x10000, id = 1234
1047
1048 */
1049
1050 In the above example,
1051 1. The “employee” struct name is used to store information
1052 2. Employee behaves reference handle to complete information (includes name, salary, and id of an employee)
1053 3. Individual information also can be accessed
1054 4. Now, if we want to store another set of information for an employee
1055 5. The typedef keyword allows creating multiple sets of information with different reference handles
1056
1057 //SYNTAX USING TYPEDEF:
1058 ------------------------
1059
1060 typedef struct {
1061 <Data type> <member 1>;
1062 <Data type> <member 2>;
1063 ...;
1064 } <struct_name>;
1065
1066 STRUCTURE EXAMPLE WITH TYPEDEF:
1067 -------------------------------
1068
1069 module struct_example;
1070 typedef struct {
1071 string name;
1072 bit[31:0] salary;
1073 integer id;
1074 } employee;
1075
1076 initial begin
1077 employee e1, e2;
1078 e1.name = "Alex";
1079 e1.salary = 'h10000;
1080 e1.id = 'd1234;
1081 $display("employee e1: %p", e1);
1082
1083 e2.name = "Bob";
1084 e2.salary = 'h20000;
1085 e2.id = 'd4321;
1086 $display("employee e2: %p", e2);
1087 $display("-------------------------------------------------");
1088
1089 // Accessing individual struct member
1090 $display("employee e1: name = %s, salary = 0x%0h, id = %0d", e1.name, e1.salary, e1.id);
1091 $display("employee e2: name = %s, salary = 0x%0h, id = %0d", e2.name, e2.salary, e2.id);
1092 end
1093 endmodule
1094
1095 /*Output:
1096
1097 employee e1: '{name:"Alex", salary:'h10000, id:1234}
1098 employee e2: '{name:"Bob", salary:'h20000, id:4321}
1099 -------------------------------------------------
1100 employee e1: name = Alex, salary = 0x10000, id = 1234
1101 employee e2: name = Bob, salary = 0x20000, id = 4321
1102
1103 */
1104 =======================
1105 //TYPES OF STRUCTURES
1106 =======================
1107
1108 1. Packed structures
1109 2. Unpacked structures
1110
1111 PACKED STRUCTURES:
1112 ==================
1113
1114 1. Similar to a packed array, if memory allocated for variables in a structure is contiguous, then it is called a
1115 packed structure.
1116 2. Only packed data types are allowed in packed structures.
1117 3. Ex. A string is not a packed data type, so code will not compile. To use string as a data type in structure,
1118 unpack structures can be used
1119 4. The “packed” keyword is used to declare a packed structure
1120
1121 PACKED STRUCTURE EXAMPLE:
1122 --------------------------
1123
1124 module struct_example;
1125 typedef struct packed {
1126 63 62 61 _ _ _ _ _ _ _ _ _ _ _ _ _ _ 3 2 1 0
1127 bit[31:0] salary; .-----------------------------------------------. o
1128 integer id; | | | | | | | | | | | | |
1129 } employee; '-----------------------------------------------'
1130
1131 initial begin
1132 employee emp1, emp2;
1133 emp1.salary = 'h10000;
1134 emp1.id = 'd1234;
1135 $display("EMP 1: %p", emp1);
1136
1137 emp2.salary = 'h12000;
1138 emp2.id = 'd4321;
1139 $display("EMP 2: %p", emp2);
1140 end
1141 endmodule
1142 /*Output:
1143
1144 EMP 1: '{salary:'h10000, id:1234}
1145 EMP 2: '{salary:'h12000, id:4321}
1146 */
1147 UNPACKED STRUCTURES:
1148 ---------------------
1149
1150 An unpacked structure is not as memory efficient as packed data structures.
1151
1152 By default, a structure is unpacked in nature
1153
1154 module struct_example;
1155 typedef struct {
1156 string name;
1157 bit[31:0] salary;
1158 integer id;
1159 } employee;
1160
1161 initial begin
1162 employee emp1, emp2;
1163 emp1.name = "Alex";
1164 emp1.salary = 'h10000;
1165 emp1.id = 'd1234;
1166 $display("EMP 1: %p", emp1);
1167
1168 emp2.name = "John";
1169 emp2.salary = 'h12000;
1170 emp2.id = 'd4321;
1171 $display("EMP 2: %p", emp2);
1172 end
1173 endmodule
1174 /*Output:
1175
1176 EMP 1: '{name:"Alex", salary:'h10000, id:1234}
1177 EMP 2: '{name:"John", salary:'h12000, id:4321}
1178
1179 */
1180
1181 //PASSING A STRUCTURE IN FUNCTION OR TASK
1182 ==========================================
1183
1184 In the below example,
1185 1. Two functions are used for allocating information to structure members and another .function to
1186 print the structure
1187 2. Similarly, a structure can be used as an input argument for tasks.
1188
1189
1190 Example:
1191
1192 module struct_example;
1193
1194 typedef struct {
1195 string name;
1196 bit[31:0] salary;
1197 integer id;
1198 } employee;
1199
1200 function void print_struct(employee emp);
1201 $display("EMP: %p", emp);
1202 endfunction
1203
1204 function employee create_struct(string name, bit [31:0] salary, integer id);
1205 employee emp;
1206 emp.name = name;
1207 emp.salary = salary;
1208 emp.id = id;
1209 return emp;
1210 endfunction
1211
1212 initial begin
1213 employee emp1, emp2;
1214 emp1 = create_struct("Alex",'h10000, 'd1234);
1215 emp2 = create_struct("John",'h12000, 'd4321);
1216 print_struct(emp1);
1217 print_struct(emp2);
1218 end
1219 endmodule
1220 /*Output:
1221
1222 EMP: '{name:"Alex", salary:'h10000, id:1234}
1223 EMP: '{name:"John", salary:'h12000, id:4321}
1224
1225 */
1226
1227 //KEY POINTS
1228 =============
1229
1230 1. In a packed structure, if any data type is 4-state, then the complete structure is treated as a 4-state
1231 structure
1232
1233 2.The packed structure is by default unsigned in nature. To declare a packed signed structure, the below
1234 syntax is used.
1235
1236 Syntax for packed signed structure
1237
1238 typedef struct packed signed {
1239 <Data type> <member 1>;
1240 <Data type> <member 2>;
1241 ...;
1242 } <struct_name>;
1243
1244 ==========================
1245 //UNIONS IN SYSTEMVERILOG
1246 ==========================
1247
1248 1. Unions are similar to structures that can contain different data types members
1249 2. except they share the same memory location
1250 3. Hence, it is memory efficient data structure. But it also restricts the user to use one member at a time
1251 4. The memory allocated for the union would be the maximum of the memory needed for the member data types
1252
1253 Syntax:
1254 -------
1255
1256 union {
1257 <Data type> <member 1>;
1258 <Data type> <member 2>;
1259 ...;
1260 } <union_name>;
1261
1262 UNION EXAMPLE
1263 -------------
1264
1265 module union_example; 31 30 29 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 3 2 1 0
1266 typedef union { .-----------------------------------------------. O
1267 bit[15:0] salary; | | | | | | | | | | | | |
1268 integer id; '-----------------------------------------------'
1269 } employee;
1270
1271 initial begin
1272 employee emp;
1273 emp.salary = 'h800;
1274 $display("salary updated for EMP: %p", emp);
1275 emp.id = 'd1234;
1276 $display("ID updated for EMP: %p", emp); //Note: Salary information will be lost
1277 end
1278 endmodule
1279
1280 /*Output:
1281
1282 salary updated for EMP: '{salary:'h800, id:Z}
1283 ID updated for EMP: '{salary:'h0, id:1234}
1284
1285 */
1286
1287
1288 //STRUCTURE VS UNION
1289 =====================
1290
1291 1. The one major difference that distinguishes structure and union is that the structure has a separate memory
1292 location for each of its members whereas, the members of a union share the same memory location.
1293
1294 2. The size of a structure is equal or greater to the sum of the sizes of each data member
1295 3. When the variable is declared in the union, the compiler allocates memory to the largest size variable member
1296 The size of a union is equal to the size of its largest data member size
1297
1298 4. A union is a block of memory that stores several data objects, but has only storage for the largest of these,
1299 and thus can only store one of the data objects at any one time
1300
1301
1302
1303 endclass
1304
1305
1306 -----------------------------------------------------===========--------------------------------------------------
1307 //====================================================INTERFACE===================================================
1308 -----------------------------------------------------===========--------------------------------------------------
1309 class
1310
1311 /*What is an Interface ?????
1312 =============================
1313 1. Verilog connects between different modules through its module ports. For large designs, this method of
1314 connection can become more time consuming and repetitious SO SV introduces Interfaces.
1315 2. A SystemVerilog interface allows us to group a number of signals together and represent them as a
1316 single port.
1317 3. Interface blocks are defined and described within interface and endinterface keywords. It can be
1318 instantiated like a module.
1319 4. All these signals can be declared and maintained at a single place and be easily maintained.
1320 5. Signals within an interface are accessed by the interface instance handle.
1321 */
1322
1323 //EXAMPLE
1324 ==========
1325
1326 APB bus protocol signals are put together in the given .interface. Note that signals
1327 are declared .within interface .and endinterface
1328
1329 // NON-Parameterized Parameterized
1330 ----------------- -------------
1331 interface apb_if (input pclk); interface apb_if #(parameter WIDTH = 32)(input pclk);
1332 logic [31:0] paddr; logic [WIDTH-1:0] paddr;
1333 logic [31:0] pwdata; logic [WIDTH-1:0] pwdata;
1334 logic [31:0] prdata; logic [WIDTH-1:0] prdata;
1335 logic penable; logic penable;
1336 logic pwrite; logic pwrite;
1337 logic psel; logic psel;
1338 endinterface endinterface
1339
1340
1341 //How to define port directions ????
1342 =====================================
1343 /* MODPORT
1344 ===========
1345 1. modport is used to define signal directions.
1346 2. Different modport definitions can be passed to different components that allows us to define different
1347 input-output directions for each component.
1348
1349 */
1350
1351 //EXAMPLE
1352 ==========
1353
1354 interface myBus (input clk);
1355
1356 logic [7:0] data;
1357 logic enable;
1358
1359 // From TestBench perspective, 'data' is input and 'enable' is output
1360 modport TB (input data, clk, output enable);
1361
1362 // From DUT perspective, 'data' is output and 'enable' is input
1363 modport DUT (output data, input enable, clk);
1364
1365 endinterface
1366
1367
1368 //How to connect an interface with DUT ?
1369 ==========================================
1370
1371 /*
1372 An interface object should be created in the top testbench module where DUT is
1373 instantiated, and passed to DUT. It is essential to ensure that the correct modport is
1374 assigned to DUT.
1375 */
1376 /*
1377 SystemVerilog allows a module to accept an interface as the portlist instead of individual signals.
1378 */
1379 /* WITHOUT USING INTERFACE */ || /* USING INTERFACE HANDLE */
1380 ------------------------- || ------------------------
1381 module dut (output data,input enable,clk); || module dut (myBus busIf);
1382 always @ (posedge clk) || always @ (posedge busIf.clk)
1383 if (enable) || if (busIf.enable)
1384 data <= data+1; || busIf.data <= busIf.data+1;
1385 else || else
1386 data <= 0; || busIf.data <= 0;
1387 endmodule || endmodule
1388 ||
1389
1390 // Filename : tb_top.sv
1391 ========================
1392
1393 module tb_top;
1394 bit clk;
1395 always #10 clk = ~clk; // Create a clock
1396
1397 myBus busIf (clk); // Create an interface object
1398
1399 dut dut0 (busIf.DUT); // Instantiate the DUT; pass modport DUT of busIf
1400
1401 initial
1402 begin
1403 busIf.enable <= 0;
1404 #10 busIf.enable <= 1;
1405 #40 busIf.enable <= 0;
1406 #20 busIf.enable <= 1;
1407 #100 $finish;
1408 end
1409 endmodule
1410
1411 //WHAT ARE CLOCKING BLOCKS ????
1412 ================================
1413 /*
1414 1. Signals that are specified inside a clocking block will be sampled/driven with respect to that clock.
1415 2. There can be mulitple clocking blocks in an interface. Note that this is for testbench related signals.
1416 3. We want to control when the TB drives and samples signals from DUT.
1417 4. Solves some part of the race condition, but not entirely.
1418 5. We can also parameterize the skew values
1419 */
1420
1421 interface my_int (input bit clk);
1422 logic [7:0] data;
1423 logic enable;
1424
1425 //Clocking Block
1426
1427 clocking dut_clk @(posedge clk);
1428 default input #3ns output #2ns;
1429 input enable;
1430 output data;
1431 endclocking
1432
1433 // From DUT perspective, 'data' is output and 'enable' is input
1434 modport DUT (output data, input enable, clk);
1435
1436 clocking tb_clk @(negedge clk);
1437 default input #3ns output #2ns;
1438 output enable;
1439 input data;
1440 endclocking
1441
1442 // From TestBench perspective, 'data' is input and 'enable' is output
1443 modport TB (input data, clk, output enable);
1444
1445
1446
1447 endinterface
1448
1449 /*In the above example, we have specified that by default, input should be sampled
1450 3ns before posedge of clk, and output should be driven 2ns after posedge of clk*/
1451
1452 //Clocking Blocks
1453 ------------------
1454 /*
1455 1. Module ports and interfaces by default do not specify any timing requirements or synchronization schemes
1456 between signals.
1457
1458 A clocking block defined between clocking and endcocking does exactly that. It is a collection of signals
1459 synchronous with a particular clock and helps to specify the timing requirements between the clock and the signals.
1460
1461 2. Clocking blocks allow inputs to be sampled and outputs to be driven at a specified
1462 clock event.
1463
1464 3. input skew ==> input signals will be sampled at skew time units before the clock event
1465
1466 4. output skew ==> output signals will be driven skew time units after the corresponding clock event.
1467
1468 3. If a default skew is not specified, then all input signals will be sampled #1step and output signlas driven 0ns
1469 after the specified event.
1470
1471 */
1472
1473
1474 //WHAT ARE INPUT AND OUTPUT SKEWS ???
1475 ======================================
1476
1477 clocking cb @(clk);
1478 input #1ps req;
1479 output #2 gnt;
1480 input #1 output #3 sig;
1481 endclocking
1482
1483 /*
1484 1. Signal req is specified to have a skew of 1ps and will be sampled 1 ps before the clock edge clk.
1485 2. The output signal gnt has an output skew of 2 time units hence will be driven 2 time units after
1486 the clock edge.
1487 3. The last signal sig is of inout type and will be sampled 1 ns before the clock edge and driven 3 ns
1488 after the clock edge.
1489 */
1490
1491
1492 clocking cb @(posedge clk);
1493 input #1step req;
1494 endclocking
1495
1496
1497
1498 1. An input skew of 1step indicates that the signal should be sampled at the .end of the previous
1499 time step, or in other words, immediately before the positive clock edge
1500
1501
1502
1503
1504 /*A race condition occurs when two or more threads are using the same resources.
1505 There are many examples of race conditions. A few are listed below.
1506
1507 1. The same signal is driven and sampled at the same time.
1508 => To avoid this race condition, a clocking block in interface is used as it provides an input and output skews to
1509 sample and drive, respectively.
1510
1511 2. Race condition between testbench and design.
1512 => The program block is used to avoid this race, as module executes on an active region, while program block
1513 executes in reactive region.
1514
1515 3. Race condition in event.
1516 => This race condition occurs when one thread is waiting for triggering an event using @(event) syntax and at the
1517 same time event is triggered from another thread. This race condition could be avoided by using wait statement and
1518 triggered method like wait(event.triggered);
1519
1520
1521 EXPLANATION:
1522 =============
1523
1524 1. A race condition in SystemVerilog is an simulation modeling artifact where the order of execution between two
1525 different constructs cannot be guaranteed. The most common race condition is when there are multiple processes
1526 reading and writing the same variable synchronized to the same event region (like the edge of a clock).
1527 SystemVerilog does not guarantee the order of execution between the reading and writing, so there is no way to know
1528 if the "read" captures the old or the new value of that variable. (bdreku, this can happen just as easily within a
1529 program block or module)
1530
1531 The solution to this problem is to move either the reading or writing of that variable to a different event region.
1532 The most common way to do this is to use a non-blocking assignment (q <= d)for the writing of that variable. That
1533 postpones actual update of that variable to a later region. Now all the other process that try to read that variable
1534 in the current event region are guaranteed to the "old" value of that variable regardless of the writing process
1535 executes before or after the reading process. This technique is the way Verilog RTL designers have been coding for
1536 years, and works equally as well for testbench verification.
1537
1538 Testbench writers have a few other options, including using a different event for writing and reading (like the
1539 inverse edge of the clock), and clocking blocks to offset the reading and writing from a synchronous clock edge.
1540
1541 Real hardware does not have the same kind of problem with race conditions. Propagation delays through registers
1542 usually prevent simultaneous reading and writing, but physical issues like clock skew and setup/hold requirements
1543 can produce timing problems where it is difficult to predict reading the old or new value of a signal.
1544
1545 */
1546 endclass
1547
1548
1549 ------------------------------------------------====================----------------------------------------------
1550 //===============================================CLASSES(BASIC OOP)===============================================
1551 ------------------------------------------------====================----------------------------------------------
1552 class
1553
1554 //What are classes ?
1555 ----------------------
1556 /*class is a user-defined datatype, an OOP construct, that can be used to encapsulate
1557 data (property) and tasks/functions (methods) which operate on the data.
1558 */
1559
1560 //EXAMPLE:
1561 -----------
1562 class myPacket;
1563 bit [2:0] header;
1564 bit encode;
1565 bit [2:0] mode;
1566 bit [7:0] data;
1567 bit stop;
1568
1569 function new (bit [2:0] header = 3'h1, bit [2:0] mode = 5);
1570 this.header = header;
1571 this.encode = 0;
1572 this.mode = mode;
1573 this.stop = 1;
1574 endfunction
1575
1576 function display ();
1577 $display ("Header = 0x%0h, Encode = %0b, Mode = 0x%0h, Stop = %0b",
1578 this.header, this.encode, this.mode, this.stop);
1579 endfunction
1580 endclass
1581
1582
1583 //What is a class handle ?
1584 --------------------------
1585 /*
1586 1. A class variable such as pkt below is only a name by which that object is known.
1587 2. It can hold the handle(POINTER) to an object of class Packet.
1588 3. Until assigned with something ,it is always null. At this point, the class object does not exist yet.
1589 */
1590 //Class Handle Example
1591 -----------------------
1592
1593 class Packet;
1594 int count;
1595 endclass
1596
1597 module tb;
1598
1599 Packet pkt; // Note: This "handle" now points to NULL
1600
1601 initial
1602 begin
1603 if (pkt == null)
1604 $display ("Packet handle 'pkt' is null");
1605
1606 $display ("count = %0d", pkt.count); // Display the class member using the "handle"
1607 // Expect a run-time error because pkt is not an object
1608 // yet, and is still pointing to NULL. So pkt is not
1609 // aware that it should hold a member
1610 end
1611 endmodule
1612
1613 /*OUTPUT
1614 Packet handle 'pkt' is null
1615 count = ncsim: *E,TRNULLID: NULL pointer dereference.
1616 */
1617
1618 //CLASS CONSTRUCTOR
1619 --------------------
1620 /*Class Object are created with the new method(function)
1621 1.Every Class has a default constructor new method
1622 Constructor new method-
1623 1.Allocates Memory
1624 2.Return the address of the memory to handle
1625 3.Initialize all the properties
1626 */
1627
1628 //EXPLICITY DEFINED:
1629 ====================
1630 class Packet;
1631 bit [31:0] addr;
1632 bit [31:0] data;
1633 function new (bit [31:0] data=15);
1634 addr = 20;
1635 endfunction
1636 endclass
1637 pkt
1638 module tb; .------------------.
1639 | addr=20 |
1640 Packet pkt; | |
1641 initial | data=15 |
1642 begin | |
1643 | |
1644 pkt = new; /*Packet pkt=new;*/ | |
1645 $display ("addr=%d,data=%d", pkt.addr,pkt.data); | |
1646 end '------------------'
1647 endmodule
1648
1649 /*OUTPUT
1650
1651 addr=20,data=15
1652
1653 */
1654
1655 //IMPLICITLY CALLED:
1656 --------------------
1657
1658 /*If the class does not have a new() function explicitly coded, an implicit new method
1659 will be automatically provided. In this case, addr & data is initialized to zero since it is of
1660 type bit for which the default value is zero.
1661 */
1662
1663 class Packet;
1664 bit [31:0] addr;
1665 bit [31:0] data;
1666 endclass
1667 pkt
1668 module tb; .------------------.
1669 | addr=0 |
1670 Packet pkt; | |
1671 initial | data=0 |
1672 begin | |
1673 | |
1674 pkt = new; /*Packet pkt=new;*/ | |
1675 $display ("addr=%d,data=%d", pkt.addr,pkt.data); | |
1676 end '------------------'
1677 endmodule
1678
1679 /*OUTPUT
1680
1681 addr=0,data=0
1682
1683 */
1684
1685
1686 //HANDLE ASSIGNMENT
1687 --------------------
1688 //If we assign pkt to a new variable called pkt2, the new variable will also point to the contents in pkt.
1689 class Packet;
1690 bit [31:0] addr;
1691 bit [31:0] data;
1692 endclass
1693 pkt
1694 module tb; .--------.
1695 | addr=0 |
1696 Packet pkt,pkt2; | data=0 |
1697 initial .-----> | | o
1698 begin | | |
1699 pkt2 '--------'
1700 pkt = new; /*Packet pkt=new;*/
1701 $display ("addr=%d,data=%d", pkt.addr,pkt.data);
1702 pkt2=pkt;
1703 pkt2.addr=10;
1704 pkt2.data=20;
1705 $display ("addr=%d,data=%d", pkt.addr,pkt2.data);
1706
1707 end
1708 endmodule
1709
1710 /*OUTPUT
1711 addr=0,data=0
1712 addr=10,data=20
1713
1714 */
1715
1716 //COPYING AN OBJECT
1717 --------------------
1718 //If we assign pkt to a new variable called pkt2, the new variable will also point to the contents in pkt.
1719 class Packet;
1720 bit [31:0] addr;
1721 bit [31:0] data;
1722 endclass
1723 pkt
1724 module tb; .---------.
1725 | addr=10 |
1726 Packet pkt,pkt2; | data=20 |
1727 initial | |
1728 begin | |
1729 '---------'
1730 pkt = new; /*Packet pkt=new;*/
1731 pkt.addr=10;
1732 pkt.data=20;
1733 $display ("addr=%d,data=%d", pkt.addr,pkt.data);
1734
1735 pkt2=new pkt;
1736 $display ("addr=%d,data=%d", pkt2.addr,pkt2.data); pkt2
1737 .---------.
1738 pkt2.addr=30; | addr=10 |
1739 pkt2.data=40; | data=20 |
1740 $display ("addr=%d,data=%d", pkt2.addr,pkt2.data); | |
1741 $display ("addr=%d,data=%d", pkt.addr,pkt.data); | |
1742 '---------'
1743 end
1744 endmodule
1745
1746 /*OUTPUT
1747 addr=10,data=20
1748 addr=10,data=20
1749 addr=30,data=40
1750 addr=10,data=20
1751 */
1752
1753
1754 //COPYING OBJECTS-SHALLOW COPY
1755 -------------------------------
1756 1.Shallow Copy - only properties of main .class are copied not the object of subclass
1757
1758
1759 class sub;
1760 int addr;
1761 endclass
1762
1763 class main;
1764 int data;
1765 sub sub_h=new;
1766 endclass
1767 .-----------. o
1768 module tb; | data=0 |
1769 | |
1770 main M1,M2; | sub_h------------.
1771 | | | o
1772 initial '-----------' |
1773 begin |
1774 .---------.
1775 M1 = new; .-----------. | |
1776 M1.data=4; | data=4 | .-------> | addr=5 |
1777 M1.sub_h.addr=5; | | ' | |
1778 M2 = new M1; | sub_h---|---------' '---------'
1779 | |
1780 end '-----------'
1781 endmodule
1782
1783 //COPYING OBJECTS-DEEP COPY
1784 -----------------------------
1785 1.Deep Copy - properties of main .class as well as of subclass will get copied
1786
1787
1788 class sub;
1789 int addr;
1790
1791 function sub copy;
1792 copy=new;
1793 copy.addr=this.addr
1794 endfunction
1795
1796 endclass
1797
1798 class main; .-----------.
1799 int data; | data=4 |
1800 sub sub_h=new; | |
1801 | sub_h------------. o
1802 function main copy; | | |
1803 copy=new; '-----------' |
1804 copy.data=this.data; |
1805 copy.sub_h=sub_h.copy; .---------. o
1806 endfunction | |
1807 | addr=5 |
1808 endclass | |
1809 .-----------. '---------' o
1810 module tb; | data=4 |
1811 | |
1812 main M1,M2; | sub_h---|-----.
1813 | | | o
1814 initial '-----------' |
1815 begin |
1816 .---------.
1817 M1 = new; | |
1818 M1.data=4; | addr=5 |
1819 M1.sub_h.addr=5; | |
1820 M2 = M1.copy; '---------'
1821 M2.sub_h.addr=10;
1822 end
1823
1824 endmodule
1825
1826
1827
1828 //SYSTEMVERILOG 'THIS' KEYWORD
1829 -------------------------------
1830 /*1.The this keyword is used to refer to class properties, parameters and methods of
1831 the current instance.
1832 2.It can only be used within non-static methods, constraints and
1833 covergroups.
1834 3.This is basically a pre-defined object handle that refers to the object
1835 that was used to invoke the method in which this is used.
1836 */
1837
1838 //EXAMPLE-
1839 ------------
1840
1841 class Packet;
1842 int addr;
1843 int data;
1844
1845 function new (int addr,int b);
1846
1847 data = b;
1848 // addr = addr; // Which addr should get assigned ?
1849 this.addr = addr; // addr variable in Packet class should be
1850 // assigned with local variable addr in new()
1851 endfunction
1852 endclass
1853
1854 /*Unless there is ambiguity in assignment, use of this keyword is not generally
1855 needed for specifying access to class members in methods.*/
1856
1857 initial
1858 begin p
1859 Packet p=new(10,20); this --> p .-----------. o
1860 end | addr |
1861 | data |
1862 | |
1863 '-----------'
1864
1865 endclass
1866
1867
1868 ------------------------------------------------===================-----------------------------------------------
1869 //===============================================CLASSES(ADV. OOP)================================================
1870 ------------------------------------------------===================-----------------------------------------------
1871 class
1872
1873 //SYSTEMVERILOG INHERITANCE
1874 =============================
1875 /*
1876 1. Inheritance is a concept in OOP that allows us to extend a class to create another
1877 class and have access to all the properties and methods of the original parent class
1878 from the handle of child class object.
1879 2. A derived class may add new properties and methods, or modify the inherited properties and methods
1880 Inheritance allows re-usability. i.e. derived class by default includes the properties and methods, which is
1881 ready to use
1882 3. If the class is derived from a derived class, then it is referred to as Multilevel inheritance
1883
1884 PARENT CLASS:
1885 ==============
1886 1. It’s an existing class;
1887 2. The class whose features are inherited
1888 3. The parent class is also known as a base class, superclass
1889
1890 CHILD CLASS:
1891 =============
1892 1. It’s an extended class;
1893 2. The class that inherits the other class is known as subclass
1894 3. The child class is also known as an extended class, derived class, subclass
1895 */
1896
1897 //Example
1898 ----------
1899
1900 class parent_class;
1901 bit [31:0] addr;
1902 endclass
1903
1904 class child_class extends parent_class;
1905 bit [31:0] data;
1906 endclass
1907
1908 module inheritence;
1909 initial
1910 begin
1911 child_class c = new();
1912 c.addr = 10;
1913 c.data = 20;
1914 $display("Value of addr = %0d data = %0d",c.addr,c.data);
1915 end
1916 endmodule
1917
1918 /*OUTPUT
1919 Value of addr = 10 data = 20
1920 */
1921
1922 //SYSTEMVERILOG POLYMORPHISM
1923 ==============================
1924 /*1.Polymorphism means many forms. Polymorphism in SystemVerilog provides an ability to an object to take on
1925 many forms.
1926
1927 2. Polymorphism allows the use of a variable of the parent class type to hold child class objects and to
1928 reference the methods of those child classes directly from the parent class variable.
1929 3. It also allows a child class method to have a different definition than its parent class if the parent class
1930 method is virtual in nature.
1931 4. It allows us to use child methods using parent handle.
1932 1. Method in parent should be virtual
1933 2. Method name should be same in both parent and child class
1934 3. p_h=c_h;
1935 */
1936 class VIRTUAL
1937
1938 //VIRTUAL METHODS
1939 ------------------
1940 A method in the parent .class can be declared as virtual which will enable all child classes to
1941 override the method with a different definition, but the prototype containing return type and
1942 arguments shall remain the same.
1943
1944 .-------------------------------.
1945 |class Base |
1946 | |
1947 | function display(); |
1948 | --- |
1949 | --- |
1950 | endfunction |
1951 | |
1952 '---------------v---------------'
1953 |
1954 |
1955 .-------------------------------.-------------------------------.
1956 | | |
1957 | | |
1958 .-----------^-----------. .-----------^-----------. .-----------^-----------.
1959 |.class child_1 | |.class child_2 | |.class child_3 |
1960 | | | | | |
1961 | function display(); | | function display(); | | function display(); |
1962 | --- | | --- | | --- |
1963 | --- | | --- | | --- |
1964 | endfunction | | endfunction | | endfunction |
1965 | | | | | |
1966 '-----------------------' '-----------------------' '-----------------------'
1967
1968 //EXAMPLE:
1969 -----------
1970
1971 // base class
1972 class base_class;
1973 virtual function void display();
1974 $display("Inside base class");
1975 endfunction
1976 endclass
1977
1978 // child class 1
1979 class child_class_1 extends base_class;
1980 function void display();
1981 $display("Inside child class 1");
1982 endfunction
1983 endclass
1984
1985 // child class 2
1986 class child_class_2 extends base_class;
1987 function void display();
1988 $display("Inside child class 2");
1989 endfunction
1990 endclass
1991
1992 // module
1993 module class_polymorphism;
1994
1995 initial
1996 begin
1997
1998 base_class b_h; //declare and create child class
1999 child_class_1 c_1 = new();
2000 child_class_2 c_2 = new();
2001
2002 //b_h=new(); //base class handle
2003
2004 // b_h = c_1; //assigning child class to base class
2005 b_h = c_2;
2006 //accessing child class methods using base class handle
2007 b_h.display();
2008
2009
2010 end
2011
2012 endmodule
2013
2014 /*OUTPUT
2015 Inside base class
2016 Inside child class 1
2017 Inside child class 2
2018
2019 */
2020
2021 //EXAMPLE_2:
2022
2023 class base_class;
2024 virtual function void display();
2025 $display("Inside base class");
2026 endfunction
2027 endclass
2028
2029 class child_class extends base_class;
2030 virtual function void display();
2031 $display("Inside child class ");
2032 endfunction
2033 endclass
2034
2035 class grand_child extends child_class;
2036 function void display();
2037 $display("Inside grand child class");
2038 endfunction
2039 endclass
2040
2041
2042 module class_polymorphism;
2043
2044 initial
2045 begin
2046
2047 base_class b_h;
2048 child_class c_h = new();
2049 grand_child g_h = new();
2050
2051 b_h = g_h;
2052 b_h.display();
2053 end
2054
2055 endmodule
2056
2057 /*OUTPUT
2058 Inside grand child class
2059
2060 */
2061
2062 //EXAMPLE_3:
2063 ------------
2064 class base_class;
2065 virtual function void display();
2066 $display("Inside base class");
2067 endfunction
2068 endclass
2069
2070 class child_class extends base_class;
2071 virtual function void display();
2072 $display("Inside child class ");
2073 endfunction
2074 endclass
2075
2076 class grand_child extends child_class;
2077 function void display();
2078 $display("Inside grand child class");
2079 endfunction
2080 endclass
2081
2082
2083 module class_polymorphism;
2084
2085 initial
2086 begin
2087
2088 base_class b_h;
2089 child_class c_h = new();
2090 grand_child g_h = new();
2091
2092 c_h = g_h;
2093
2094 b_h.display();
2095 end
2096
2097 endmodule
2098
2099 /*OUTPUT
2100 Error : Because here parent handle b_h is not pointing to any object.
2101 we can't access properties and method without creating object.
2102 */
2103
2104 class
2105 //EXAMPLE_3:
2106 ------------
2107 class base_class;
2108 virtual function void display();
2109 $display("Inside base class");
2110 endfunction
2111 endclass
2112
2113 class child_class extends base_class;
2114 virtual function void display();
2115 $display("Inside child class ");
2116 endfunction
2117 endclass
2118
2119 class grand_child extends child_class;
2120 function void display();
2121 $display("Inside grand child class");
2122 endfunction
2123 endclass
2124
2125
2126 module class_polymorphism;
2127
2128 initial
2129 begin
2130
2131 base_class b_h;
2132 child_class c_h = new();
2133 grand_child g_h = new();
2134
2135 //b_h = c_h;
2136
2137 c_h = g_h;
2138
2139 b_h = c_h
2140
2141 b_h.display();
2142 end
2143
2144 endmodule
2145
2146 /*OUTPUT
2147 b_h = c_h c_h = g_h
2148 c_h = g_h b_h = c_h
2149 b_h.display(); b_h.display();
2150
2151 Inside child class Inside grand child class
2152
2153 */
2154 endclass
2155 endclass
2156
2157 //SYSTEMVERILOG "SUPER" KEYWORD:
2158 =================================
2159 /*1. If properties and method name is same in both the classes parent and child.
2160 2. Then using child handle only child class properties and method we can access.
2161 3. Super keyword can be used only in child class
2162 4. Super keyword used to access parent class properties and methods from the child class.
2163 5. Super.new() :- become mandatory if parent class constructor required an argument
2164 */
2165 //EXAMPLE:
2166 -----------
2167
2168 class parent_class;
2169 bit [31:0] addr;
2170
2171 function display();
2172 $display("Addr = %0d",addr);
2173 endfunction
2174
2175 endclass
2176
2177 class child_class extends parent_class;
2178 bit [31:0] data;
2179
2180 function display();
2181 super.display();
2182 $display("Data = %0d",data);
2183 endfunction
2184
2185 endclass
2186
2187 module inheritence;
2188 initial
2189 begin
2190 child_class c=new();
2191 c.addr = 10;
2192 c.data = 20;
2193 c.display();
2194 end
2195 endmodule
2196
2197 /*Output
2198
2199 Addr = 10
2200 Data = 20
2201 */
2202 endclass
2203
2204
2205 -----------------------------------------------------===========--------------------------------------------------
2206 //=====================================================CASTING===================================================
2207 -----------------------------------------------------===========--------------------------------------------------
2208 class
2209 /*
2210 1. SystemVerilog casting means the conversion of one data type to another datatype.
2211 During value or variable assignment to a variable, it is required to assign value or variable of the same
2212 data type.
2213
2214 2. Some situations need assignment of different data type, in such situations,
2215 it is necessary to convert data type and assign.
2216
2217 3. Otherwise, the assignment of different data type results in a compilation error. The method of data type
2218 conversion is called casting.
2219
2220 In systemVerilog, there are two types of casting,
2221
2222 1. Static casting
2223 2. Dynamic casting
2224
2225 */
2226
2227 //STATIC CASTING
2228 =================
2229
2230 1. SystemVerilog static casting is not applicable to OOP
2231 2. Static casting converts one data type to another compatible data types (example string to int)
2232 3. As the name says ‘Static’, the conversion data type is fixed
2233 4. Static casting will be checked during compilation, so there won’t be run-time checking and error reporting
2234 5. Casting is applicable to value, variable or to an expression
2235
2236 A data type can be changed by using a cast ( ‘ ) operation
2237
2238
2239 //STATIC CASTING EXAMPLE
2240 -------------------------
2241
2242 In the below example,
2243 the real type is converted into int type.
2244 i.e multiplication of two real numbers results in real value,
2245 the result is converted into int and then assigned to a variable of int type.
2246
2247 Note: the casting is applied to expression here
2248
2249 module casting;
2250
2251 real r_a;
2252 int i_a;
2253
2254 initial
2255 begin
2256
2257 r_a = (2.1 * 3.2);
2258
2259 //real to integer conversion
2260 i_a = int'(2.1 * 3.2); //or i_a = int'(r_a);
2261
2262 $display("real value is %f",r_a);
2263 $display("int value is %d",i_a);
2264 end
2265 endmodule
2266
2267 /*Simulator Output
2268
2269 real value is 6.720000
2270 int value is 7
2271
2272 */
2273
2274 //DYNAMIC CASTING
2275 ==================
2276 1. Dynamic casting is used to, safely cast a parent_class handle into a child_class handle in a .class
2277 hierarchy
2278 2. Dynamic casting will be checked during run time, an attempt to cast an object to an incompatible object
2279 will result in a run-time error
2280
2281 3. Dynamic casting is done using the $cast(destination, source) method
2282 4. With $cast compatibility of the assignment will not be checked during compile time, it will be checked
2283 during run-time
2284
2285 Let’s see how we can use the casting,
2286
2287 1. It is always legal to assign a child_class handle to a handle of a .class higher in the inheritance
2288 tree (parent_class).
2289
2290 .-------------------------------------------.
2291 | parent_class = child_class; /*allowed*/ |
2292 '-------------------------------------------'
2293
2294 2. It is never legal to directly assign a parent_class handle to a handle of one of its
2295 child_class
2296
2297 .-----------------------------------------------.
2298 | child_class = parent_class; /*not_allowed*/ |
2299 '-----------------------------------------------'
2300
2301 3. However, it is legal to assign a parent_class handle to a child_class handle if the parent_class handle
2302 refers to an object of the given child_class
2303
2304 parent_class p_h;
2305 child_class c_h1,c_h2;
2306
2307 p_h=c_h1;
2308
2309 c_h2=p_h; //allowed because parent_class is pointing to child_class.
2310
2311 4. Though parent_class is pointing to the child_class, we will get a compilation error saying its not
2312 compatible type for the assignment.
2313
2314 This we can over come by make use of $cast method, i.e,
2315 .-----------------------------------.
2316 | $cast(c_h2,p_h); /*Allowed*/ |
2317 '-----------------------------------'
2318
2319 WHY IS IT CALLED AS DYNAMIC CASTING?
2320 ====================================
2321
2322 1. In the above parent_class assignment with child_class example.
2323 2. type of parent_class is changing dynamically i.e on declaration it is of parent_class type,
2324 on child_class assignment it is of child_class type.
2325
2326 3. Parent_class handle during $cast execution is considered for the assignment, so it referred to as dynamic
2327 casting
2328
2329
2330 //DYNAMIC CASTING EXAMPLES
2331 ===========================
2332
2333 /*1 ASSIGNING CHILD CLASS HANDLE TO PARENT CLASS HANDLE
2334 ***********************************************************
2335
2336 class parent_class;
2337 bit [31:0] addr;
2338 function display();
2339 $display("Addr = %0d",addr);
2340 endfunction
2341 endclass
2342
2343 class child_class extends parent_class;
2344 bit [31:0] data;
2345 function display();
2346 super.display();
2347 $display("Data = %0d",data);
2348 endfunction
2349 endclass
2350
2351 module inheritence;
2352 initial begin
2353 parent_class p=new();
2354 child_class c=new();
2355 c.addr = 10;
2356 c.data = 20;
2357 p = c; //assigning child class handle to parent class handle
2358 c.display();
2359 end
2360 endmodule
2361 */
2362 /*Simulator Output
2363
2364 Addr = 10
2365 Data = 20
2366
2367 */
2368
2369 /*2 ASSIGNING PARENT CLASS HANDLE TO CHILD CLASS HANDLE
2370
2371 This assignment is invalid, it leads to a compilation error.
2372
2373 class parent_class;
2374 bit [31:0] addr;
2375 function display();
2376 $display("Addr = %0d",addr);
2377 endfunction
2378 endclass
2379
2380 class child_class extends parent_class;
2381 bit [31:0] data;
2382
2383 function display();
2384 super.display();
2385 $display("Data = %0d",data);
2386 endfunction
2387 endclass
2388
2389 module inheritence;
2390 initial begin
2391 parent_class p=new();
2392 child_class c=new();
2393 c.addr = 10;
2394 c.data = 20;
2395 c = p; //assigning child class handle to parent class handle
2396 c.display();
2397 end
2398 endmodule
2399 */
2400 /*Simulator Output
2401
2402 "c = p;"
2403 Expression 'p' on rhs is not a class or a compatible class and hence cannot
2404 be assigned to a class handle on lhs.
2405 Please make sure that the lhs and rhs expressions are compatible
2406
2407 */
2408
2409 /*3 ASSIGNING PARENT CLASS HANDLE TO CHILD CLASS HANDLE
2410
2411 assigning parent class handle (which is pointing to child class handle) to child class handle, leads to compile
2412 error.
2413
2414 class parent_class;
2415 bit [31:0] addr;
2416
2417 function display();
2418 $display("Addr = %0d",addr);
2419 endfunction
2420 endclass
2421
2422 class child_class extends parent_class;
2423 bit [31:0] data;
2424 function display();
2425 super.display();
2426 $display("Data = %0d",data);
2427 endfunction
2428 endclass
2429
2430 module inheritence;
2431 initial begin
2432 parent_class p;
2433 child_class c=new();
2434 child_class c1;
2435 c.addr = 10;
2436 c.data = 20;
2437 p = c; //p is pointing to child class handle c.
2438 c1 = p; //type check fails during compile time.
2439 c1.display();
2440 end
2441 endmodule
2442 */
2443 /*Simulator Output
2444
2445 "c1 = p;"
2446 Expression 'p' on rhs is not a class or a compatible class and hence cannot
2447 be assigned to a class handle on lhs.
2448 Please make sure that the lhs and rhs expressions are compatible.
2449
2450 */
2451
2452 /*4 USE OF $CAST OR CASTING
2453
2454 In the above example, assigning parent class handle (which is pointing to child class handle) to child class handle
2455 is valid but compilation error is observed.
2456 During the compile time, as the handle of p is of parent class type which leads to compile error.
2457
2458 With the use of $cast(), type check during compile time can be skipped
2459
2460 class parent_class;
2461 bit [31:0] addr;
2462
2463 function display();
2464 $display("Addr = %0d",addr);
2465 endfunction
2466 endclass
2467
2468 class child_class extends parent_class;
2469 bit [31:0] data;
2470
2471 function display();
2472 super.display();
2473 $display("Data = %0d",data);
2474 endfunction
2475 endclass
2476
2477 module inheritence;
2478 initial begin
2479 parent_class p;
2480 child_class c=new();
2481 child_class c1;
2482 c.addr = 10;
2483 c.data = 20;
2484
2485 p = c; //p is pointing to child class handle c.
2486 $cast(c1,p); //with the use of $cast, type chek will occur during runtime
2487
2488 c1.display();
2489 end
2490 endmodule
2491 */
2492 /*Simulator Output
2493
2494 Addr = 10
2495 Data = 20
2496 */
2497
2498 endclass
2499
2500
2501 -----------------------------------------------==============================-------------------------------------
2502 //==============================================SEMAPHORE , EVENTS & MAILBOX =====================================
2503 -----------------------------------------------==============================-------------------------------------
2504 class
2505
2506 class //SEMAPHORE
2507
2508 Semaphore is a SystemVerilog built-in_class,
2509 used for access control to shared resources,
2510 and for basic synchronization.
2511
2512 A semaphore is like a bucket with the number of keys. processes using semaphores must first procure a key from the
2513 bucket before they can continue to execute, All other processes must wait until a sufficient number of keys are
2514 returned to the bucket.
2515
2516 Imagine a situation where two processes try to access a shared memory area.
2517
2518 where one process tries to write and
2519 the other process is trying to read the same memory location.
2520 this leads to an unexpected result.
2521 A semaphore can be used to overcome this situation.
2522
2523 //SEMAPHORE SYNTAX
2524 ====================
2525
2526 semaphore semaphore_name;
2527
2528 //SEMAPHORE METHODS
2529 ======================
2530
2531 Semaphore is a built-in_class that provides the following methods,
2532
2533 1. new(); Create a semaphore with a specified number of keys
2534 2. get(); Obtain one or more keys from the bucket
2535 3. put(); Return one or more keys into the bucket
2536 4. try_get(); Try to obtain one or more keys without blocking
2537
2538
2539 semaphore_name = new(numbers_of_keys);
2540
2541 the new method will create the semaphore with number_of_keys keys in a bucket; where number_of_keys is integer
2542 variable.
2543 the default number of keys is ‘0’
2544 the new() method will return the semaphore handle or null if the semaphore cannot be created
2545
2546 //put();
2547 ========
2548 The semaphore put() method is used to return key/keys to a semaphore.
2549
2550 .-----------------------------------------------------------------.
2551 | semaphore_name.put(number_of_keys); or semaphore_name.put(); |
2552 '-----------------------------------------------------------------'
2553
2554 When the semaphore_name.put() method is called,
2555
2556 1. the specified number of keys are returned to the semaphore.
2557 2. The default number of keys returned is 1.
2558
2559 //get();
2560 =========
2561 The semaphore get() method is used to get key/keys from a semaphore.
2562
2563 .-----------------------------------------------------------------.
2564 | semaphore_name.get(number_of_keys); or semaphore_name.get(); |
2565 '-----------------------------------------------------------------'
2566
2567 When the semaphore_name.get() method is called,
2568
2569 1. If the specified number of keys are available, then the method returns and execution continues
2570 2. If the specified number of keys are not available, then the process blocks until the keys become available
2571 3. The default number of keys requested is 1
2572
2573 //try_get();
2574 =============
2575 The semaphore try_get() method is used to procure a specified number of keys from a semaphore, but without blocking.
2576
2577 .-------------------------------------------------------------------------.
2578 | semaphore_name.try_get(number_of_keys); or semaphore_name.try_get(); |
2579 '-------------------------------------------------------------------------'
2580
2581 When the semaphore_name.try_get() method is called,
2582
2583 1. If the specified number of keys are available, the method returns 1 and execution continues
2584 2. If the specified number of keys are not available, the method returns 0 and execution continues
2585 3. The default number of keys requested is 1
2586
2587 //SEMAPHORE EXAMPLES
2588 =====================
2589
2590 1. //WITH ONE KEY
2591 ==================
2592 two processes accessing the same resource
2593 In the example below,
2594
2595 1.semaphore sema is created with the 1 key,
2596 2.two processes are accessing the display method at the same time,
2597 3.But only one process will get the semaphore key and the other process will wait till it gets the key
2598
2599 module semaphore_ex;
2600 semaphore sema; //declaring semaphore sema
2601
2602 initial
2603 begin
2604 sema=new(1); //creating sema with '1' key
2605
2606 fork
2607 display(); //process-1
2608 display(); //process-2
2609 join
2610 end
2611
2612 //display method
2613 task automatic display();
2614 sema.get(); //getting '1' key from sema
2615 $display($time,"\tCurrent Simulation Time");
2616 #30;
2617 sema.put(); //putting '1' key to sema
2618 endtask
2619 endmodule
2620
2621 /*Simulator Output
2622
2623 0 Current Simulation Time
2624 30 Current Simulation Time
2625 */
2626
2627 2. //WITH 4 KEYS
2628 =================
2629 Semaphore with 4 keys
2630 In the example below,
2631 Creating semaphore with ‘4’ keys
2632
2633 module semaphore_ex;
2634 semaphore sema; //declaring semaphore sema
2635 initial
2636 begin
2637 sema=new(4); //creating sema with '4' keys
2638 fork
2639 display(); //process-1
2640 display(); //process-2
2641 join
2642 end
2643 //display method
2644 task automatic display();
2645 sema.get(4); //getting '4' keys from sema
2646 $display($time,"\tCurent Simulation Time");
2647 #30;
2648 sema.put(4); //putting '4' keys to sema
2649 endtask
2650 endmodule
2651
2652 /*Simulator Output
2653
2654 0 Current Simulation Time
2655 30 Current Simulation Time
2656 */
2657
2658 3. //SEMAPHORE ACCESS WITH 2 KEYS
2659 ===================================
2660
2661 In the example below,
2662 Creating semaphore with ‘4’ keys. ‘2’ keys are required to get access to the method.
2663
2664 At the same time, two processes will get access to the method
2665 and the other process will be blocked until the one other process puts the key
2666
2667 module semaphore_ex;
2668 semaphore sema; //declaring semaphore sema
2669
2670 initial
2671 begin
2672 sema=new(4); //creating sema with '4' keys
2673 fork
2674 display(); //process-1
2675 display(); //process-2
2676 display(); //process-3
2677 join
2678 end
2679
2680 //display method
2681 task automatic display();
2682 sema.get(2); //getting '2' keys from sema
2683 $display($time,"\tCurrent Simulation Time");
2684 #30;
2685 sema.put(2); //putting '2' keys to sema
2686 endtask
2687 endmodule
2688
2689 /*Simulator Output
2690
2691 0 Current Simulation Time
2692 0 Current Simulation Time
2693 30 Current Simulation Time
2694 */
2695
2696 4.//PUTTING BACK MORE KEYS
2697 ===========================
2698 In the example below,
2699 Creating semaphore with ‘1’ key, putting more number of keys back to the semaphore
2700 module semaphore_ex;
2701 semaphore sema; //declaring semaphore sema
2702 initial
2703 begin
2704 sema=new(1); //creating sema with '1' keys
2705 fork
2706 display(1); //process-1
2707 display(2); //process-2
2708 display(3); //process-3
2709 join
2710 end
2711
2712 //display method
2713 task automatic display(int key);
2714 sema.get(key); //getting 'key' number of keys from sema
2715 $display($time,"\tCurrent Simulation Time, Got %0d keys",key);
2716 #30;
2717 sema.put(key+1); //putting 'key' number of keys to sema
2718 endtask
2719 endmodule
2720
2721 /*Simulator Output
2722
2723 0 Current Simulation Time, Got 1 keys
2724 30 Current Simulation Time, Got 2 keys
2725 60 Current Simulation Time, Got 3 keys
2726 */
2727
2728
2729 endclass
2730
2731 class //EVENTS
2732
2733 =========
2734 wait ---> can catch the event triggered in current simulation time slot
2735 and also catch the event triggered in future simulation time slot
2736
2737 @ ---> can catch the event triggered in future simulation time slot only
2738
2739 //EVENT EXAMPLES
2740 =================
2741
2742 1. the event waiting with @ operator
2743 The below example shows the event triggering and waiting for the event trigger
2744
2745 module events_ex;
2746 event ev_1; //declaring event ev_1
2747
2748 initial begin
2749 fork
2750 //process-1, triggers the event
2751 begin
2752 #40;
2753 $display($time,"\tTriggering The Event");
2754 ->ev_1;
2755 end
2756
2757 //process-2, wait for the event to trigger
2758 begin
2759 $display($time,"\tWaiting for the Event to trigger");
2760 @(ev_1.triggered);
2761 $display($time,"\tEvent triggered");
2762 end
2763 join
2764 end
2765 endmodule
2766
2767 /*Simulator Output
2768
2769 0 Waiting for the Event to trigger
2770 40 Triggering The Event
2771 40 Event triggered
2772 */
2773
2774 2. //TRIGGER FIRST AND THEN WAITING FOR A TRIGGER
2775 ====================================================
2776 In the below example,
2777 event triggering happens first and then the waiting for trigger happens.
2778 As the waiting happens later, it will be blocking, so the statements after the wait for the trigger will not be
2779 executed
2780
2781 module events_ex;
2782
2783 event ev_1; //declaring event ev_1
2784 initial begin
2785 fork
2786 //process-1, triggers the event
2787 begin
2788 #40;
2789 $display($time,"\tTriggering The Event");
2790 ->ev_1;
2791 end
2792 //process-2, wait for the event to trigger
2793 begin
2794 $display($time,"\tWaiting for the Event to trigger");
2795 #60;
2796 @(ev_1.triggered);
2797 $display($time,"\tEvent triggered");
2798 end
2799 join
2800 end
2801 initial begin
2802 #100;
2803 $display($time,"\tEnding the Simulation");
2804 $finish;
2805 end
2806 endmodule
2807
2808 //0 Waiting for the Event to trigger
2809 //40 Triggering The Event
2810 //100 Ending the Simulation
2811 */
2812
2813
2814 3.//TRIGGER AND WAIT FOR AN EVENT AT THE SAME TIME
2815 ===================================================
2816 In the example below,
2817 event triggering and waiting for the event trigger will happen at the same time.@() operator is used to detecting
2818 the event trigger. but as triggering and waiting happens at the same time, @() operator will not detect the event.
2819 this can be solved by using wait() operator;
2820
2821 module events_ex;
2822 event ev_1; //declaring event ev_1
2823
2824 initial
2825 begin
2826 fork
2827 //process-1, triggers the event
2828 begin
2829 $display($time,"\tTriggering The Event");
2830 ->ev_1;
2831 end
2832
2833 //process-2, wait for the event to trigger
2834 begin
2835 $display($time,"\tWaiting for the Event to trigger");
2836 @(ev_1.triggered);
2837 $display($time,"\tEvent triggered");
2838 end
2839 join
2840 end
2841 endmodule
2842
2843 /*Simulator Output
2844
2845 0 Triggering The Event
2846 0 Waiting for the Event to trigger
2847 */
2848
2849 4.//TRIGGER AND WAIT FOR AN EVENT AT THE SAME TIME
2850 ===================================================
2851
2852 In the example below,
2853 event triggering and waiting for the event trigger will happen at the same time.
2854 wait(); the operator is used to detects the event triggering
2855
2856 module events_ex;
2857 event ev_1; //declaring event ev_1
2858
2859 initial begin
2860 fork
2861 //process-1, triggers the event
2862 begin
2863 $display($time,"\tTriggering The Event");
2864 ->ev_1;
2865 end
2866
2867 //process-2, wait for the event to trigger
2868 begin
2869 $display($time,"\tWaiting for the Event to trigger");
2870 wait(ev_1.triggered);
2871 $display($time,"\tEvent triggered");
2872 end
2873 join
2874 end
2875 endmodule
2876
2877 /*Simulator Output
2878
2879 0 Triggering The Event
2880 0 Waiting for the Event to trigger
2881 0 Event triggered
2882 */
2883
2884 endclass
2885
2886 class //MAILBOX
2887
2888
2889
2890 //SYSTEMVERILOG MAILBOX EXAMPLE
2891 ================================
2892
2893 In the example below,
2894 Mailbox is used for communication between generator and driver.
2895
2896 Process-1(Generator_class) will .generate (created and randomize) the packet and put into the mailbox mb_box
2897 Process-2(Driver_class) gets the generated packet from the mailbox and display the fields
2898
2899 //-------------------------------------------------------------------------
2900 // Packet
2901 //-------------------------------------------------------------------------
2902
2903 class packet;
2904 rand bit [7:0] addr;
2905 rand bit [7:0] data;
2906
2907 //Displaying randomized values
2908 function void post_randomize();
2909 $display("Packet::Packet Generated");
2910 $display("Packet::Addr=%0d,Data=%0d",addr,data);
2911 endfunction
2912 endclass
2913
2914 //-------------------------------------------------------------------------
2915 //Generator - Generates the transaction packet and send to driver
2916 //-------------------------------------------------------------------------
2917
2918 class generator;
2919 packet pkt;
2920 mailbox m_box;
2921 //constructor, getting mailbox handle
2922 function new(mailbox m_box);
2923 this.m_box = m_box;
2924 endfunction
2925 task run;
2926 repeat(2)
2927 begin
2928 pkt = new();
2929 pkt.randomize(); //generating packet
2930 m_box.put(pkt); //putting packet into mailbox
2931 $display("Generator::Packet Put into Mailbox");
2932 #5;
2933 end
2934 endtask
2935 endclass
2936
2937 //-------------------------------------------------------------------------
2938 // Driver - Gets the packet from generator and display's the packet items
2939 //-------------------------------------------------------------------------
2940
2941 class driver;
2942 packet pkt;
2943 mailbox m_box;
2944
2945 //constructor, getting mailbox handle
2946 function new(mailbox m_box);
2947 this.m_box = m_box;
2948 endfunction
2949
2950 task run;
2951 repeat(2)
2952 begin
2953 m_box.get(pkt); //getting packet from mailbox
2954 $display("Driver::Packet Recived");
2955 $display("Driver::Addr=%0d,Data=%0d\n",pkt.addr,pkt.data);
2956 end
2957 endtask
2958 endclass
2959
2960 //-------------------------------------------------------------------------
2961 // tbench_top
2962 //-------------------------------------------------------------------------
2963
2964 module mailbox_ex;
2965 generator gen;
2966 driver dri;
2967 mailbox m_box; //declaring mailbox m_box
2968
2969 initial begin
2970 //Creating the mailbox, Passing the same handle to generator and driver,
2971 //because same mailbox should be shared in-order to communicate.
2972 m_box = new(); //creating mailbox
2973
2974 gen = new(m_box); //creating generator and passing mailbox handle
2975 dri = new(m_box); //creating driver and passing mailbox handle
2976 $display("------------------------------------------");
2977 fork
2978 gen.run(); //Process-1
2979 dri.run(); //Process-2
2980 join
2981 $display("------------------------------------------");
2982 end
2983 endmodule
2984
2985 /*Simulator Output
2986
2987 ------------------------------------------
2988 Packet::Packet Generated
2989 Packet::Addr=3,Data=38
2990 Generator::Packet Put into Mailbox
2991 Driver::Packet Recived
2992 Driver::Addr=3,Data=38
2993
2994 Packet::Packet Generated
2995 Packet::Addr=118,Data=92
2996 Generator::Packet Put into Mailbox
2997 Driver::Packet Recived
2998 Driver::Addr=118,Data=92
2999 ------------------------------------------
3000 */
3001
3002 endclass
3003
3004 endclass
3005
3006
3007 -----------------------------------------------===============================------------------------------------
3008 //==============================================DATA HIDING AND ENCAPSULATION=====================================
3009 -----------------------------------------------===============================------------------------------------
3010 class
3011 /*
3012 1. The technique of hiding the data within the class and making it available only through the methods,
3013 is known as encapsulation.
3014 2. Because it seals the data (and internal methods) safely inside the “capsule” of the class, where it can be
3015 accessed only by trusted users (i.e., by the methods of the class).
3016
3017 3. By default all the members and methods of a class are accessible from anywhere using the object handle,
3018 sometimes this could corrupt the class members values, which should not be touched at all.
3019 */
3020 //ACCESS CONTROL RULES THAT RESTRICT THE MEMBERS OF A CLASS FROM BEING USED OUTSIDE THE CLASS, THIS IS ACHIEVED BY
3021 PREFIXING THE CLASS MEMBERS WITH THE KEYWORDS,
3022
3023 1. local
3024 2. protected
3025
3026 //1. LOCAL CLASS MEMBERS
3027 ===========================
3028 External access to the.class members can be avoided by declaring members as local.
3029 Any violation could result in a compilation error.
3030
3031 SYNTAX:
3032 --------
3033 local integer x;
3034
3035 LOCAL CLASS MEMBERS EXAMPLES
3036 -----------------------------
3037
3038 //1 .ACCESSING LOCAL VARIABLE OUTSIDE THE CLASS ( NOT ALLOWED )
3039 ================================================================
3040 /*In below example,
3041
3042 //The local variable declared inside the class is trying to access from outside the class by using object handle. As
3043 the variable is declared as local, which leads to a compilation error.
3044
3045 class parent_class;
3046 local bit [31:0] tmp_addr;
3047
3048 function new(bit [31:0] r_addr);
3049 tmp_addr = r_addr + 10;
3050 endfunction
3051
3052 function display();
3053 $display("tmp_addr = %0d",tmp_addr);
3054 endfunction
3055 endclass
3056
3057
3058 // module
3059 module encapsulation;
3060 initial
3061 begin
3062 parent_class p_c = new(5);
3063
3064 p_c.tmp_addr = 20; //Accessing local variable outside the class
3065 p_c.display();
3066 end
3067 endmodule
3068 */
3069 /*Simulator Output
3070
3071 Error- Illegal class variable access
3072 testbench.sv,
3073 Local member 'tmp_addr' of class 'parent_class' is not visible to scope
3074 'encapsulation'.
3075 */
3076
3077 //2. ACCESSING LOCAL VARIABLE WITHIN THE CLASS ( ALLOWED )
3078 ===========================================================
3079 /*In the below example,
3080 //The local variable declared inside the class is being accessed inside the class. as it is allowed, no compilation
3081 error is observed.
3082
3083 class parent_class;
3084 local bit [31:0] tmp_addr;
3085
3086 function new(bit [31:0] r_addr);
3087 tmp_addr = r_addr + 10;
3088 endfunction
3089
3090 function display();
3091 $display("tmp_addr = %0d",tmp_addr); //Accessing local variable inside the class
3092 endfunction
3093 endclass
3094
3095 // module
3096 module encapsulation;
3097 initial
3098 begin
3099 parent_class p_c = new(5);
3100 p_c.display();
3101 end
3102 endmodule
3103 */
3104 /*Simulator Output
3105
3106 Addr = 15
3107 */
3108
3109
3110
3111 //2. PROTECTED CLASS MEMBERS
3112 =============================
3113 In some use cases,
3114 1. it is required to access the.class members only by the derived.class’s,
3115 2. this can be done by prefixing the.class members with the protected keyword
3116
3117 3. Any violation could result in a compilation error.
3118
3119 SYNTAX:
3120 --------
3121 protected integer x;
3122
3123 PROTECTED CLASS MEMBERS EXAMPLES
3124 ----------------------------------
3125
3126 //1. ACCESSING A PROTECTED VARIABLE OUTSIDE THE CLASS ( NOT ALLOWED )
3127 /*In the below example,
3128 The protected variable declared inside the class is trying to access from outside the class by using object handle
3129
3130 As the variable is declared as protected, which leads to a compilation error
3131
3132 //PARENT CLASS
3133 class parent_class;
3134 protected bit [31:0] tmp_addr;
3135
3136 function new(bit [31:0] r_addr);
3137 tmp_addr = r_addr + 10;
3138 endfunction
3139
3140 function display();
3141 $display("tmp_addr = %0d",tmp_addr);
3142 endfunction
3143 endclass
3144
3145 //CHILD CLASS
3146 class child_class extends parent_class;
3147 function new(bit [31:0] r_addr);
3148 super.new(r_addr);
3149 endfunction
3150
3151 function void incr_addr();
3152 tmp_addr++;
3153 endfunction
3154 endclass
3155
3156 //module
3157 module encapsulation;
3158 initial
3159 begin
3160 parent_class p_h = new(5);
3161 child_class c_h = new(10);
3162
3163 // variable declared as protected cannot be accessed outside the class
3164 p_h.tmp_addr = 10;
3165 p_h.display();
3166
3167 c_h.incr_addr(); //Accessing protected variable in extended class
3168 c_h.display();
3169 end
3170 endmodule
3171 */
3172 /*Simulator Output
3173
3174 Error- Illegal class variable access
3175 testbench.sv,
3176 Protected member 'tmp_addr' of class 'parent_class' is not visible to scope
3177 'encapsulation'.
3178 */
3179
3180 //ACCESSING A PROTECTED VARIABLE IN THE EXTENDED CLASS ( ALLOWED )
3181 /*In the below example,
3182 The protected variable declared inside the class is being accessed inside the extended class. as it is allowed, no
3183 compilation error is observed
3184
3185 //PARENT CLASS
3186 class parent_class;
3187 protected bit [31:0] tmp_addr;
3188
3189 function new(bit [31:0] r_addr);
3190 tmp_addr = r_addr + 10;
3191 endfunction
3192
3193 function display();
3194 $display("tmp_addr = %0d",tmp_addr);
3195 endfunction
3196 endclass
3197
3198 //CHILD CLASS
3199
3200 class child_class extends parent_class;
3201 function new(bit [31:0] r_addr);
3202 super.new(r_addr);
3203 endfunction
3204
3205 function void incr_addr();
3206 tmp_addr++;
3207 endfunction
3208 endclass
3209
3210 // module
3211 module encapsulation;
3212 initial
3213 begin
3214 child_class c_h = new(10);
3215
3216 c_h.incr_addr(); //Accessing protected variable in extended class
3217 c_h.display();
3218 end
3219 endmodule
3220 */
3221 /*Simulator Output
3222
3223 Addr = 21
3224
3225 */
3226
3227 endclass
3228
3229
3230 ------------------------------------------------=======================-------------------------------------------
3231 //==============================================Abstract Class(VIRTUAL)===========================================
3232 ------------------------------------------------=======================-------------------------------------------
3233 class
3234 /*
3235 SystemVerilog class declared with the keyword virtual is referred to as an abstract class.
3236
3237 1. An abstract class sets out the prototype for the sub-classes.
3238 2. An abstract class cannot be instantiated, it can only be derived.
3239 3. An abstract class can contain methods for which there are only a prototype and no implementation, just a
3240 method declaration.
3241
3242 */
3243
3244 //ABSTRACT CLASS EXAMPLES
3245 ==========================
3246
3247 1. INSTANTIATING VIRTUAL CLASS
3248 ================================
3249 In the below example,
3250 1. Creating an object of a virtual.class.
3251 2. An abstract.class can only be derived,
3252 3. creating an object of a virtual.class leads to a compilation error
3253
3254 //abstract class
3255 virtual class packet;
3256 bit [31:0] addr;
3257 endclass
3258
3259 class packet_2 extends packet;
3260
3261 endclass
3262
3263 module virtual_class;
3264 initial
3265 begin
3266 packet2_ p;
3267
3268 p = new();
3269
3270 p.addr=12;
3271 end
3272 endmodule
3273
3274 /*Simulator Output
3275
3276 virtual_class, "p = new();"
3277 Instantiation of the object 'p' can not be done because its type 'packet' is
3278 an abstract base class.
3279 Perhaps there is a derived class that should be used.
3280 */
3281
3282 2. DERIVING VIRTUAL CLASS
3283 ===========================
3284
3285 In the below example,
3286 An abstract.class is derived and written extend the.class and creating it
3287
3288 //abstract class
3289 virtual class packet;
3290 bit [31:0] addr;
3291 endclass
3292
3293 class extended_packet extends packet;
3294 function void display;
3295 $display("Value of addr is %0d", addr);
3296 endfunction
3297 endclass
3298
3299 module virtual_class;
3300 initial
3301 begin
3302 extended_packet p;
3303 p = new();
3304 p.addr = 10;
3305 p.display();
3306 end
3307 endmodule
3308
3309 /*Simulator Output
3310
3311 Value of addr is 10
3312
3313 */
3314
3315 endclass
3316
3317
3318 ------------------------------------------------=======================-------------------------------------------
3319 //==================================================VIRTUAL METHODS===============================================
3320 ------------------------------------------------=======================-------------------------------------------
3321 class
3322
3323 SystemVerilog Methods declared with the keyword virtual are referred to as virtual methods.
3324
3325 VIRTUAL METHODS,
3326 1. Virtual Functions
3327 2. Virtual Tasks
3328
3329 //VIRTUAL FUNCTIONS
3330 ====================
3331
3332 A.function declared with a virtual keyword before the.function keyword is referred to as virtual Function
3333
3334 //VIRTUAL TASK
3335 ===============
3336
3337 Task declared with a virtual keyword before the.task keyword is referred to as virtual.task
3338
3339
3340 //ABOUT VIRTUAL METHOD
3341 =======================
3342
3343 In a virtual method,
3344
3345 base_class b_c;
3346 extended_class e_c;
3347
3348 Considering both the.class’s has the method display().
3349
3350 assigning e_c to b_c,
3351
3352 b_c = e_c;
3353
3354 On calling b_c.display()
3355
3356 if display() method in base_class is virtual, then extended.class display method will get called
3357 if display() method in base_class is non-virtual, then base.class display method will get called
3358
3359 //Virtual function syntax
3360 --------------------------
3361 virtual function function_name;
3362 //Function definition
3363 endfunction
3364
3365 //Virtual task syntax
3366 ----------------------
3367 virtual task task_name;
3368 //task definition
3369 endtask
3370
3371 //VIRTUAL METHOD EXAMPLES
3372 ==========================
3373
3374 //METHOD WITHOUT VIRTUAL KEYWORD
3375 -----------------------------------
3376 /*In the below example,
3377
3378 the method inside the base class is declared without a virtual keyword,
3379 on calling method of the base class which is pointing to the extended class will call the base class method
3380 //PARENT CLASS
3381 class base_class;
3382
3383 function void display;
3384 $display("Inside base_class");
3385 endfunction
3386
3387 endclass
3388 //CHILD CLASS
3389 class extended_class extends base_class;
3390
3391 function void display;
3392 $display("Inside extended class");
3393 endfunction
3394
3395 endclass
3396
3397 module virtual_class;
3398 initial
3399 begin
3400 base_class b_c;
3401 extended_class e_c;
3402
3403 e_c = new();
3404 b_c = e_c;
3405
3406 b_c.display();
3407 end
3408 endmodule
3409 */
3410 /*Simulator Output
3411
3412 Inside base_class
3413
3414 */
3415
3416 //A METHOD WITH VIRTUAL KEYWORD
3417 -----------------------------------
3418 /*In the below example,
3419 the method inside the base class is declared with a virtual keyword, on calling method of the base class which
3420 is pointing to an extended class will call the extended class method
3421 //PARENT Class
3422
3423 class base_class;
3424
3425 virtual function void display;
3426 $display("Inside base_class");
3427 endfunction
3428
3429 endclass
3430
3431 //CHILD CLASS
3432
3433 class extended_class extends base_class;
3434
3435 function void display;
3436 $display("Inside extended_class");
3437 endfunction
3438
3439 endclass
3440
3441 module virtual_class;
3442 initial
3443 begin
3444 base_class b_c;
3445 extended_class e_c;
3446
3447 e_c = new();
3448 b_c = e_c;
3449
3450 b_c.display();
3451 end
3452 endmodule
3453 */
3454 /*Simulator Output
3455
3456 Inside extended_class
3457
3458 */
3459
3460
3461 endclass
3462
3463
3464 ------------------------------------------------=======================-------------------------------------------
3465 //===============================================PURE VIRTUAL METHODS=============================================
3466 ------------------------------------------------=======================-------------------------------------------
3467 class
3468
3469 1. Pure virtual methods is a virtual method that you want to force child_class to override
3470 2. Pure virtual methods can be declared inside abstrac_class only
3471 3. Pure virtual methods has no implementation
3472 4. Pure virtual methods has no .endfunction/.endtask
3473
3474 There are two major difference between virtual and pure virtual methods
3475 1. There can't be a definition of the pure virtual methods in the base_class
3476 2. There must be definition of the pure virtual methods in the derived_class
3477
3478 A_class extended from an abstract_class can only be instantiated if all pure virtual methods have bodies in
3479 extended_class
3480
3481
3482 endclass
3483
3484
3485 -------------------------------------------------===========================--------------------------------------
3486 //================================================STATIC PROPERTIES/METHODS=======================================
3487 -------------------------------------------------===========================--------------------------------------
3488 class
3489 / 1. Class members can be created with the keyword static.
3490 2. Class members with the keyword static are called as static_class members.
3491 3. The_class can have static properties and static methods (functions and tasks)
3492 4. A single copy of static variables is shared across multiple instances
3493
3494 //STATIC PROPERTIES
3495 ====================
3496 1.The_class can have multiple instances
3497 2.each instance of the_class will be having its own copy of variables
3498 3.Sometimes only one version of a variable is required to be shared by all instances
3499 4.These_class properties are created using the keyword static.
3500
3501 SYNTAX
3502 -------
3503 //static <data_type> <property_name>;
3504 Note:
3505
3506 1.Static.class properties and methods can be used without creating an object of that type
3507 2.Static.class properties and methods can be accessed using scope-resolution operator
3508 3.Memory .for static properties allocated at compile time*/
3509
3510 //EXAMPLE: without creating object
3511 ===================================
3512
3513 class A;
3514 static int i;
3515 //endclass
3516
3517 program main;
3518 A obj_1;
3519 A obj_2;
3520
3521 initial
3522 begin
3523 obj_1.i = 123;
3524 $display(obj_2.i);
3525 end
3526 endprogram
3527
3528 RESULT
3529
3530 123
3531
3532
3533 //EXAMPLE: using scope-resolution Operator
3534 ===========================================
3535 class A ;
3536 static int i;
3537 endclass
3538
3539 program main;
3540 A obj_1;
3541 //obj_1=new;
3542 initial
3543 begin
3544 obj_1.i = 123;
3545 //A::i=123;
3546 $display(A::i);
3547 end
3548 endprogram
3549
3550 RESULT
3551
3552 123
3553
3554 //STATIC METHODS
3555 =================
3556 1. Static methods are the same as static properties,
3557 2. A static method can access only static properties of the.class
3558 3. Access to the non-static properties is illegal and lead to a compilation error.
3559 4. Static methods can not be .virtual
3560
3561 Note:
3562
3563 1.Static.class properties and methods can be used without creating an object of that type.
3564 2.Static.class properties and methods can be accessed using scope-resolution operator
3565
3566 SYNTAX
3567 -------
3568 // static task/function <method_name>;
3569
3570 //EXAMPLES
3571 ===========
3572
3573 Example::1;
3574
3575 class base;
3576 static int i;
3577
3578 static function get();
3579 int a;
3580 a++;
3581 i++;
3582
3583 $display("a=%d",a);
3584 $display("i=%d",i);
3585 endfunction
3586 endclass
3587
3588 base b1_h,b2_h;
3589
3590 module test();
3591 initial
3592 begin
3593 b1_h.get();
3594 b1_h.get();
3595 b2_h.get();
3596 end
3597 endmodule
3598
3599
3600 /*RESULT
3601
3602 a=1 i=1
3603 a=1 i=2
3604 a=1 i=3
3605
3606 */
3607
3608 Example::2;
3609
3610 class base;
3611 int i;
3612
3613 static function get();
3614 int a;
3615 a++;
3616 i++;
3617
3618 $display("a=%d",a);
3619 $display("i=%d",i);
3620 endfunction
3621 endclass
3622
3623 base b1_h,b2_h;
3624
3625 module test();
3626 initial
3627 begin
3628 b1_h.get();
3629 b1_h.get();
3630 b2_h.get();
3631 end
3632 endmodule
3633
3634
3635 /*RESULT
3636
3637 Illegal to access non-static property 'i' from a static method.
3638
3639 */
3640
3641 Example::3;
3642
3643 class base;
3644 static int i;
3645
3646 function static get();
3647 int a;
3648 a++;
3649 i++;
3650
3651 $display("a=%d",a);
3652 $display("i=%d",i);
3653 endfunction
3654 endclass
3655
3656 base b1_h,b2_h;
3657
3658 module test();
3659 initial
3660 begin
3661 b1_h.get();
3662 b1_h.get();
3663 b2_h.get();
3664 end
3665 endmodule
3666
3667
3668 /*RESULT
3669
3670 a=1 i=1
3671 a=2 i=2
3672 a=3 i=3
3673
3674 */
3675
3676 Example::4;
3677
3678 class base;
3679 int i;
3680
3681 function static get();
3682
3683 int a;
3684 a++;
3685 i++;
3686
3687 $display("a=%d",a);
3688 $display("i=%d",i);
3689 endfunction
3690 endclass
3691
3692 base b1_h;
3693
3694 module test();
3695 initial
3696 begin
3697 b1_h.get();
3698 b1_h.get();
3699 b1_h.get();
3700 end
3701 endmodule
3702
3703
3704 /*RESULT
3705
3706 Here i is a dynamic variable so we can not access is without creating object so it will throw an error
3707
3708 */
3709
3710
3711 Example::5;
3712
3713 class base;
3714 int i;
3715
3716 function static get();
3717 int a;
3718 a++;
3719 i++;
3720
3721 $display("a=%d",a);
3722 $display("i=%d",i);
3723 endfunction
3724 endclass
3725
3726 base b1_h,b2_h;
3727
3728 module test();
3729 initial
3730 begin
3731 b1_h=new;
3732 b2_h=new;
3733 b1_h.get();
3734 b1_h.get();
3735 b2_h.get();
3736 end
3737 endmodule
3738
3739
3740 /*RESULT
3741 a=1 i=1
3742 a=2 i=2
3743 a=3 i=3
3744 */
3745
3746
3747 Example::6;
3748
3749 class base;
3750
3751 static int i;
3752
3753 function static get();
3754
3755 int b;
3756 int a;
3757 a++;
3758 i++;
3759
3760 $display("a=%d",a);
3761 $display("i=%d",i);
3762 endfunction
3763 endclass
3764
3765 base b1_h,b2_h;
3766
3767 module test();
3768 initial
3769 begin
3770 //b1_h=new;
3771 //b2_h=new;
3772 b1_h.get();
3773 b1_h.get();
3774 b2_h.get();
3775 end
3776 endmodule
3777
3778
3779 /*RESULT
3780 a=1 i=1
3781 a=2 i=2
3782 a=3 i=3
3783 */
3784
3785
3786 endclass
3787
3788
3789 ----------------------------------------------------===============-----------------------------------------------
3790 //===================================================RANDOMIZATION================================================
3791 ----------------------------------------------------===============-----------------------------------------------
3792 class
3793 class VERILOG RANDOM SYSTEM FUNCTION
3794 // $random();
3795 ==============
3796
3797 1.$random system_function returns a new 32-bit random number each time it is called.
3798 2.The random number is a signed integer;
3799 3.It can be positive or negative.
3800
3801 The following example demonstrates random generation of signed numbers
3802
3803 EXAMPLE:
3804 module Tb();
3805 integer address;
3806
3807 initial
3808 begin
3809 repeat(5)
3810 #1 address = $random;
3811 end
3812
3813 initial
3814 $monitor("address = %0d;",address);
3815
3816 endmodule
3817
3818 RESULT:
3819
3820 address = 303379748;
3821 address = -1064739199;
3822 address = -2071669239;
3823 address = -1309649309;
3824 address = 112818957;
3825
3826
3827
3828
3829 /* We have seen how to generate random numbers.
3830
3831 But the numbers randge from - (2**32 -1) to 2 **32.
3832 Most of the time, the requirement is dont need this range.
3833
3834 For example, take a memory.
3835 The address starts from 0 to some 1k or 1m.
3836 Generating a random address which DUT is not supporting is meaning less.
3837
3838 In verilog there are no constructs to constraint randomization.
3839
3840 Following example demonstrated how to generate random number between 0 to 10.
3841 Using % operation,the remainder of any number is always between 0 to 10.
3842 */
3843
3844
3845 EXAMPLE:
3846 module Tb();
3847 integer add_1;
3848
3849 initial
3850 begin
3851 repeat(5)
3852 begin
3853 #1;
3854 add_1 = $random % 10;
3855 end
3856 end
3857
3858 initial
3859 $monitor("add_1 = %0d",add_1);
3860
3861 endmodule
3862
3863 RESULT:
3864
3865 add_1 = 8;
3866 add_1 = 4294967287;
3867 add_1 = 4294967295;
3868 add_1 = 9;
3869 add_1 = 9;
3870
3871
3872 /*OOPS!...... The results are not what is expected.
3873 The reason is $random generates negative numbers also.
3874
3875 The following example demonstrates proper way of generating a random number between 0 to 10.
3876 Concatenation operator returns only bitvector. Bit vectors are unsigned, so the results are correct as we
3877 expected.
3878 */
3879
3880 EXAMPLE:
3881 module Tb();
3882 integer add_1;
3883
3884 initial
3885 begin
3886 repeat(5)
3887 begin
3888 #1;
3889 add_1 = {$random} % 10;
3890 add_1 = $unsigned($random) % 10;
3891 end
3892 end
3893
3894 initial
3895 $monitor("add_1 = %0d",add_1);
3896
3897 endmodule
3898
3899 RESULT:
3900
3901 add_1 = 8;
3902 add_1 = 7;
3903 add_1 = 5;
3904 add_1 = 9;
3905 add_1 = 9;
3906
3907
3908
3909 The above example shows the generation of numbers from 0 to N.
3910 Some specification require the range to start from non Zero number.
3911
3912 MIN + {$random} % (MAX - MIN )
3913
3914 will_generate random numbers between MIN and MAX
3915
3916
3917
3918 EXAMPLE:
3919 module Tb();
3920 integer add;
3921
3922 initial
3923 begin
3924 repeat(5)
3925 begin
3926 #1;
3927 add = 40 + {$random} % (50 - 40) ;
3928 $display("add = %0d",add);
3929 end
3930 end
3931 endmodule
3932
3933 RESULT:
3934
3935 add = 48
3936 add = 47
3937 add = 49
3938 add = 46
3939 add = 47
3940
3941
3942 //NOW HOW TO GENERATE A RANDOM NUMBER BETWEEN TWO RANGES?
3943 ============================================================
3944 The number should be between MIN1 and MAX1 or MIN2 and MAX2.
3945
3946 The following example show how to_generate this specification
3947
3948
3949
3950 EXAMPLE:
3951 module Tb();
3952 integer add;
3953
3954 initial
3955 begin
3956 repeat(5)
3957 begin
3958 #1;
3959 if($random % 2)
3960 add = 40 + {$random} % (50 - 40) ;
3961 else
3962 add = 90 + {$random} % (100 - 90) ;
3963 $display("add = %0d",add);
3964 end
3965 end
3966 endmodule
3967
3968 RESULT:
3969
3970 add = 97
3971 add = 47
3972 add = 87
3973 add = 42
3974 add = 49
3975
3976 endclass
3977
3978 class SYSTEM VERILOG RANDOM SYSTEM Function
3979
3980 In addition to the system_function which are in verilog,
3981
3982 SystemVerilog has:
3983
3984 1. $urandom()
3985 2. $urandom_range()
3986
3987 returns a unsigned values
3988
3989 //EXAMPLES
3990 -----------
3991
3992 EXAMPLE:
3993 module Tb();
3994 integer address;
3995
3996 initial
3997 begin
3998 repeat(5)
3999 begin
4000 address = $urandom();
4001 $display("address = %d;",address);
4002 end
4003 end
4004
4005 endmodule
4006
4007 RESULTS:
4008
4009 # address = 3468265955;
4010 # address = 541037099;
4011 # address = 3836988758;
4012 # address = 3611785217;
4013 # address = 978699393;
4014 $Urandom_range
4015
4016
4017
4018 //$urandom_range()
4019
4020 1 .function returns an unsigned integer within a specified range.
4021
4022 2. The syntax for $urandom_range() is as follows:
4023
4024 $urandom_range( int unsigned maxval,int unsigned minval = 0 );
4025
4026 3. The_function shall return an unsigned integer in the range of maxval ... minval
4027
4028
4029 EXAMPLE:1
4030 module Tb();
4031 integer num_1,num_2;
4032
4033 initial
4034 begin
4035 repeat(5)
4036 begin
4037 #1;
4038 num_1 = $urandom_range(25,20);
4039 num_2 = $urandom_range(55,50);
4040 $display("num_1 = %0d,num_2 = %0d",num_1,num_2);
4041 end
4042 end
4043 endmodule
4044
4045 RESULTS:
4046
4047 # num_1 = 25,num_2 = 55
4048 # num_1 = 22,num_2 = 55
4049 # num_1 = 23,num_2 = 52
4050 # num_1 = 21,num_2 = 54
4051 # num_1 = 25,num_2 = 54
4052
4053
4054
4055 //If minval is omitted, the_function shall return a value in the range of maxval ... 0
4056
4057
4058 EXAMPLE:2
4059 module Tb();
4060 integer num_1,num_2;
4061
4062 initial
4063 begin
4064 repeat(5)
4065 begin
4066 #1;
4067 num_1 = $urandom_range(3);
4068 num_2 = $urandom_range(5);
4069 $display("num_1 = %0d,num_2 = %0d",num_1,num_2);
4070 end
4071 end
4072 endmodule
4073
4074 RESULTS:
4075
4076 num_1 = 3,num_2 = 5
4077 num_1 = 2,num_2 = 5
4078 num_1 = 1,num_2 = 2
4079 num_1 = 3,num_2 = 4
4080 num_1 = 1,num_2 = 4
4081
4082
4083
4084
4085 //If maxval is less than minval,
4086 //the arguments are automatically reversed so that the first argument is larger than the second argument.
4087
4088
4089 EXAMPLE:3
4090 module Tb();
4091 integer num_1,num_2;
4092
4093 initial
4094 begin
4095 repeat(5)
4096 begin
4097 #1;
4098 num_1 = $urandom_range(20,25);
4099 num_2 = $urandom_range(50,55);
4100 $display("num_1 = %0d,num_2 = %0d",num_1,num_2);
4101 end
4102 end
4103 endmodule
4104
4105 RESULTS:
4106
4107 num_1 = 25,num_2 = 55
4108 num_1 = 22,num_2 = 55
4109 num_1 = 23,num_2 = 52
4110 num_1 = 21,num_2 = 54
4111 num_1 = 25,num_2 = 54
4112
4113 endclass
4114
4115 class//RANDOM VARIBLE DECLARATION:
4116 ==================================
4117
4118
4119
4120 Variables declared as rand or randc are only randomized due to call of randomize() .function
4121 All other varibles are considered as state variables
4122
4123
4124
4125 EXAMPLE:
4126 class ex_8;
4127 rand bit[3:0] var1;
4128 randc bit[3:0] var2;
4129 rand integer var3;
4130 endclass
4131
4132
4133
4134
4135 1. Fixed arrays, dynamic arrays, associative arrays and queues can be declared as rand or randc
4136 2. All their elements are treated as random.
4137 3. Individual array elements can also be constrained,in this_case, index expression must be constant.
4138 4. For dynamic arrays, the size of the array length can be constrained.
4139
4140
4141 //SCOPE-RANDOMIZATION
4142 ======================
4143
4144 1. std::randomize(), enables users to randomize data in the current scope without the need to define a_class
4145 or instantiate a_class object.
4146 2. Variable which are passed as arguments are randomized
4147 3. There are no limit on the no of arguments
4148 4. If a property does not of rand or randc type then it can be randomize by giving that property as arguments to
4149 randomize() method
4150
4151 eg. success = std::randomize(a,b);
4152
4153 where std ---> class_name
4154 5. We can add inline constraints with randomize() method
4155
4156 eg. success = std::randomize(a,b) with {a>10;b<20;a<20};
4157
4158 6. Most important is that the std::randomize_function behaves exactly the same as a_class randomize method,
4159 except that it operates on the variables of the current scope instead of_class member variables.
4160
4161 7. It will return 1 on succesful randomization and return 0 on failed
4162
4163 EXAMPLE:1
4164 ----------
4165
4166 module top;
4167
4168 int a;
4169 int b;
4170 bit success;
4171
4172 initial
4173 begin
4174
4175 success=std::randomize(a,b);
4176 //void'(std::randomize());
4177 $display("a=%d and b=%d",a,b);
4178 end
4179 endmodule
4180
4181 RESULT:
4182
4183 a=3259;
4184 b=44588;
4185
4186
4187 //RAND KEYWORD
4188 ===============
4189 1. Variable declared with the rand keyword are standard random variable.
4190 2. There values are uniformly distributed over their range
4191 3. Random values can be repeated
4192
4193 rand bit[1:0] var1;
4194
4195 0,1,2,3
4196 0,3,2,3
4197 1,2,1,3
4198
4199 //RANDC KEYWORD
4200 ================
4201
4202 1. For variable declared with randc keyword
4203 2. On randomization variable value does not repeat untill every possible value has been assigned
4204
4205 randc bit[1:0] var1;
4206
4207 0,1,2,3 0,1,2,1 x
4208 3,1,2,0
4209 2,1,0,3
4210 3,0,1,2
4211 endclass
4212
4213 class DISABLE RANDOMIZATION(rand_mode())
4214
4215 /*The variable declared without rand or randc will not get random values on randomization.
4216 what if for some reason it is required not to generate a random value for a random variable.
4217 Yes, it is possible to disable the randomization of a variable by using the systemverilog randomization method
4218 rand_mode.*/
4219
4220 //RAND_MODE METHOD
4221 ====================
4222
4223 The rand_mode() method is used to disable the randomization of a variable declared with the rand/randc keyword.
4224
4225 1. rand_mode(1) ---> means randomization enabled
4226 2. rand_mode(0) ---> means randomization disabled
4227
4228 The default value of rand_mode is 1, i.e enabled
4229
4230 3. Once the randomization is disabled,
4231 4. it is required to make rand_mode(1) enable back the randomization
4232
4233 5. rand_mode can be called as SystemVerilog method,
4234 6. the randomization enables/disable status of a variable can be obtained by calling
4235
4236 variable.rand_mode()
4237
4238 7. the rand_mode method returns 1 if randomization is enabled else returns 0
4239
4240
4241 RAND_MODE SYNTAX:
4242 -----------------
4243 .-------------------------------------------------------.
4244 | <object_hanlde>.<variable_name>.rand_mode(enable); |
4245 '-------------------------------------------------------'
4246
4247 //enable = 1, randomization enable
4248 //enable = 0, randomization disable
4249
4250
4251
4252 1. WITHOUT RANDOMIZATION DISABLE
4253 =================================
4254
4255 In the below example,
4256 The_class packet has random variables addr and data,
4257 on randomization, these variables will get random value
4258
4259 class packet;
4260 rand byte addr;
4261 rand byte data;
4262 endclass
4263
4264 module rand_methods;
4265 initial
4266 begin
4267 packet pkt;
4268 pkt = new();
4269
4270 //calling randomize method
4271 pkt.randomize();
4272
4273 $display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);
4274 end
4275 endmodule
4276
4277 //Simulator Output
4278
4279 addr = 110 data = 116
4280
4281
4282 2.RANDOMIZATION DISABLE FOR A CLASS VARIABLE
4283 =============================================
4284
4285 In the below example,
4286
4287 The_class packet has random variables addr and data,
4288 randomization is disabled for a variable addr,
4289 on randomization only data will get random value.
4290 The addr will not get any random value.
4291
4292 rand_mode() method is called in a display to know the status
4293
4294 class packet;
4295 rand byte addr;
4296 rand byte data;
4297 endclass
4298
4299 module rand_methods;
4300 initial
4301 begin
4302 packet pkt;
4303 pkt = new();
4304
4305 //disable rand_mode of addr variable of pkt
4306 pkt.addr.rand_mode(0);
4307
4308 //calling randomize method
4309 pkt.randomize();
4310
4311 $display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);
4312
4313 $display("\taddr.rand_mode() = %0d \t data.rand_mode() = %0d",pkt.addr.rand_mode(),
4314 pkt.data.rand_mode());
4315 end
4316 endmodule
4317
4318 //Simulator Output
4319
4320 addr = 0 data = 110
4321 addr.rand_mode() = 0 data.rand_mode() = 1
4322
4323
4324
4325 3.RANDOMIZATION DISABLE FOR ALL CLASS VARIABLE
4326 ================================================
4327 In the below example,
4328
4329 randomization for all the_class variable is disabled by calling obj.rand_mode(0);
4330
4331 class packet;
4332 rand byte addr;
4333 rand byte data;
4334 endclass
4335
4336 module rand_methods;
4337 initial
4338 begin
4339 packet pkt;
4340 pkt = new();
4341
4342 $display("\taddr.rand_mode() = %0d \t data.rand_mode() =
4343 %0d",pkt.addr.rand_mode(),pkt.data.rand_mode());
4344
4345 //disable rand_mode of object
4346 pkt.rand_mode(0);
4347
4348 //calling randomize method
4349 pkt.randomize();
4350
4351 $display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);
4352
4353 $display("\taddr.rand_mode() = %0d \t data.rand_mode() =
4354 %0d",pkt.addr.rand_mode(),pkt.data.rand_mode());
4355 end
4356 endmodule
4357
4358 //Simulator Output
4359
4360 addr.rand_mode() = 1 data.rand_mode() = 1
4361 addr = 0 data = 0
4362 addr.rand_mode() = 0 data.rand_mode() = 0
4363
4364
4365
4366 endclass
4367
4368 class CONSTRAINED RANDOMIZATION
4369
4370 class//CONSTRAINT BLOCKS
4371 =========================
4372
4373 1. Constraint blocks are_class members like tasks, functions, and variables
4374 2. Constraint blocks will have a unique name within a .class
4375 3. Constraint blocks consist of conditions or expressions to limit or control the values for a random variable
4376 4. Constraint blocks are enclosed within curly braces { }
4377 5. Constraint blocks can be defined inside the_class or outside the_class like .extern methods,
4378 6. constraint block defined outside the_class is called as .extern constraint block
4379
4380 CONSTRAINT BLOCK SYNTAX
4381 --------------------------
4382 constraint <constraint_block_name> { <condition/expression>;
4383 ...
4384 <condition/expression>;}
4385 CONSTRAINT BLOCK EXAMPLE
4386
4387 constraint addr_range { addr > 5; }
4388
4389 where,
4390 addr_range is .constraint block name
4391 addr is constrained in such a way that on randomization addr will get a value greater than 5
4392
4393
4394 //CONSTRAINT BLOCK INSIDE THE CLASS
4395 ====================================
4396 In the below example,
4397
4398 constraint block is defined inside the_class
4399
4400 class packet;
4401 rand bit [3:0] addr;
4402
4403 constraint addr_range { addr > 5; }
4404 endclass
4405
4406 module constr_blocks;
4407 initial
4408 begin
4409 packet pkt;
4410 pkt = new();
4411 repeat(10)
4412 begin
4413 pkt.randomize();
4414 $display("\taddr = %0d",pkt.addr);
4415 end
4416 end
4417 endmodule
4418
4419 /*Simulator Output
4420
4421 addr = 14
4422 addr = 10
4423 addr = 9
4424 addr = 8
4425 addr = 9
4426 addr = 6
4427 addr = 10
4428 addr = 14
4429 addr = 12
4430 addr = 8
4431
4432 */
4433
4434 //CONSTRAINT BLOCK OUTSIDE THE CLASS
4435 =====================================
4436 In the below example,
4437
4438 .constraint block is declared inside the_class and defined outside the_class
4439
4440 class packet;
4441
4442 rand bit [3:0] addr;
4443 //constraint block declaration
4444 constraint addr_range;
4445 endclass
4446
4447 //constraint implementation outside class body
4448 constraint packet::addr_range { addr > 5; }
4449
4450 module extern_constr;
4451 initial
4452 begin
4453 packet pkt;
4454 pkt = new();
4455
4456 repeat(10)
4457 begin
4458 pkt.randomize();
4459 $display("\taddr = %0d",pkt.addr);
4460 end
4461 end
4462 endmodule
4463
4464 /*Simulator Output
4465
4466 addr = 14
4467 addr = 10
4468 addr = 9
4469 addr = 8
4470 addr = 9
4471 addr = 6
4472 addr = 10
4473 addr = 14
4474 addr = 12
4475 addr = 8
4476 */
4477
4478 endclass
4479
4480 class //INSIDE Constraint
4481 ==========================
4482 During randomization, it might require to randomize the variable within a range of values or with inset of
4483 values or other than a range of values. this can be achieved by using constraint inside operator.With SystemVerilog
4484 inside operator, random variables will get values specified within the inside block.
4485
4486 values within the inside block can be variable, constant or range
4487 1. the inside block is written with an inside keyword followed by curly braces {}
4488
4489 constraint addr_range { addr inside { ... }; }
4490
4491 2. the range is specified by [ ]
4492
4493 constraint addr_range { addr inside { [5:10]}; }
4494
4495 3. set of values are specified by ‘comma’,
4496
4497 constraint addr_range { addr inside { 1,3,5,7,9}; }
4498
4499 4. it is allowed to mix range and set of values
4500
4501 constraint addr_range { addr inside {1,3,[5:10],12,[13:15]}; }
4502
4503 5. if the value needs to be outside the range, then it can be specified as inverse (!) of inside
4504
4505 constraint addr_range { addr !(inside {[5:10]}); }
4506
4507 6. Other random variables can be used in inside block
4508
4509 rand bit [3:0] start_addr;
4510 rand bit [3:0] end_addr;
4511 rand bit [3:0] addr;
4512
4513 constraint addr_range { addr inside {[start_addr:end_addr]}; }
4514
4515
4516
4517
4518 //CONSTRAINT INSIDE EXAMPLE
4519 ============================
4520
4521 In the example below,
4522
4523 addr_1 will get random value within the range start_addr and end_addr,
4524
4525 class packet;
4526 rand bit [3:0] addr;
4527 rand bit [3:0] start_addr;
4528 rand bit [3:0] end_addr;
4529
4530 constraint addr_1_range { addr inside {[start_addr:end_addr]}; }
4531 endclass
4532
4533 module constr_inside;
4534 initial
4535 begin
4536 packet pkt;
4537 pkt = new();
4538 $display("------------------------------------");
4539 repeat(3)
4540 begin
4541 pkt.randomize();
4542 $display("\tstart_addr = %0d,end_addr = %0d",pkt.start_addr,pkt.end_addr);
4543 $display("\taddr = %0d",pkt.addr);
4544 $display("------------------------------------");
4545 end
4546 end
4547 endmodule
4548
4549 /*Simulator Output
4550
4551 ------------------------------------
4552 start_addr = 12,end_addr = 13
4553
4554 addr = 12
4555 ------------------------------------
4556 start_addr = 3,end_addr = 7
4557
4558 addr = 7
4559 ------------------------------------
4560 start_addr = 5,end_addr = 11
4561
4562 addr = 9
4563 ------------------------------------
4564 */
4565
4566 endclass
4567
4568 class //DISTRIBUTION Constraint(dist)
4569
4570 with dist operator,
4571
4572 1. it’s possible to control the occurrence or repetition of the same value on randomization
4573 2. some values can be allocated more often to a random variable
4574 3. dist is an operator, it takes a list of values and weights, separated by := or :/ operator
4575
4576
4577 //WEIGHTED DISTRIBUTION
4578 ========================
4579 As the name says,
4580 1. In weighted distribution weight will be specified to the values inside the constraint block
4581 2. Value with the more weight will get allocated more often to a random variable
4582
4583 SYNTAX
4584 ------- .---------------------------.
4585 | value := weight or |
4586 | value :/ weight |
4587 '---------------------------'
4588
4589 Value – desired value to a random variable
4590 weight – indicates how often the value needs to be considered on randomization
4591
4592 3. The values and weights can be constants or variables,
4593 4. value can be single or a range
4594 5. The default weight of an unspecified value is := 1
4595 6. The sum of weights need not be a 100
4596
4597 The := operator,
4598 ================
4599
4600 assigns the specified weight to the item,
4601 or if the item is a range, specified weight to every value in the range.
4602
4603 addr dist { 2 := 5, [10:12] := 8 };
4604
4605 for addr == 2 , weight 5 5/13
4606 addr == 10, weight 8 8/13
4607 addr == 11, weight 8 8/13
4608 addr == 12, weight 8
4609
4610 The :/ operator,
4611 ================
4612
4613 assigns the specified weight to the item,
4614 or if the item is a range, specified weight/n to every value in the range.
4615 where n is the number of values in the range.
4616
4617 addr dist { 2 :/ 5, [10:12] :/8 };
4618
4619 for addr == 2 , weight 5/1 5/13
4620 addr == 10, weight 8/3 (2.66)/13
4621 addr == 11, weight 8/3
4622 addr == 12, weight 8/3
4623
4624
4625
4626
4627 //WEIGHTED DISTRIBUTION CONSTRAINT EXAMPLES
4628 =============================================
4629
4630 In the example below,
4631 On randomization, the possibility of ‘addr’ is getting the value of 10 is more than 7 and 2
4632 this is because of weight specified to get value 10 is more than the other two values
4633
4634 class packet;
4635 rand bit [3:0] addr;
4636
4637 constraint addr_range { addr dist { 2 := 5, 7 := 8, 10 := 12 }; }
4638 endclass
4639
4640 module constr_dist;
4641 initial
4642 begin
4643 packet pkt;
4644 pkt = new();
4645 $display("------------------------------------");
4646 repeat(10)
4647 begin
4648 pkt.randomize();
4649 $display("\taddr = %0d",pkt.addr);
4650 end
4651 $display("------------------------------------");
4652 end
4653 endmodule
4654
4655 /*Simulator Output
4656
4657 ------------------------------------
4658 addr = 10
4659 addr = 7
4660 addr = 10
4661 addr = 10
4662 addr = 10
4663 addr = 7
4664 addr = 7
4665 addr = 2
4666 addr = 10
4667 addr = 10
4668 ------------------------------------
4669 */
4670
4671
4672
4673 //DIFFERENCE BETWEEN := AND :/ DIST OPERATOR
4674 ==============================================
4675
4676 In the below example,
4677
4678 addr_1=2 weight=5, and addr_1=10 weight=8, addr_1=11 weight=8, addr_1=12 weight=8
4679
4680 addr_1=2 weight=5, and addr_1=10 weight=9/3=3, addr_1=11 weight=3, addr_1=12 weight=3
4681
4682 class packet;
4683 rand bit [3:0] addr_1;
4684 rand bit [3:0] addr_2;
4685
4686 constraint addr_1_range { addr_1 dist { 2 := 5, [10:12] := 8 }; }
4687 constraint addr_2_range { addr_2 dist { 2 :/ 5, [10:12] :/ 9 }; }
4688 endclass
4689
4690 module constr_dist;
4691 initial
4692 begin
4693 packet pkt;
4694 pkt = new();
4695
4696 $display("------------------------------------");
4697 repeat(10)
4698 begin
4699 pkt.randomize();
4700 $display("\taddr_1 = %0d",pkt.addr_1);
4701 end
4702 $display("------------------------------------");
4703 $display("------------------------------------");
4704 repeat(10)
4705 begin
4706 pkt.randomize();
4707 $display("\taddr_2 = %0d",pkt.addr_2);
4708 end
4709 $display("------------------------------------");
4710 end
4711 endmodule
4712 /*SIMULATOR Output
4713 # ------------------------------------
4714 # addr_1 = 10
4715 # addr_1 = 10
4716 # addr_1 = 12
4717 # addr_1 = 10
4718 # addr_1 = 12
4719 # addr_1 = 12
4720 # addr_1 = 10
4721 # addr_1 = 2
4722 # addr_1 = 11
4723 # addr_1 = 2
4724 # ------------------------------------
4725 # ------------------------------------
4726 # addr_2 = 2
4727 # addr_2 = 11
4728 # addr_2 = 11
4729 # addr_2 = 10
4730 # addr_2 = 12
4731 # addr_2 = 11
4732 # addr_2 = 2
4733 # addr_2 = 2
4734 # addr_2 = 2
4735 # addr_2 = 10
4736 # ------------------------------------
4737
4738
4739
4740 */
4741 endclass
4742
4743 class //Verilog implication if else Constraints
4744
4745 //IMPLICATION CONSTRAINTS
4746 ==========================
4747
4748 1. The implication operator can be used to declaring conditional relations between two variables
4749 2. Implication operator is denoted by the symbol ->
4750 3. The implication operator is placed between the expression and constraint
4751
4752 Syntax
4753 -------
4754 expression -> constraint
4755
4756 If the expression on the LHS of implication operator (->) is true, then the only constraint on the RHS will be
4757 considered.
4758
4759 IMPLICATION CONSTRAINT EXAMPLE
4760 ===============================
4761
4762 In the example below,
4763
4764 If addr_range == small, then addr will get a value less than 8.
4765
4766 i.e implication operator is used to mention condition between the two variables addr_range and addr
4767
4768 class packet;
4769 rand bit [3:0] addr;
4770 string addr_range;
4771 constraint address_range { (addr_range == "small") -> (addr < 8);}
4772 endclass
4773
4774 module constr_implication;
4775 initial
4776 begin
4777 packet pkt;
4778 pkt = new();
4779
4780 pkt.addr_range = "small";
4781 $display("------------------------------------");
4782 repeat(4)
4783 begin
4784 pkt.randomize();
4785 $display("\taddr_range = %s addr = %0d",pkt.addr_range,pkt.addr);
4786 end
4787 $display("------------------------------------");
4788 end
4789 endmodule
4790
4791 /*Simulator Output
4792
4793 ------------------------------------
4794 addr_range = small addr = 6
4795 addr_range = small addr = 2
4796 addr_range = small addr = 1
4797 addr_range = small addr = 4
4798 ------------------------------------
4799 */
4800
4801
4802 //IF ELSE CONSTRAINTS
4803 ======================
4804
4805 1. if else block allows conditional executions of constraints.
4806 2. If the expression is true, all the constraints in the first constraint/constraint-block must be satisfied,3.
4807 Otherwise all the constraints in the optional else constraint/constraint-block must be satisfied
4808
4809 IF ELSE CONSTRAINTS EXAMPLE
4810 =============================
4811
4812 Above an example of implication operator usage is written with if else condition
4813
4814 In the example below,
4815
4816 If addr_range == small, then addr will get a value less than 8
4817
4818 class packet;
4819 rand bit [3:0] addr;
4820 string addr_range;
4821
4822 constraint address_range { if(addr_range == "small")
4823 addr < 8;
4824 else
4825 addr > 8;
4826 }
4827 endclass
4828
4829 module constr_if_else;
4830 initial
4831 begin
4832 packet pkt;
4833 pkt = new();
4834 pkt.addr_range = "small";
4835 $display("------------------------------------");
4836 repeat(3)
4837 begin
4838 pkt.randomize();
4839 $display("\taddr_range = %s addr = %0d",pkt.addr_range,pkt.addr);
4840 end
4841 $display("------------------------------------");
4842
4843 pkt.addr_range = "high";
4844 $display("------------------------------------");
4845 repeat(3)
4846 begin
4847 pkt.randomize();
4848 $display("\taddr_range = %s addr = %0d",pkt.addr_range,pkt.addr);
4849 end
4850 $display("------------------------------------");
4851 end
4852 endmodule
4853
4854 /*Simulator Output
4855
4856 ------------------------------------
4857 addr_range = small addr = 1
4858 addr_range = small addr = 4
4859 addr_range = small addr = 6
4860 ------------------------------------
4861 ------------------------------------
4862 addr_range = high addr = 12
4863 addr_range = high addr = 15
4864 addr_range = high addr = 9
4865 ------------------------------------
4866 */
4867
4868 endclass
4869
4870 class //foreach constraint
4871
4872 1. SystemVerilog supports using the foreach loop inside a constraint block
4873 2. Using the foreach loop within the constraint block will make easy to constrain an array
4874 3. The foreach loop iterates over the elements of an array, so constraints with the foreach loop are
4875 called Iterative constraints
4876
4877 4. The foreach constraint will be applicable to an array with one or more than one element
4878 5. So it’s required to_specify or constrain the size of the dynamic array
4879
4880 Syntax
4881 -------
4882
4883 constraint constraint_name { foreach ( variable[iterator] )
4884 variable[iterator] <__conditions__> }
4885
4886 //FOREACH LOOP CONSTRAINT EXAMPLE
4887 ==================================
4888
4889 In the below example,
4890
4891 1. addr and data are the two dynamic arrays
4892 2. The first size of the arrays is constrained
4893 3. and then the values for each array element are constrained using a foreach loop
4894
4895 Constraining array sizes,
4896 ------------------------
4897
4898 constraint asize { addr.size < 4; }
4899 constraint dsize { data.size == addr.size; }
4900
4901 Constraining array elements,
4902 ---------------------------
4903
4904 constraint avalues { foreach ( addr[i] )
4905 addr[i] inside {4,8,12,16}; }
4906
4907 constraint dvalues { foreach ( data[j] )
4908 data[j] > 4 * j; }
4909
4910
4911 class packet;
4912 rand byte addr [];
4913 rand byte data [];
4914
4915 constraint avalues { foreach( addr[i] ) addr[i] inside {4,8,12,16}; }
4916 constraint dvalues { foreach( data[j] ) data[j] > 4 * j; }
4917 constraint asize { addr.size < 4; }
4918 constraint dsize { data.size == addr.size; }
4919 endclass
4920
4921 module constr_iteration;
4922 initial
4923 begin
4924 packet pkt;
4925 pkt = new();
4926
4927 $display("------------------------------------");
4928 repeat(2)
4929 begin
4930 pkt.randomize();
4931 $display("\taddr-size = %0d data-size = %0d",pkt.addr.size(),pkt.data.size());
4932 foreach(pkt.addr[i]) $display("\taddr = %0d data = %0d",pkt.addr[i],pkt.data[i]);
4933 $display("------------------------------------");
4934 end
4935 end
4936 endmodule
4937
4938 /*Simulator Output
4939
4940 ------------------------------------
4941 addr-size = 2 data-size = 2
4942 addr = 4 data = 101
4943 addr = 16 data = 21
4944 ------------------------------------
4945 addr-size = 3 data-size = 3
4946 addr = 16 data = 89
4947 addr = 4 data = 19
4948 addr = 16 data = 13
4949 ------------------------------------
4950 */
4951 endclass
4952
4953 class //DISABLE CONSTRAINTS(constraint_mode())
4954
4955 1. Constraints in a_class can be disabled using the constraint_mode method call
4956 2. By default all the constraints will be enabled,
4957 3. During the randomization constraint solver will not consider the disabled constraints
4958 4. The constraint disables method is similar to rand_mode() method
4959
4960 CONSTRAINT_MODE() METHOD
4961
4962 1. constraint_mode(1) ----> means constraint block is enabled
4963 2. constraint_mode(0) ----> means constraint block is disabled
4964
4965 default value of constraint_mode is 1, i.e enabled
4966
4967 5. once the constraint block is disabled, it is required to make constraint_mode(1) enable back the
4968 constraint block
4969
4970 6. constraint_mode can be called as like SystemVerilog method, which returns the enable/disable status
4971 a constraint block
4972
4973
4974 CONSTRAINT_MODE SYNTAX
4975
4976 <object_hanlde>.<constraint_block_name>.constraint_mode(enable);
4977
4978 //enable == 1, constraint block enable
4979 //enable == 0, constraint block disable
4980
4981
4982 //CONSTRAINT DISABLE EXAMPLES
4983 ===============================
4984
4985 WITHOUT CONSTRAINT DISABLE
4986 ---------------------------
4987
4988 In the below example,
4989 1. The constraint is enabled by default,
4990 2. So on randomization constraint solver will consider the constraint and assigns the random value to
4991 variable addr as per the constraint is written
4992
4993 class packet;
4994 rand bit [3:0] addr;
4995
4996 constraint addr_range { addr inside {5,10}; }
4997 endclass
4998
4999 module static_constr;
5000 initial
5001 begin
5002 packet pkt;
5003 pkt = new();
5004
5005 pkt.randomize();
5006 $display("\taddr = %0d",pkt.addr);
5007 end
5008 endmodule
5009
5010 /*Simulator Output
5011
5012 addr = 5
5013 */
5014
5015 WITH CONSTRAINT DISABLED
5016 -------------------------
5017
5018 1. The constraint is disabled by using the constraint_mode method,
5019 2. So on randomization constraint solver will not consider the constraint
5020
5021 class packet;
5022 rand bit [3:0] addr;
5023
5024 constraint addr_range { addr inside {5,10,15}; }
5025 endclass
5026
5027 module static_constr;
5028 initial
5029 begin
5030 packet pkt;
5031 pkt = new();
5032
5033 $display("Before Constraint disable");
5034 repeat(2)
5035 begin
5036 pkt.randomize();
5037 $display("\taddr = %0d",pkt.addr);
5038 end
5039
5040 //disabling constraint
5041 pkt.addr_range.constraint_mode(0);
5042
5043 $display("After Constraint disable");
5044 repeat(2)
5045 begin
5046 pkt.randomize();
5047 $display("\taddr = %0d",pkt.addr);
5048 end
5049 end
5050 endmodule
5051
5052 /*Simulator Output
5053
5054 Before Constraint disable
5055 addr = 15
5056 addr = 5
5057
5058 After Constraint disable
5059 addr = 9
5060 addr = 14
5061 */
5062
5063 CALLING CONSTRAINT_MODE METHOD
5064 ===============================
5065
5066 In the below example,
5067
5068 Constrain_mode is called as method to see to the enable/disable status of constraint
5069
5070 class packet;
5071 rand bit [3:0] addr;
5072
5073 constraint addr_range { addr inside {5,10,15}; }
5074 endclass
5075
5076 module static_constr;
5077 initial
5078 begin
5079 packet pkt;
5080 pkt = new();
5081
5082 $display("Before Constraint disable");
5083 $display("Value of constraint mode = %0d",pkt.addr_range.constraint_mode());
5084
5085 pkt.randomize();
5086 $display("\taddr = %0d",pkt.addr);
5087
5088 //disabling constraint
5089 pkt.addr_range.constraint_mode(0);
5090
5091 $display("After Constraint disable");
5092 $display("Value of constraint mode = %0d",pkt.addr_range.constraint_mode());
5093
5094 pkt.randomize();
5095 $display("\taddr = %0d",pkt.addr);
5096
5097 end
5098 endmodule
5099
5100 /*Simulator Output
5101
5102 Before Constraint disable
5103 Value of constraint mode = 1
5104
5105 addr = 15
5106
5107 After Constraint disable
5108 Value of constraint mode = 0
5109
5110 addr = 1
5111
5112 */
5113
5114
5115
5116
5117
5118 endclass
5119
5120 class //Static Constraints
5121
5122 1. SystemVerilog static constraints are similar to static .class properties
5123 2. A constraint block can be defined as static by including the static keyword in its definition
5124 3. The static constraint is shared across all the .class instances
5125
5126 4. only the mode change of static constraint will get affected in all the instances of a .class
5127 5. mode change is enable or disable of a constraint by constrain_mode() method
5128
5129 6. a static constraint can be enabled or disabled by any object handle of its .class,
5130 7. mode change with one object handle will reflect all other objects of same .class type
5131
5132 STATIC CONSTRAINT SYNTAX
5133
5134 static constraint constraint_name { ....; }
5135
5136 //STATIC CONSTRAINT EXAMPLES
5137 =============================
5138
5139 TURN OFF NON-STATIC CONSTRAINT
5140 -------------------------------
5141
5142 In the below example,
5143 1. The_class packet has two instances pkt1 and pkt2
5144 2. constraint addr_range is defined to control the value of random variable addr
5145
5146 3. On randomization, pkt1.addr and pkt2.addr will take value based on the constraint
5147
5148 4. The constraint is disabled using a pkt2 handle
5149 5. As constraint is non-static only for pkt2 constraint will get disabled
5150
5151 6. On randomization, pkt1.addr will get value based on the constraint
5152
5153
5154 class packet;
5155 rand bit [7:0] addr;
5156 constraint addr_range { addr == 5; }
5157 endclass
5158
5159 module static_constr;
5160 initial
5161 begin
5162 packet pkt1;
5163 packet pkt2;
5164 pkt1 = new();
5165 pkt2 = new();
5166
5167 $display("Before disabling constraint");
5168 pkt1.randomize();
5169 $display("\tpkt1.addr = %0d",pkt1.addr);
5170 pkt2.randomize();
5171 $display("\tpkt2.addr = %0d",pkt2.addr);
5172
5173 pkt2.addr_range.constraint_mode(0);
5174
5175 $display("After disabling constraint");
5176 pkt1.randomize();
5177 $display("\tpkt1.addr = %0d",pkt1.addr);
5178
5179 pkt2.randomize();
5180 $display("\tpkt2.addr = %0d",pkt2.addr);
5181 end
5182 endmodule
5183 /*Simulator Output
5184
5185 Before disabling constraint
5186
5187 pkt1.addr = 5
5188 pkt2.addr = 5
5189 //only pkt2 disabled
5190 After disabling constraint
5191 pkt1.addr = 5
5192 pkt2.addr = 134
5193
5194 */
5195
5196
5197 TURN OFF STATIC CONSTRAINT
5198 ----------------------------
5199
5200 The example below is the same as the above example,
5201 The only change is the constraint is made as static.
5202
5203 1. The constraint is disabled by using one of the object handles
5204 2. As the constraint is static in nature, the constraint will get disabled for both the objects
5205
5206 class packet;
5207 rand bit [7:0] addr;
5208 static constraint addr_range { addr == 5; }
5209 endclass
5210
5211 module static_constr;
5212 initial
5213 begin
5214 packet pkt1;
5215 packet pkt2;
5216 pkt1 = new();
5217 pkt2 = new();
5218
5219 $display("Before disabling constraint");
5220 pkt1.randomize();
5221 $display("\tpkt1.addr = %0d",pkt1.addr);
5222 pkt2.randomize();
5223 $display("\tpkt2.addr = %0d",pkt2.addr);
5224
5225 pkt2.addr_range.constraint_mode(0);
5226
5227 $display("After disabling constraint");
5228 pkt1.randomize();
5229 $display("\tpkt1.addr = %0d",pkt1.addr);
5230
5231 pkt2.randomize();
5232 $display("\tpkt2.addr = %0d",pkt2.addr);
5233 end
5234 endmodule
5235
5236 /*Simulator Output
5237
5238 Before disabling constraint
5239 pkt1.addr = 5
5240 pkt2.addr = 5
5241
5242 After disabling constraint //Both get disabled
5243 pkt1.addr = 22
5244 pkt2.addr = 134
5245
5246 */
5247 endclass
5248
5249 class //Inline Constraints
5250
5251 1. Constraints will be written inside the_class
5252 2. inline constraint allows the user to add extra constraints to existing constraints written inside
5253 the_class
5254 3. inline constraints will be written outside the_class i.e along with the randomize method call
5255
5256 4. The inline constraint is written using with keyword
5257
5258 during randomization,
5259 5. constraint solver will consider both inline constraints and constraints written inside the_class
5260
5261 6. The inline constraint will not override the constraints written inside the_class
5262 7. The inline constraint shouldn’t conflict with the constraint written inside the_class, else it
5263 will lead to randomization failure
5264
5265 for example, constraint inside the_class written as var < 5,
5266 and inline constraint written as var > 5
5267
5268 INLINE CONSTRAINT SYNTAX
5269 -------------------------
5270
5271 object.randomize() with { .... };
5272
5273 //INLINE CONSTRAINT EXAMPLES
5274 =============================
5275
5276 ONLY INLINE CONSTRAINT
5277 -----------------------
5278
5279 In the below example,
5280
5281 Class doesn’t have constraints defined in it
5282 the inline constraint is used to constrain the variable addr
5283
5284 class packet;
5285 rand bit [3:0] addr;
5286 endclass
5287
5288 module inline_constr;
5289 initial
5290 begin
5291 packet pkt;
5292 pkt = new();
5293
5294 repeat(2)
5295 begin
5296 pkt.randomize() with { addr == 8;};
5297 $display("\taddr = %0d",pkt.addr);
5298 end
5299 end
5300 endmodule
5301 /*Simulator Output
5302
5303 addr = 8
5304 addr = 8
5305 */
5306
5307 CONSTRAINT INSIDE THE CLASS AND INLINE CONSTRAINT
5308 --------------------------------------------------
5309
5310 In the below example,
5311
5312 1. addr and data are the two random variables
5313 2. The constraint for data is written inside the .class
5314 3. The inline constraint is written for addr
5315
5316 Conclusion: Both .class and inline constraints are considered during randomization
5317
5318 class packet;
5319 rand bit [3:0] addr;
5320 rand bit [3:0] data;
5321
5322 constraint data_range { data > 0;
5323 data < 10; }
5324 endclass
5325
5326 module inline_constr;
5327 initial
5328 begin
5329 packet pkt;
5330 pkt = new();
5331 repeat(2)
5332 begin
5333 pkt.randomize() with { addr == 8;};
5334 $display("\taddr = %0d data = %0d",pkt.addr,pkt.data);
5335 end
5336 end
5337 endmodule
5338
5339 /*Simulator Output
5340
5341 addr = 8 data = 2
5342 addr = 8 data = 5
5343 */
5344
5345
5346 CONFLICT WITH INLINE CONSTRAINT
5347 -------------------------------
5348
5349 In the below example,
5350 1. The addr is the random variable
5351 2. constraint inside the .class written as addr < 5
5352 3. inline constraint written as addr > 5.
5353
5354 Conclusion: Conflict between the .class and inline constraints leads to randomization failure
5355
5356 class packet;
5357 rand bit [3:0] addr;
5358 constraint addr_range {addr < 5;};
5359 endclass
5360
5361 module inline_constr;
5362 initial
5363 begin
5364 packet pkt;
5365 pkt = new();
5366 repeat(2)
5367 begin
5368 pkt.randomize() with { addr > 5;};
5369 $display("\taddr = %0d",pkt.addr);
5370 end
5371 end
5372 endmodule
5373 /*Simulator Output
5374
5375 Error-[CNST-CIF] Constraints inconsistency failure
5376 testbench.sv, 15
5377 Constraints are inconsistent and cannot be solved.
5378 Please check the inconsistent constraints being printed above and rewrite
5379 them.
5380 addr = 0
5381 =======================================================
5382 Solver failed when solving following set of constraints
5383 rand bit[3:0] addr; // rand_mode = ON
5384 constraint addr_range // (from this) (constraint_mode = ON) (testbench.sv:7)
5385 {
5386 (addr < 4'h5);
5387 }
5388 constraint WITH_CONSTRAINT // (from this) (constraint_mode = ON) (testbench.sv:15)
5389 {
5390 (addr > 4'h5);
5391 }
5392 =======================================================
5393 */
5394
5395
5396 CLASS AND INLINE CONSTRAINTS FOR THE SAME RANDOM VARIABLE
5397 ----------------------------------------------------------
5398
5399 In the below example,
5400
5401 1. The addr is the random variable
5402 2. constraint inside the_class written as addr between 6:12
5403 3. inline constraint is written as addr == 8
5404
5405 Conclusion: Constraint solver considers both .class and inline constraints
5406
5407 class packet;
5408 rand bit [3:0] addr;
5409
5410 constraint addr_range {addr inside {[6:12]};};
5411 endclass
5412
5413 module inline_constr;
5414 initial
5415 begin
5416 packet pkt;
5417 pkt = new();
5418 repeat(2)
5419 begin
5420 pkt.randomize() with { addr == 8;};
5421 $display("\taddr = %0d",pkt.addr);
5422 end
5423 end
5424 endmodule
5425
5426 /*Simulator Output
5427
5428 addr = 8
5429 addr = 8
5430 */
5431
5432
5433
5434
5435 endclass
5436
5437 class //Soft Constraints
5438
5439 1. SystemVerilog constraints declared with the keyword soft is called as soft constraints
5440
5441 2. Any conflict between class_constraint and inline constraint leads to a randomization failure
5442 from this it is clear that it is not possible to override the class_constraint by inline constraint
5443
5444 3. Some test scenarios demand to override the constraints, this can be done by writing a soft keyword in
5445 class_constraint
5446
5447 4. A soft constraint is a constraint on a random variable, which allows overriding the constraint
5448
5449 SYNTAX:
5450 -------
5451
5452 constraint c_name { soft variable { condition };}
5453
5454 EXAMPLES:
5455 =========
5456
5457
5458 CONFLICT BETWEEN CONSTRAINTS:
5459 =============================
5460
5461 In the example below,
5462 In the class_packet,
5463 1. The addr variable is constrained to greater than 6
5464 2. And the same addr variable is constrained to less than 6 in the inline constraint
5465 3. That means expecting the value of addr to be less than and greater than 6, this is not
5466 possible and leads to a randomization failure
5467 4. This problem is resolved in the next example using soft constraint
5468
5469 class packet;
5470 rand bit [3:0] addr;
5471 constraint addr_range { addr > 6; }
5472 endclass
5473
5474 module soft_constr;
5475 initial
5476 begin
5477 packet pkt;
5478 pkt = new();
5479
5480 repeat(2)
5481 begin
5482 pkt.randomize() with { addr < 6;};
5483 $display("\taddr = %0d",pkt.addr);
5484 end
5485 end
5486 endmodule
5487 /*Simulator Output
5488
5489 Constraints inconsistency failure
5490 Constraints are inconsistent and cannot be solved.
5491 Please check the inconsistent constraints being printed above and rewritethem.
5492 addr = 0
5493
5494 */
5495
5496 USING SOFT CONSTRAINT
5497 ======================
5498 In the example below,
5499 a previous example problem is solved using soft constraints,
5500 Constraint declared inside the class will get suppressed by inline constraints
5501
5502 class packet;
5503 rand bit [3:0] addr;
5504 constraint addr_range { soft addr > 6; }
5505 endclass
5506
5507 module soft_constr;
5508 initial
5509 begin
5510 packet pkt;
5511 pkt = new();
5512
5513 repeat(2)
5514 begin
5515 pkt.randomize() with { addr < 6;};
5516 $display("\taddr = %0d",pkt.addr);
5517 end
5518 end
5519 endmodule
5520 /*Simulator Output
5521
5522 addr = 1
5523 addr = 3
5524 */
5525
5526
5527 endclass
5528 endclass
5529
5530 class //Overriding Constraints
5531
5532 Constraint blocks can be overridden by writing constraint block with the same name as in parent_class
5533
5534 In the example below,
5535 ----------------------
5536
5537 Constraint to an addr > 5 of the parent_class is overridden with constraint addr < 5 in child_class
5538
5539 class packet;
5540 rand bit [3:0] addr;
5541 constraint addr_range { addr > 5; }
5542 // constraint addr_range2{ addr < 5; }
5543 endclass
5544
5545 class packet2 extends packet;
5546 constraint addr_range { addr < 5; } //Override constraint of parent class
5547 endclass
5548
5549 module const_inhe;
5550 initial
5551 begin
5552 packet pkt1;
5553 packet2 pkt2;
5554
5555 pkt1 = new();
5556 pkt2 = new();
5557
5558 $display("------------------------------------");
5559 repeat(5)
5560 begin
5561 pkt1.randomize();
5562 $display("\tpkt1:: addr = %0d",pkt1.addr);
5563 end
5564
5565 $display("------------------------------------");
5566 repeat(5)
5567 begin
5568 pkt2.randomize();
5569 $display("\tpkt2:: addr = %0d",pkt2.addr);
5570 end
5571 $display("------------------------------------");
5572 end
5573 endmodule
5574
5575 /*Simulator Output
5576 ------------------------------------
5577 pkt1:: addr = 14
5578 pkt1:: addr = 10
5579 pkt1:: addr = 9
5580 pkt1:: addr = 8
5581 pkt1:: addr = 9
5582 ------------------------------------
5583 pkt2:: addr = 0
5584 pkt2:: addr = 1
5585 pkt2:: addr = 2
5586 pkt2:: addr = 0
5587 pkt2:: addr = 2
5588 ------------------------------------
5589
5590 */
5591
5592 endclass
5593
5594 class //Inheritance Constraint
5595
5596 Like_class members, constraints also will get inherited from parent_class to child_class
5597
5598 class packet;
5599 rand bit [3:0] addr;
5600 constraint addr_range { addr > 5; }
5601 endclass
5602
5603 class packet2 extends packet;
5604 constraint addr_range_2 { addr < 20; } //Inheritance constraint of parent class
5605 endclass
5606
5607 module const_inhe;
5608 initial
5609 begin
5610 packet pkt1;
5611 packet2 pkt2;
5612
5613 pkt1 = new();
5614 pkt2 = new();
5615
5616 $display("------------------------------------");
5617 repeat(5)
5618 begin
5619 pkt1.randomize();
5620 $display("\tpkt1:: addr = %0d",pkt1.addr);
5621 end
5622
5623 $display("------------------------------------");
5624 repeat(5)
5625 begin
5626 pkt2.randomize();
5627 $display("\tpkt2:: addr = %0d",pkt2.addr);
5628 end
5629 $display("------------------------------------");
5630 end
5631 endmodule
5632
5633 /*Simulator Output
5634
5635 ------------------------------------
5636 pkt1:: addr = 8
5637 pkt1:: addr = 10
5638 pkt1:: addr = 25
5639 pkt1:: addr = 30
5640 pkt1:: addr = 9
5641 ------------------------------------
5642 pkt2:: addr = 8
5643 pkt2:: addr = 19
5644 pkt2:: addr = 12
5645 pkt2:: addr = 15
5646 pkt2:: addr = 10
5647 ------------------------------------
5648
5649 */
5650 endclass
5651
5652 class //unique constraints
5653
5654
5655 1. SystemVerilog constraint defined with the keyword unique is called as a unique constraint
5656 2. On randomization, unique values to set of variables or unique elements to an array can be generated by
5657 using unique constraints
5658
5659 Unique constraint allows us to,
5660
5661 1. Generate unique values across the variables
5662 2. Generate unique elements in an array (Fixed Size Array, Dynamic Array, Associative array and
5663 Queue)
5664
5665 Syntax:
5666 --------
5667 constraint c_name { unique {variable's/array}; }
5668
5669 EXAMPLES:
5670 ==========
5671
5672 UNIQUE ELEMENTS
5673
5674 In the below example,
5675 1. On randomization unique values to a variable var_1, var_2, var_3 can be obtained by writing unique
5676 constraints
5677 2. Also, a unique constraint is written to an array to get unique array elements
5678
5679 class unique_elements;
5680 rand bit [3:0] var_1,var_2,var_3;
5681 rand bit [7:0] array[6];
5682 constraint varis_c {unique {var_1,var_2,var_3};}
5683 constraint array_c {unique {array};}
5684
5685 function void display();
5686 $display("var_1 = %p",var_1);
5687 $display("var_2 = %p",var_2);
5688 $display("var_3 = %p",var_3);
5689 $display("array = %p",array);
5690 endfunction
5691 endclass
5692
5693 program unique_elements_randomization;
5694 unique_elements pkt;
5695
5696 initial
5697 begin
5698 pkt = new();
5699 pkt.randomize();
5700 pkt.display();
5701 end
5702 endprogram
5703
5704 /*Simulator Output
5705
5706 var_1 = 8
5707 var_2 = 14
5708 var_3 = 11
5709 array = '{'h81, 'h7b, 'h4, 'h47, 'he1, 'h17}
5710
5711 */
5712
5713
5714 UNIQUE ARRAY OF ELEMENTS EXAMPLE
5715 ---------------------------------
5716 In below example,
5717 1. Unique elements for an array is generated by using a unique keyword
5718 2. Also considered that the value of elements is less than 10
5719
5720 class unique_elements;
5721 rand bit [31:0] array[10];
5722
5723 constraint array_c {unique {array};
5724 foreach(array[i])
5725 array[i] < 10;}
5726
5727 function void display();
5728 $display("array = %p",array);
5729 endfunction
5730 endclass
5731
5732 program unique_elements_randomization;
5733
5734 unique_elements pkt;
5735
5736 initial
5737 begin
5738 pkt = new();
5739 pkt.randomize();
5740 pkt.display();
5741 end
5742
5743 endprogram
5744
5745 /*Simulator Output
5746
5747 array = '{'h5, 'h7, 'h8, 'h1, 'h6, 'h9, 'h2, 'h3, 'h4, 'h0}
5748
5749 */
5750 endclass
5751
5752 endclass
5753
5754 endclass
5755
5756
5757 ------------------------------------------------------==========--------------------------------------------------
5758 //=====================================================COVERAGE===================================================
5759 ------------------------------------------------------==========--------------------------------------------------
5760 class
5761
5762 COVERAGE is:
5763 1. Defined as the percentage of verification objective that have been met
5764 2. Used as a metric for evaluating the progress of a verification project
5765 3. Used to reduce the number of cycles spent in verifying a design
5766 4. Allow the user to tell how well a design has been tested
5767
5768 There are two types of coverage
5769
5770 Code Coverage:
5771 1. It checks the quality of testbench/inputs
5772 2. Either code is wrong or testbench is wrong
5773 3. Measure how much of the code has been executed
5774 4. Code, Path, Expression, FSM Coverage are type of code coverage
5775
5776 Functional Coverage:
5777 1. User-specified to tie the verification environment to the design intent or functionality
5778 2. Functional coverage goals are derived from the functional specification
5779 3. Functional coverage is not automatically inferred from the design
5780 4. It is user defined model
5781
5782
5783 /*
5784 SystemVerilog Coverage is achieved by doing the following
5785 1. Define a coverage model (covergroup)
5786 2. Define coverage points for the model (coverpoint)
5787 3. Define cross-coverage points between coverage points (cross)
5788 4. Optionally specify coverage point bin for tracking (bins)
5789 5. Place instances of the coverage model in the TB
5790 */
5791 ==============
5792 //COVERGROUP
5793 ==============
5794
5795 -> It is built-in .class
5796 -> The_covergroup construct encapsulate the specification of a coverage model and may contain:
5797 1. A clocking event that synchronizes sampling of points
5798 2. A set of coverage points
5799 3. Cross coverage between coverage points
5800 4. Optional formal arguments
5801
5802 //CREATING COVERGROUP INSTANCES
5803
5804 Example of a_covergroup definition
5805
5806 covergroup cg_group;
5807 <definition of_covergroup>
5808 endgroup: cg_group
5809
5810 1. The_covergroup construct is a user-defined type
5811 2. The type definition is written once
5812 3. Multiple instances of that type can be created in different contexts
5813 _covergroup can be placed inside a module or a named block
5814 4. Syntax for creating_covergroup instances
5815
5816 cg_group = new();
5817
5818
5819 //COVERGROUP EXAMPLE
5820
5821 class example;
5822 logic clk;
5823 logic [7:0] address; ---> implicit bins = 2^8 = 256;
5824 logic [2:0] opcode; ---> implicit bins = 2^3 = 8;
5825 logic valid; ---> implicit bins = 2^1 = 2;
5826
5827 covergroup cg_group;
5828
5829 c1 : coverpoint opcode;
5830 c2 : coverpoint address;
5831
5832 c1_X_val : cross c1,valid;
5833
5834 endgroup: cg_group
5835
5836 function new();
5837 cg_group=new;
5838 endfunction: new
5839
5840 endclass: example
5841
5842 //maximum bins that can be created by default is 64;
5843 //So for accomodate 256 values for address every bin should have 4 vlaues;
5844
5845 ===============
5846 //COVERPOINTS
5847 ===============
5848
5849 -> Coverpoints are the variables you are interested in tracking
5850 -> from these variablers you may be interested in tracking specific values or range of values
5851 -> During simulation the values for variables defined as coverpoints are tracked and stored in coverage
5852 database
5853
5854 Syntax-
5855 ---------
5856
5857 [coverpoint_id : ] coverpoint variable_id;
5858
5859 OR
5860
5861 [coverpoint_id : ] coverpoint variable_id {bins_defn};
5862
5863
5864 Example-
5865 ----------
5866
5867 c1 : coverpoint address;
5868 c2 : coverpoint data;
5869
5870 ==================
5871 //BINS
5872 ==================
5873
5874 ---> bins are the values for the variable we want to tracked
5875 ---> While defining a coverpoint, if you don't.specify any bins
5876 SystemVerilog will automatically create bins
5877
5878 ---> For a variable of M bits the max bins will be bins(N) = 2^M
5879
5880
5881 ==================
5882 //IMPLICIT BINS
5883 ==================
5884 class coverage;
5885
5886 bit [2:0] var1;
5887
5888 covergroup cg_group;
5889 cp_var1 : coverpoint var1;
5890 endgroup : cg_group
5891
5892 function new();
5893 cg_group = new;
5894 endfunction
5895
5896 endclass
5897
5898 //for var1 implicit created bins are 2^3 = 8
5899
5900 bin covered
5901 //coverage % = -------------
5902 total bins
5903
5904 ==================
5905 //EXPLICIT BINS
5906 ==================
5907
5908 We can create,
5909 --> A Seperate bin for each value in a given range list;
5910 --> A Single bin for all values in a range list
5911
5912 class coverage;
5913
5914 bit [2:0] var1;
5915
5916 covergroup cg_group;
5917
5918 cp_var1 : coverpoint var1 {
5919 bins a[] = {[0:1],6}; // 3 bins a[0],a[1],a[6]
5920 bins b[] = {2,3}; // 2 bins b[2],b[3]
5921 bins c = default; // 1 bin for 4,5,7
5922 } // 6 total bins
5923
5924 endgroup
5925
5926
5927 function new();
5928 cg_group = new;
5929 endfunction
5930
5931 endclass
5932
5933 // Whenever we want to track values we declare and default bins should never be tracked
5934
5935 ========================
5936 //BINS: SCALER & VECTOR
5937 ========================
5938
5939 --> There are two types of bins
5940 1. Scaler bins : for all values in the set of values only a single bin is created
5941 2. Vector bins : a unique bin is created for each value
5942
5943
5944
5945 class coverage;
5946
5947 bit [2:0] var1;
5948
5949 covergroup cg_group;
5950
5951 cp_var1 : coverpoint var1 {
5952 bins sca = {0,3,4,6,7}; // 1 bin sca for all (0,3,4,6,7)
5953 bins vec[] = {1,2,5}; // 3 bins vec[1],vec[2],vec[5]
5954 } // 4 total bins
5955
5956 endgroup
5957
5958
5959 function new();
5960 cg_group = new;
5961 endfunction
5962
5963 endclass
5964
5965 //CROSS COVERAGE
5966
5967 1. The cross-coverage allows having a cross product (i.e. cartesian product) between two or more variables.
5968 2. or coverage points within the same .covergroup.
5969 3. In simple words, cross-coverage is nothing but a set of cross-products of variables or coverage points
5970
5971 Syntax:
5972 --------
5973
5974 <cross_coverage_label> : cross <coverpoint_1>, <coverpoint_2>,........., <coverpoint_n>
5975
5976
5977 class coverage;
5978
5979 bit [7:0] addr, data;
5980 bit [3:0] valid;
5981 bit en;
5982
5983 covergroup cg_group @(posedge clk);
5984 cp1: coverpoint addr && en; // labeled as cp1
5985 cp2: coverpoint data; // labeled as cp2
5986 cp1_X_cp2: cross cp1, cp2; // cross coverage between two expressions
5987 valid_X_cp2: cross valid, cp2; // cross coverage between variable and expression
5988 endgroup : cg_group
5989
5990 function new();
5991 cg_group = new;
5992 endfunction
5993
5994 endclass
5995
5996
5997 //BINSOF AND INTERSECT CONSTRUCT IN FUNCTIONAL COVERAGE
5998
5999 //binsof construct in coverage
6000
6001 The binsof construct is used to yield bins of its expression.
6002
6003 Syntax:
6004 ---------
6005
6006 binsof (<expression>)
6007 Where,
6008
6009 An expression can be either a single variable or an explicitly defined coverage point
6010
6011 EXAMPLE:
6012 --------
6013
6014
6015 bit [7:0] var1, var2;
6016
6017 covergroup c_group @(posedge clk);
6018 cp1: coverpoint var1 {
6019 bins x1 = { [0:99] };
6020 bins x2 = { [100:199] };
6021 bins x3 = { [200:255] };
6022 }
6023
6024 cp2: coverpoint var2 {
6025 bins y1 = { [0:74] };
6026 bins y2 = { [75:149] };
6027 bins y3 = { [150:255] };
6028 }
6029
6030 cp1_X_cp2: cross var1, var2 {
6031 bins xy1 = binsof(cp1.x1);
6032 bins xy2 = binsof(cp2.y2);
6033 bins xy3 = binsof(cp1.x1) && binsof(cp2.y2);
6034 bins xy4 = binsof(cp1.x1) || binsof(cp2.y2);
6035 }
6036 endgroup
6037
6038
6039 In the above example,
6040
6041 1. coverage points cp1 and cp2 include a set of cover bins for variables var1 and var2
6042 2. The cp1_X_cp2 denotes the cross product of var1 and var2 with specified cross-bins
6043
6044 3. If no additional cross bins were specified (i.e. cp1_X_cp2: cross var1, var2),
6045 then it would have resulted in 9 cross products listed as:
6046
6047 <x1, y1>, <x1, y2>, <x1, y3>,
6048 <x2, y1>, <x2, y2>, <x2, y3>,
6049 <x3, y1>, <x3, y2>, <x3, y3>,
6050
6051 The cross bin xy1: It results in 3 cross products listed as
6052 <x1, y1>, <x1, y2>, <x1, y3>
6053
6054 The cross bin xy2: It results in 3 cross products listed as
6055 <x1, y2>, <x2, y2>, <x3, y2>
6056
6057 The cross bin xy3: It results in 1 cross-product listed as
6058 <x1, y2>
6059
6060 The cross bin xy4: It results in 5 cross products listed as
6061 <x1, y1>, <x1, y2>, <x1, y3>,
6062 <x2, y2>, <x3, y2>
6063
6064
6065 //INTERSECT CONSTRUCT IN COVERAGE
6066
6067 --> The intersect construct is generally used in conjunction with the binsof construct
6068 --> which is used to exclude or include a set of values of bins that intersect a desired set of values
6069
6070 Syntax:
6071 ---------
6072 binsof(<coverpoint>) intersect {<range of values>}
6073
6074
6075 Meaning:
6076 ----------
6077
6078 bins Description
6079
6080 binsof(cp) intersect {r} ---> The bins of coverpoint cp whose values intersect the range specified by r
6081
6082 !binsof(cp) intersect {r} --> The bins of coverpoint cp whose values do not intersect the range specified by r
6083
6084 Example:
6085
6086 bit [7:0] var1, var2;
6087
6088 covergroup c_group @(posedge clk);
6089 cp1: coverpoint var1 {
6090 bins x1 = { [0:99] };
6091 bins x2 = { [100:199] };
6092 bins x3 = { [200:255] };
6093 }
6094
6095 cp2: coverpoint var2 {
6096 bins y1 = { [0:74] };
6097 bins y2 = { [75:149] };
6098 bins y3 = { [150:255] };
6099 }
6100
6101 cp1_X_cp2: cross var1, var2 {
6102 bins xy1 = binsof(cp1) intersect {[100:200]};
6103 bins xy2 = !binsof(cp1) intersect {[100:200]};
6104 bins xy3 = !binsof(cp1) intersect {99, 125, 150, 175};
6105 }
6106 endgroup
6107
6108 In the above example,
6109
6110 1. coverage points cp1 and cp2 include a set of cover bins for variables var1 and var2
6111 2. The cp1_X_cp2 denotes the cross product of var1 and var2 with specified cross-bins.
6112
6113 3. If no additional cross bins were specified (i.e. cp1_X_cp2: cross var1, var2)
6114 then it would have resulted in 9 cross products listed as:
6115
6116 <x1, y1>, <x1, y2>, <x1, y3>,
6117 <x2, y1>, <x2, y2>, <x2, y3>,
6118 <x3, y1>, <x3, y2>, <x3, y3>
6119
6120 The cross bin xy1: The x2 and x3 of cp1 intersect with value range [100:200]. It results in 6 cross products
6121 listed as
6122
6123 <x2, y1>, <x2, y2>, <x2, y3>,
6124 <x3, y1>, <x3, y2>, <x3, y3>.
6125
6126 The cross bin xy2: The x1 alone do not intersect the value range [100:200]. It results in 3 cross products
6127 listed as
6128
6129 <x1, y1>, <x1, y2>, <x1, y3>
6130
6131 The cross bin xy3: The x3 alone do not intersect with range of values 99, 125, 150, 175. It results in 3
6132 cross products listed as
6133
6134 <x3, y1>, <x3, y2>, <x3, y3>
6135
6136
6137
6138 //EXCLUDING CROSS PRODUCT USING IGNORE_BINS AND ILLEGAL_BINS CONSTRUCT
6139
6140 In the above example, cross-product bins can be excluded as
6141
6142 cp1_X_cp2: cross var1, var2
6143 {
6144 ignore_bins xy1 = binsof(cp1) intersect {[100:200]};
6145 ignore_bins xy2 = !binsof(cp1) intersect {[100:200]};
6146 ignore_bins xy3 = !binsof(cp1) intersect {99, 125, 150, 175};
6147 }
6148
6149 The cross bin xy1: It results into exclusion of 6 cross products listed as
6150 <x2, y1>, <x2, y2>, <x2, y3>,
6151 <x3, y1>, <x3, y2>, <x3, y3>.
6152
6153 The cross bin xy2: It results in the exclusion of 3 cross products listed as
6154 <x1, y1>, <x1, y2>, <x1, y3>
6155
6156 The cross bin xy3: It results in the exclusion of 3 cross products listed as
6157 <x3, y1>, <x3, y2>, <x3, y3>
6158
6159
6160 Similarly, illegal bins can also be specified as
6161
6162 cp1_X_cp2: cross var1, var2
6163 {
6164 illegal_bins xy1 = binsof(cp1) intersect {[100:150]};
6165 illegal_bins xy2 = !binsof(cp1) intersect {[100:150]};
6166 illegal_bins xy3 = !binsof(cp1) intersect {99, 125, 150, 175};
6167 }
6168
6169
6170 endclass
6171
6172
6173
6174 --------------------------------------------------==============--------------------------------------------------
6175 //=================================================TB_COMPONENT===================================================
6176 --------------------------------------------------==============--------------------------------------------------
6177 class
6178
6179 ====================
6180 //RAM_TB_GENERATOR
6181 ====================
6182 class ram_gen;
6183
6184 ram_trans gen_trans;
6185 ram_trans data2send;
6186
6187 mailbox #(ram_trans) gen2rd;
6188 mailbox #(ram_trans) gen2wr;
6189
6190 function new(mailbox #(ram_trans) gen2rd,
6191 mailbox #(ram_trans) gen2wr);
6192 this.gen_trans=new;
6193 this.gen2rd=gen2rd;
6194 this.gen2wr=gen2wr;
6195 endfunction: new
6196
6197
6198 virtual task start();
6199
6200 fork
6201 begin
6202
6203 for(int i=0; i<number_of_transactions;i++)
6204 begin
6205 assert(gen_trans.randomize());
6206 data2send=new gen_trans;
6207 gen2rd.put(data2send);
6208 gen2wr.put(data2send);
6209 end
6210 end
6211 join_none
6212 endtask: start
6213
6214 endclass: ram_gen
6215
6216 =========
6217 //RAM_IF
6218 =========
6219 interface ram_if(input bit clock);
6220
6221 logic [63:0] data_in;
6222 logic [63:0] data_out;
6223 logic [11:0] rd_address;
6224 logic [11:0] wr_address;
6225 logic read;
6226 logic write;
6227
6228 //Write bfm clocking block
6229 clocking wr_drv_cb@(posedge clock);
6230 default input #1 output #1;
6231 output wr_address;
6232 output data_in;
6233 output write;
6234 endclocking: wr_drv_cb
6235
6236 //Read BFM clocking block
6237 clocking rd_drv_cb@(posedge clock);
6238 default input #1 output #1;
6239 output read;
6240 output rd_address;
6241 endclocking: rd_drv_cb
6242
6243 //read minitor clocking block
6244 clocking rd_mon_cb@(posedge clock);
6245 default input #1 output #1;
6246 input read;
6247 input rd_address;
6248 input data_out;
6249 endclocking: rd_mon_cb
6250
6251 //write monitor clocking block
6252 clocking wr_mon_cb@(posedge clock);
6253 default input #1 output #1;
6254 input write;
6255 input wr_address;
6256 input data_in;
6257 endclocking: wr_mon_cb
6258
6259 //Write BFM modport
6260 modport WR_BFM (clocking wr_drv_cb);
6261
6262 //Read BFM modport
6263 modport RD_BFM (clocking rd_drv_cb);
6264
6265 //Write monitor modport
6266 modport WR_MON (clocking wr_mon_cb);
6267
6268 //Read Monitor modport
6269 modport RD_MON (clocking rd_mon_cb);
6270
6271
6272 endinterface: ram_if
6273
6274 ============
6275 //REF_MODEL
6276 ============
6277 class ram_model;
6278
6279 ram_trans mon_data1;
6280 ram_trans mon_data2;
6281
6282
6283 logic [63:0] ref_data[int];
6284
6285 mailbox #(ram_trans) wr2rm;
6286 mailbox #(ram_trans) rd2rm;
6287
6288 mailbox #(ram_trans) rm2sb;
6289
6290 ram_trans rm_data;
6291
6292
6293
6294 function new(mailbox #(ram_trans) wr2rm,
6295 mailbox #(ram_trans) rd2rm,
6296 mailbox #(ram_trans) rm2sb);
6297 this.wr2rm=wr2rm;
6298 this.rd2rm=rd2rm;
6299 this.rm2sb=rm2sb;
6300 endfunction: new
6301
6302 //Understand and include the tasks dual_mem_fun_read and dual_mem_fun_write
6303
6304 task dual_mem_fun_write(ram_trans mon_data1);
6305 begin
6306 if(mon_data1.write)
6307 mem_write(mon_data1);
6308 end
6309 endtask
6310
6311 task dual_mem_fun_read(ram_trans mon_data2);
6312 begin
6313 if(mon_data2.read)
6314 mem_read(mon_data2);
6315 end
6316 endtask
6317
6318 task mem_write(ram_trans mon_data1);
6319 ref_data[mon_data1.wr_address]= mon_data1.data;
6320 endtask:mem_write
6321
6322
6323 task mem_read(inout ram_trans mon_data2);
6324 if(ref_data.exists(mon_data2.rd_address))
6325 mon_data2.data_out = ref_data[mon_data2.rd_address];
6326 endtask: mem_read
6327
6328
6329 virtual task start();
6330 //in fork join_none
6331 fork
6332 begin
6333 fork
6334 begin
6335 forever
6336 begin
6337 wr2rm.get(mon_data1);
6338 dual_mem_fun_write(mon_data1);
6339 end
6340 end
6341
6342 begin
6343 forever
6344 begin
6345 rd2rm.get(mon_data2);
6346 dual_mem_fun_read(mon_data2);
6347 rm2sb.put(mon_data2);
6348 end
6349 end
6350 join
6351 end
6352 join_none
6353 endtask: start
6354
6355 endclass:ram_model
6356
6357 ============
6358 //READ_BFM
6359 ============
6360 class ram_read_bfm;
6361
6362 virtual ram_if.RD_BFM rd_if;
6363 ram_trans data2duv;
6364 mailbox #(ram_trans) gen2rd;
6365
6366 function new(virtual ram_if.RD_BFM rd_if,
6367 mailbox #(ram_trans) gen2rd);
6368 this.rd_if=rd_if;
6369 this.gen2rd=gen2rd;
6370 endfunction: new
6371
6372 virtual task drive();
6373 @(rd_if.rd_drv_cb);
6374 rd_if.rd_drv_cb.rd_address<=data2duv.rd_address;
6375 rd_if.rd_drv_cb.read<=data2duv.read;
6376
6377 repeat(2)
6378 @(rd_if.rd_drv_cb);
6379
6380 rd_if.rd_drv_cb.read<='0;
6381 endtask : drive
6382
6383 virtual task start();
6384 // Within fork join_none
6385 fork
6386 forever
6387 begin
6388 gen2rd.get(data2duv);
6389 drive();
6390 end
6391 join_none
6392 endtask: start
6393
6394 endclass: ram_read_bfm
6395
6396 ============
6397 //READ_MON
6398 ============
6399 class ram_read_mon;
6400
6401 virtual ram_if.RD_MON rdmon_if;
6402
6403 ram_trans data2rm,data2sb;
6404
6405 mailbox #(ram_trans) mon2rm;
6406 mailbox #(ram_trans) mon2sb;
6407
6408 function new(virtual ram_if.RD_MON rdmon_if,
6409 mailbox #(ram_trans) mon2rm,
6410 mailbox #(ram_trans) mon2sb);
6411 this.rdmon_if=rdmon_if;
6412 this.mon2rm=mon2rm;
6413 this.mon2sb=mon2sb;
6414 this.data2rm=new;
6415 endfunction: new
6416
6417
6418 task monitor();
6419
6420 @(rdmon_if.rd_mon_cb);
6421 wait (rdmon_if.rd_mon_cb.read==1);
6422 @(rdmon_if.rd_mon_cb);
6423 begin
6424 data2rm.read = rdmon_if.rd_mon_cb.read;
6425 data2rm.rd_address = rdmon_if.rd_mon_cb.rd_address;
6426 data2rm.data_out= rdmon_if.rd_mon_cb.data_out;
6427
6428 data2rm.display("DATA FROM READ MONITOR");
6429 end
6430
6431 endtask
6432
6433 task start();
6434 fork
6435 forever
6436 begin
6437 monitor();
6438 data2sb= new data2rm;
6439 mon2rm.put(data2rm);
6440 mon2sb.put(data2sb);
6441 end
6442 join_none
6443 endtask: start
6444
6445 endclass:ram_read_mon
6446
6447 ================
6448 //RAM_SCOREBOARD
6449 ================
6450 class ram_sb;
6451
6452 event DONE;
6453
6454 int data_verified = 0;
6455 int rm_data_count = 0;
6456 int mon_data_count = 0;
6457
6458
6459 ram_trans rm_data;
6460
6461 ram_trans rcvd_data;
6462
6463 ram_trans cov_data;
6464
6465 mailbox #(ram_trans) rm2sb; //ref model to sb
6466 mailbox #(ram_trans) rdmon2sb; //mon to sb
6467
6468 covergroup mem_coverage;
6469 option.per_instance=1;
6470
6471
6472 RD_ADD : coverpoint cov_data.rd_address {
6473 bins ZERO = {0};
6474 bins LOW1 = {[1:585]};
6475 bins LOW2 = {[586:1170]};
6476 bins MID_LOW = {[1171:1755]};
6477 bins MID = {[1756:2340]};
6478 bins MID_HIGH = {[2341:2925]};
6479 bins HIGH1 = {[2926:3510]};
6480 bins HIGH2 = {[3511:4094]};
6481 bins MAX = {4095};
6482 }
6483
6484 DATA : coverpoint cov_data.data_out {
6485 bins ZERO = {0};
6486 bins LOW1 = {[1:500]};
6487 bins LOW2 = {[501:1000]};
6488 bins MID_LOW = {[1001:1500]};
6489 bins MID = {[1501:2000]};
6490 bins MID_HIGH = {[2001:2500]};
6491 bins HIGH1 = {[2501:3000]};
6492 bins HIGH2 = {[3000:4293]};
6493 bins MAX = {4294};
6494 }
6495
6496
6497
6498 RD : coverpoint cov_data.read {
6499 bins read = {1};
6500 }
6501
6502
6503 READxADD: cross RD,RD_ADD;
6504
6505
6506 endgroup : mem_coverage
6507
6508 function new(mailbox #(ram_trans) rm2sb,
6509 mailbox #(ram_trans) rdmon2sb);
6510 this.rm2sb = rm2sb;
6511 this.rdmon2sb = rdmon2sb;
6512 mem_coverage = new();
6513 endfunction: new
6514
6515 task start();
6516 fork
6517 while(1)
6518 begin
6519 rm2sb.get(rm_data);
6520 rm_data_count++;
6521
6522 rdmon2sb.get(rcvd_data);
6523 mon_data_count++;
6524
6525 check(rcvd_data);
6526
6527 end
6528 join_none
6529 endtask: start
6530
6531 virtual task check(ram_trans rc_data);
6532 string diff;
6533
6534 if(rc_data.read==1)
6535 begin
6536 if (rc_data.data_out == 0)
6537 $display("SB: Random data not written");
6538 else if(rc_data.read==1 && rc_data.data_out!=0)
6539 begin
6540 if(!rm_data.compare(rc_data,diff))
6541 begin:failed_compare
6542 rc_data.display("SB: Received Data");
6543 rm_data.display("SB: Data sent to DUV");
6544 $display("%s\n%m\n\n", diff);
6545 $finish;
6546 end:failed_compare
6547 else
6548 $display("SB: %s\n%m\n\n", diff);
6549 end
6550
6551 cov_data = rm_data;
6552
6553 mem_coverage.sample();
6554
6555 data_verified++;
6556 if(data_verified >= (number_of_transactions-rc_data.no_of_write_trans))
6557 begin
6558
6559 ->DONE;
6560 end
6561 end
6562 endtask
6563
6564 function void report();
6565 $display(" ------------------------ SCOREBOARD REPORT ----------------------- \n ");
6566 $display(" %0d Read Data Generated, %0d Read Data Recevied, %0d Read Data Verified \n",
6567 rm_data_count,mon_data_count,data_verified);
6568 $display(" ------------------------------------------------------------------ \n ");
6569 endfunction: report
6570
6571
6572 endclass:ram_sb
6573
6574 ============
6575 //RAM_TRANS
6576 ============
6577 class ram_trans;
6578
6579 rand bit[63:0] data;
6580 rand bit[11:0] rd_address;
6581 rand bit[11:0] wr_address;
6582 rand bit read;
6583 rand bit write;
6584
6585 logic [63:0] data_out;
6586
6587 static int trans_id;
6588
6589 static int no_of_read_trans;
6590 static int no_of_write_trans;
6591 static int no_of_RW_trans;
6592
6593 constraint VALID_ADDR {wr_address!=rd_address;}
6594 constraint VALID_CTRL {{read,write}!=2'b00;}
6595 constraint VALID_DATA {data inside {[1:4294]};}
6596
6597 function void post_randomize();
6598 trans_id++;
6599 if(this.read==1 && this.write==0)
6600 no_of_read_trans++;
6601 if(this.write==1 && this.read==0)
6602 no_of_write_trans++;
6603 if(this.read==1 && this.write==1)
6604 no_of_RW_trans++;
6605 this.display("\tRANDOMIZED DATA");
6606
6607 endfunction:post_randomize
6608
6609
6610 function void display(input string message);
6611 $display("=============================================================");
6612 $display("%s",message);
6613 if(message=="\tRANDOMIZED DATA")
6614 begin
6615 $display("\t_______________________________");
6616 $display("\tTransaction No. %d",trans_id);
6617 $display("\tRead Transaction No. %d", no_of_read_trans);
6618 $display("\tWrite Transaction No. %d", no_of_write_trans);
6619 $display("\tRead-Write Transaction No. %d", no_of_RW_trans);
6620 $display("\t_______________________________");
6621 end
6622 $display("\tRead=%d, write=%d",read,write);
6623 $display("\tRead_Address=%d, Write_Address=%d",rd_address, wr_address);
6624 $display("\tData=%d",data);
6625 $display("\tData_out= %d",data_out);
6626 $display("=============================================================");
6627 endfunction: display
6628
6629
6630 //Understand and include the compare method in transaction
6631
6632 function bit compare (input ram_trans rcv,output string message);
6633 compare='0;
6634 begin
6635 if (this.rd_address != rcv.rd_address)
6636 begin
6637 $display($time);
6638 message ="--------- ADDRESS MISMATCH ---------";
6639 return(0);
6640 end
6641
6642 if (this.data_out != rcv.data_out)
6643 begin
6644 $display($time);
6645 message="--------- DATA MISMATCH ---------";
6646 return(0);
6647 end
6648
6649 begin
6650 message=" SUCCESSFULLY COMPARED";
6651 return(1);
6652 end
6653 end
6654 endfunction : compare
6655
6656 endclass:ram_trans
6657
6658 ================
6659 //RAM_WRITE_BFM
6660 ================
6661 class ram_write_bfm;
6662
6663 virtual ram_if.WR_BFM wr_if;
6664
6665 ram_trans data2duv;
6666 mailbox #(ram_trans) gen2wr;
6667
6668 function new(virtual ram_if.WR_BFM wr_if,
6669 mailbox #(ram_trans) gen2wr);
6670 this.wr_if=wr_if;
6671 this.gen2wr=gen2wr;
6672 endfunction: new
6673
6674 virtual task drive();
6675
6676 @(wr_if.wr_drv_cb);
6677 wr_if.wr_drv_cb.data_in<=data2duv.data;
6678 wr_if.wr_drv_cb.wr_address<=data2duv.wr_address;
6679 wr_if.wr_drv_cb.write<=data2duv.write;
6680
6681 repeat(2)
6682 @(wr_if.wr_drv_cb);
6683
6684 wr_if.wr_drv_cb.write<='0;
6685 endtask : drive
6686
6687 virtual task start();
6688
6689 fork
6690 forever
6691 begin
6692 gen2wr.get(data2duv);
6693 drive();
6694 end
6695 join_none
6696 endtask: start
6697
6698 endclass: ram_write_bfm
6699
6700 ================
6701 //RAM_WRITE_MON
6702 ================
6703 class ram_write_mon;
6704
6705 virtual ram_if.WR_MON wrmon_if;
6706
6707 ram_trans data2rm;
6708
6709 mailbox #(ram_trans) mon2rm;
6710
6711 function new(virtual ram_if.WR_MON wrmon_if,
6712 mailbox #(ram_trans) mon2rm);
6713 this.wrmon_if=wrmon_if;
6714 this.mon2rm=mon2rm;
6715 this.data2rm=new;
6716 endfunction: new
6717
6718
6719 task monitor();
6720 @(wrmon_if.wr_mon_cb) //@(posedge clock)
6721 wait(wrmon_if.wr_mon_cb.write==1)
6722 @(wrmon_if.wr_mon_cb);
6723 begin
6724 data2rm.write= wrmon_if.wr_mon_cb.write;
6725 data2rm.wr_address = wrmon_if.wr_mon_cb.wr_address;
6726 data2rm.data= wrmon_if.wr_mon_cb.data_in;
6727
6728 data2rm.display("DATA FROM WRITE MONITOR");
6729
6730 end
6731 endtask
6732
6733 task start();
6734 fork
6735 forever
6736 begin
6737 monitor();
6738 mon2rm.put(data2rm);
6739 end
6740 join_none
6741 endtask: start
6742
6743 endclass:ram_write_mon
6744
6745 ==========
6746 //RAM_ENV
6747 ==========
6748 class ram_env;
6749
6750 virtual ram_if.WR_BFM wr_if;
6751 virtual ram_if.RD_BFM rd_if;
6752 virtual ram_if.WR_MON wrmon_if;
6753 virtual ram_if.RD_MON rdmon_if;
6754
6755
6756 mailbox #(ram_trans) gen2wr=new();
6757 mailbox #(ram_trans) gen2rd=new();
6758
6759 mailbox #(ram_trans) wr2rm=new();
6760 mailbox #(ram_trans) rd2rm=new();
6761
6762 mailbox #(ram_trans) rd2sb=new();
6763
6764 mailbox #(ram_trans) rm2sb=new();
6765
6766
6767 ram_gen gen;
6768 ram_write_bfm wr_bfm;
6769 ram_read_bfm rd_bfm;
6770 ram_write_mon wr_mon;
6771 ram_read_mon rd_mon;
6772 ram_model model;
6773 ram_sb sb;
6774
6775 function new(virtual ram_if.WR_BFM wr_if,
6776 virtual ram_if.RD_BFM rd_if,
6777 virtual ram_if.WR_MON wrmon_if,
6778 virtual ram_if.RD_MON rdmon_if);
6779 this.wr_if = wr_if;
6780 this.rd_if = rd_if;
6781 this.wrmon_if = wrmon_if;
6782 this.rdmon_if = rdmon_if;
6783 endfunction : new
6784
6785
6786 task build;
6787 gen = new(gen2rd, gen2wr);
6788 wr_bfm = new(wr_if,gen2wr);
6789 rd_bfm = new(rd_if, gen2rd);
6790 wr_mon = new(wrmon_if,wr2rm);
6791 rd_mon = new(rdmon_if,rd2rm,rd2sb);
6792 model= new(wr2rm, rd2rm,rm2sb);
6793 sb= new(rm2sb,rd2sb);
6794 endtask : build
6795
6796 task reset_dut();
6797 begin
6798 rd_if.rd_drv_cb.rd_address<='0;
6799 rd_if.rd_drv_cb.read<='0;
6800
6801 wr_if.wr_drv_cb.wr_address<=0;
6802 wr_if.wr_drv_cb.write<='0;
6803
6804 repeat(5) @(wr_if.wr_drv_cb);
6805 for (int i=0; i<4096; i++)
6806 begin
6807 wr_if.wr_drv_cb.write<='1;
6808 wr_if.wr_drv_cb.wr_address<=i;
6809 wr_if.wr_drv_cb.data_in<='0;
6810 @(wr_if.wr_drv_cb);
6811 end
6812 wr_if.wr_drv_cb.write<='0;
6813 repeat (5) @(wr_if.wr_drv_cb);
6814 end
6815 endtask : reset_dut
6816
6817 task start;
6818 gen.start();
6819 wr_bfm.start();
6820 rd_bfm.start();
6821 wr_mon.start();
6822 rd_mon.start();
6823 model.start();
6824 sb.start();
6825 endtask : start
6826
6827 task stop();
6828 wait(sb.DONE.triggered);
6829 endtask : stop
6830
6831 task run();
6832 reset_dut();
6833 start();
6834 stop();
6835 sb.report();
6836 endtask : run
6837
6838 endclass : ram_env
6839
6840 ===========
6841 //RAM_PKG
6842 ===========
6843 package ram_pkg;
6844
6845 int number_of_transactions=1;
6846
6847 `include "ram_trans.sv"
6848 `include "ram_gen.sv"
6849 `include "ram_write_bfm.sv"
6850 `include "ram_read_bfm.sv"
6851 `include "ram_write_mon.sv"
6852 `include "ram_read_mon.sv"
6853 `include "ram_model.sv"
6854 `include "ram_sb.sv"
6855 `include "ram_env.sv"
6856
6857
6858 endpackage
6859
6860 ========
6861 //TEST
6862 ========
6863
6864 import ram_pkg::*;
6865
6866 class test;
6867
6868 virtual ram_if.RD_BFM rd_if;
6869 virtual ram_if.WR_BFM wr_if;
6870 virtual ram_if.RD_MON rdmon_if;
6871 virtual ram_if.WR_MON wrmon_if;
6872
6873 ram_env env;
6874
6875 function new( virtual ram_if.WR_BFM wr_if,
6876 virtual ram_if.RD_BFM rd_if,
6877 virtual ram_if.WR_MON wrmon_if,
6878 virtual ram_if.RD_MON rdmon_if);
6879 this.wr_if = wr_if;
6880 this.rd_if = rd_if;
6881 this.wrmon_if = wrmon_if;
6882 this.rdmon_if = rdmon_if;
6883 env = new(wr_if,rd_if,wrmon_if,rdmon_if);
6884 endfunction
6885
6886 task build_and_run();
6887
6888 begin
6889 number_of_transactions = 10;
6890 env.build();
6891 env.run();
6892 $finish;
6893 end
6894
6895 endtask
6896
6897 endclass
6898
6899 ======
6900 //TOP
6901 ======
6902
6903 `include "test.sv"
6904 module top();
6905
6906 parameter cycle = 10;
6907
6908 reg clock;
6909
6910 ram_if DUV_IF(clock);
6911
6912 test test_h;
6913
6914 ram_4096 RAM (.clk (clock),
6915 .data_in (DUV_IF.data_in),
6916 .data_out (DUV_IF.data_out),
6917 .wr_address (DUV_IF.wr_address),
6918 .rd_address (DUV_IF.rd_address),
6919 .read (DUV_IF.read),
6920 .write (DUV_IF.write)
6921 );
6922
6923 initial
6924 begin
6925 test_h = new(DUV_IF,DUV_IF, DUV_IF, DUV_IF);
6926 test_h.build_and_run();
6927 end
6928
6929
6930 initial
6931 begin
6932 clock=1'b0;
6933 forever #(cycle/2) clock=~clock;
6934 end
6935
6936 endmodule
6937
6938 endclass
6939
6940
6941
6942
6943

You might also like