Puzzles

Que 6: You have two non-uniform threads, each takes 30 mins to burn if we burn it from one side. How will you measure 45 minutes with those two threads without cutting or breaking them?
Ans  6: If we burn it from one side, it will take 30 mins. to burn. So if we burn it from both the side it will burn in 15 mins. So, to measure 45 mins. 1st we will burn one thread from one side for 30 mins and immediately after it we will burn 2nd thread from both sides to measure 15 mins. and thus we can measure 45 mins.  


Que 7: You have 10 packets of chocolate, each packet consists of 10 chocolates. Each chocolate is 10gm except in one packet which has 11gms chocolate each, all the packets look similar. Use a digital weighing machine once to find out which packet has 11 gm of chocolates.
Ans  7: As we can use the weighing machine once, we have to make some combination of the chocolates in such a way that one weigh will tell the packet. One such possible combination is to take 1 chocolate from the 1st packet, 2 chocolate from the 2nd packet, and so on.
So, the total chocolates become 550gm. If 1st packet has the 11gm chocolate the measured weight will be 560gm. Likewise, if the nth packet has 11 gm chocolate measured weight will be (550+10n)gm.


Que 8: If a Pen and a pencil cost Rs 10, if the price of a pen is Rs 9 more than that of a pencil. What is the cost of a pen and pencil? 
Ans  8:
Suppose the price of the Pen is x and the price of the pencil is y.
             By the question  x + y = 10 and x – y = 9
             Solving both equations x(Pen) will be Rs 9.5 and y(Pencil) will be Rs 0.5. 


Que 9: There are 25 horses. You can conduct a race among at most 5 to find out their relative speed. At no point, you can find out the actual speed of the horse in a race. Find out how many races are required to get the top 3 fastest horses.
Ans  9: Make 5 groups of 5 horses and run 5 races. Suppose five groups are a,b,c,d, and e and the next alphabet represents its rank in the group(of 5 horses) eg. d3 means horse in group d and has ranked 3rd in his group. [ 5 RACES DONE ] 
a1 b1 c1 d1 e1 
a2 b2 c2 d2 e2 
a3 b3 c3 d3 e3 
a4 b4 c4 d4 e4 
a5 b5 c5 d5 e5 

Now make a race of (a1,b1,c1,d1,e1).[RACE 6 DONE] suppose result is a1>b1>c1>d1>e1 
which implies a1 must be FIRST. 
b1 and c1 MAY BE(but not must be) 2nd and 3rd. 
For the II positions, the horse will be either b1 or a2.
(we have to find the top 3 horses therefore we choose horses b1,b2,a2,a3, and c1 to race among them [RACE 7 DONE]. 
The only possibilities are : 
c1 may be third 
b1 may be the second or third 
b2 may be third 
a2 may be the second or third 
a3 may be third 
The final result will give ANSWER. suppose result is a2>a3>b1>c1>b2 
then answer is a1,a2,a3,b1,c1. 
HENCE ANSWER is 7 RACES  


Que 10: Prove that the number between 2 consecutive odd prime numbers(eg 17 19), is always divisible by 6.
Ans  10: To prove this, we need to prove that the number between two consecutive odd prime numbers is divisible by 2 and 3.
The number between two odd numbers will be even so it will be divisible by 2.
In each consecutive 3 odd number 1 number is always divisible by 3,  let’s say two consecutive odd prime numbers are n and n+2, then n-2 and n+4 will be divisible by 3 and hence the number between them n+1 will also be divisible by 3.

<< Previous | Next >>

Puzzles

Que 1: There are few bacteria in a bottle which gets double every day. On the 10th day, that bottle gets full. On which day the bottle was one-fourth.
Ans  1:  If the bacteria is double each day and on the 10th day, the bottle is getting full it means, It was half on the 9th day and one-fourth on the 8th day.


Que 2: 100 coins are lying on a table. 10 of them are heads up and 90 are tails up. You can’t see and feel the coins. How can we split the coins into two piles such that there is the same number of heads up in each pile?
Ans  2: We can make 2 piles of 10 and 90. Suppose if x coins are heads and 10-x tails on the 1st pile then it means there are 10-x heads are there in the 2nd pile. If we flip all the coins in 1st pile, then there will be 10-x heads up which will be equal to heads in 2nd pile.


Que 3: Four persons want to cross a bridge. They take 1min., 2min., 5min. and 10min. to cross the bridge respectively. If only two people can cross the bridge at a time and they need a torch. They have only one torch, so each time they cross they have to bring back that torch. Both the person crossing the bridge should have to walk together. In how much minimum time they all will cross the bridge?
Ans  3: Suppose we have persons a, b, c, and d which take 1min., 2min, 5min. and 10min. to cross the bridge respectively. We will follow the following sequence :

a and b cross the bridge:  2min.
a will return back:              1min.
c and d cross the bridge:   10 min.
b will return back:              2min.
a and b cross the bridge:    2min.
So in total 17 min. they all will cross the bridge.


Que 4: There are three closed boxes. There are apples in one box, oranges in 2nd box, and mixed fruit (apple and orange) in 3rd box. By mistakenly the labels of the items are incorrectly tagged on all the boxes. You can draw any one fruit from any box and label them correctly. 
Ans  4: Pick a fruit from the basket labeled ‘Mix fruit’. We know from the question that this basket does not contain ‘Mix fruit’ in that box.

If this fruit is an apple, then label this Basket as ‘Apple’. Now we’ve determined that the basket labeled as ‘Mix fruit’ only contains Apples.

The basket labeled as ‘Oranges’, but we know that since the label is incorrect, this basket either has only apples in it or has Mix fruit. Since we already know which basket contains only apples, we know that the basket labeled as ‘Oranges’ contains ‘Mix fruit’. So label it as ‘Mix fruit’. The 3rd basket will be labeled as ‘Oranges’.


Que 5: There are three persons at different places on a circular track, They start running in a random direction with the same speed, what is the probability that they will not cross each other?
Ans  5:
Each person can run in two directions clockwise or anticlockwise. So, all the people will have 2 options. So there will be a total of 8 possibilities in which they can run. They won’t cross each other if they all run in the same direction clockwise or anticlockwise. So, In 2 cases out of 8, they will not cross, Probability will be 2/8 = ¼.

<< Previous | Next >>

Digital Design

Que 6: What is the range of n bit 2’s complement and 1’s complement representation?

Ans  6: 2’s complement represents an integer in the range [−2n−1, 2n−1 − 1].
        1’s complement represents an integer in the range [−2n−1 + 1, 2n−1 − 1].


Que 7: In which two input gate, If we toggle any one of the inputs toggles the output?

Ans  7: In gray code, only one bit toggles in the next number, for every next number output should toggle, there could be two possibilities.
Refer to Table 1 for Possible solutions at Outputs 1 and 2.
This can be concluded that Output 1 is XOR and Output 2 is XNOR.


Que 8: In 7 input XOR gate, If 4 inputs are 1 and 3 inputs are 0, what will be the output?

Ans  8: In the XOR gate, When Input has even number of 1’s gives output 0 and if Odd number of inputs are 1 then output is 1.
If 4 inputs are 1 and 3 inputs are 0, then output will be 0.


Que 9: Which gates are universal gates? Design XOR gates using NAND gate.

Ans  9: A universal gate is a gate that can implement any Boolean function without the need to use any other gate type. The NAND and NOR gates are universal gates.
Refer to the Figure, for XOR gate implementation from the NAND gate.


Que 10: Implement OR gate using NAND gate.

Ans  10: OR gate can be converted to NAND gate using De Morgan’s theorem.
                A + B  = ((A + B )’)’
                = (A’ . B’)’
                Refer to the Figure, For OR gate using NAND gate implementation.

<< Previous | Next >>

Digital Design

Que 1: Prove that A+A'B = B+B'A = A+B.

Ans 1: A+A'B = (AB' + AB) + A'B
    = AB' + (AB + A'B)
    = AB' + B

A+A'B = (AB' + AB) + A'B
    = AB' + AB + AB + A'B
    = (AB' + AB ) + (AB + A'B)
    = A + B


Que 2: Convert 25.625 fraction decimal numbers into binary number system.

Ans  2: The weights in binary numbers are 25(32), 24(16), 23(8), 22(4), 21(2), 20(1), 2-1(.5), 2-2(.25), 2-3(.125) and so on.
25.625 can be written as 16+8+1+0.5+0.125, If the weight value exists it will
be mentioned as 1 else 0. So, 25.625 can be written as 11001.101.


Que 3: Convert 1011001 in 2’s complement and 1’s complement.

Ans 3: To convert binary numbers into 2’s complement, bits of binary numbers are inverted. So, 1011001 can be represented as 0100110 in 2’s complement.
To convert binary numbers into 1’s complement, Bits of the binary numbers are inverted except the last 1 in the binary number. So, 1011001 can be represented as 0100111 in 1’s complement.
  


Que 4: What is gray code representation and how to convert from binary number to gray code?

Ans  4: Gray code, is an ordering of the binary numeral system such that two successive values differ in only one bit. eg. 00, 01, 11, 10.
This representation can be used to reduce the combinational logic.
Refer the Fig. 1 for Gray code to binary code converter.


Que 5: Convert 10/3 into Base 3 system.

Ans 5: In base 3 system, weights of the number are 34(81), 33(27), 32(9), 31(3), 30(1), 3-1 (1/3), 3-2(1/9) and so on.
10/3 can be written as 9/3 +1/3 = 3 + 1/3, So the Base 3 representation of 10/3 would be 10.1.

<< Previous | Next >>

Queues

A queue is a variable-size, ordered collection of homogeneous elements. A queue supports constant time access to all its elements as well as constant time insertion and removal at the beginning or the end of the queue. Each element in a queue is identified by an ordinal number that represents its position within the queue, with 0 representing the first, and $ representing the last. A queue is analogous to a one-dimensional unpacked array that grows and shrinks automatically. Thus, like arrays, queues can be manipulated using the indexing, concatenation, slicing operator syntax, and equality operators. Queues are declared using the same syntax as unpacked arrays, but specifying $ as the array size. The maximum size of a queue can be limited by specifying its optional right bound (last index).
For example:

byte q1[$]; // A queue of bytes
string names[$] = { "Bob" }; // A queue of strings with one element
integer Q[$] = { 3, 2, 7 }; // An initialized queue of integers
bit q2[$:255]; // A queue whose maximum size is 256 bits

The empty array literal {} is used to denote an empty queue. If an initial value is not provided in the declaration, the queue variable is initialized to the empty queue.

Queue Operators

Queues support the same operations that can be performed on unpacked arrays, and using the same operators and rules except as defined below:

int q_[$] = { 2, 4, 8 };
int p_[$];
int e, pos;

e = q_[0]; // read the first (left-most) item
e = q_[$]; // read the last (right-most) item
q_[0] = e; // write the first item
p_ = q_; // read and write entire queue (copy)
q_ = { q_, 6 }; // insert ’6’ at the end (append 6)
q_ = { e, q_ }; // insert ’e’ at the beginning (prepend e)
q_ = q_[1:$]; // delete the first (left-most) item
q_ = q_[0:$-1]; // delete the last (right-most) item
q_ = q_[1:$-1]; // delete the first and last items
q_ = {}; // clear the queue (delete all items)
q_ = { q_[0:pos-1], e, q_[pos,$] }; // insert ’e’ at position pos
q_ = { q_[0:pos], e, q_[pos+1,$] }; // insert ’e’ after position pos

Unlike arrays, the empty queue, {}, is a valid queue and the result of some queue operations. The following rules govern queue operators:

  • Q[ a : b ] yields a queue with b – a + 1 elements.
  • If a > b then Q[a:b] yields the empty queue {}.
  • Q[ n : n ] yields a queue with one item, the one at position n. Thus, Q[ n : n ] === { Q[n] }.
  • If n lies outside Q’s range (n < 0 or n > $) then Q[n:n] yields the empty queue {}.
  • If either a or b are 4-state expressions containing X or Z values, it yields the empty queue {}.
  • Q[ a : b ] where a < 0 is the same as Q[ 0 : b ].
  • Q[ a : b ] where b > $ is the same as Q[ a : $ ].

Queue methods

In addition to the array operators, queues provide several built-in methods.

size()

The prototype for the size() method is:
function int size();

The size() method returns the number of items in the queue. If the queue is empty, it returns 0.

for ( int j = 0; j < q.size; j++ ) $display( q[j] );

insert()

The prototype of the insert() method is:
function void insert(int index, queue_type item);

The insert() method inserts the given item at the specified index position.

  • Q.insert(i, e) is equivalent to: Q = {Q[0:i-1], e, Q[i,$]}

delete()

The prototype of the delete() method is:
function void delete(int index);

The delete() method deletes the item at the specified index position.

  • Q.delete(i) is equivalent to: Q = {Q[0:i-1], Q[i+1,$]}

pop_front()

The prototype of the pop_front() method is:
function queue_type pop_front();

The pop_front() method removes and returns the first element of the queue.

              e = Q.pop_front() is equivalent to: e = Q[0]; Q = Q[1,$]

pop_back()

The prototype of the pop_back() method is:
function queue_type pop_back();

The pop_back() method removes and returns the last element of the queue.

e = Q.pop_back() is equivalent to: e = Q[$]; Q = Q[0,$-1]

push_front()

The prototype of the push_front() method is:
function void push_front(queue_type item);

The push_front() method inserts the given element at the front of the queue.

Q.push_front(e) is equivalent to: Q = {e, Q}

push_back()

The prototype of the push_back() method is:
function void push_back(queue_type item);

The push_back() method inserts the given element at the end of the queue.

  • Q.push_back(e) is equivalent to: Q = {Q, e}

<< Previous | Next >>

Associative arrays

When the size of the collection is unknown or the data space is sparse, an associative array is a better option. Associative arrays do not have any storage allocated until it is used, and the index expression is not restricted to integral expressions but can be of any type.
An associative array implements a lookup table of the elements of its declared type. The data type to be used as an index serves as the lookup key, and imposes an ordering.

The syntax to declare an associative array is:

data_type array_id [ index_type ];

where:

  • data_type is the data type of the array elements. Can be any type allowed for fixed-size arrays.
  • array_id is the name of the array being declared.
  • index_type is the data type to be used as an index, or *. If * is specified, then the array is indexed by any

integral expression of arbitrary size. An index type restricts the indexing expressions to a particular type.

Examples of associative array declarations are:

integer i_array[*]; // associative array of integer (unspecified index)
bit [20:0] array_b[string]; // associative array of 21-bit vector, indexed by string
event ev_array[myClass]; // associative array of event indexed by class myClass

Array elements in associative arrays are allocated dynamically; an entry is created the first time it is written. The associative array maintains the entries that have been assigned values and their relative order according to the index data type. Associative array elements are unpacked, meaning that other than copying or comparing arrays, you must select an individual element out of the array before using it in most expressions.

Wildcard index type

Example: int array_name [*];

Associative arrays that specify a wildcard index type have the following properties:

  • The array can be indexed by any integral data type. Since the indices can be of different sizes, the same numerical value can have multiple representations, each of a different size. SystemVerilog resolves this ambiguity by detecting the number of leading zeros and computing a unique length and representation for every value.
  • Non-integral index types are illegal and result in a type check error.
  • A 4-state Index containing X or Z is invalid.
  • Indices are unsigned.
  • Indexing expressions are self-determined; signed indices are not sign extended.
  • A string literal index is auto-cast to a bit-vector of equivalent size.
  • The ordering is numerical (smallest to largest).

String index

Example: int array_name [ string ];

Associative arrays that specify a string index have the following properties:

  • Indices can be strings or string literals of any length. Other types are illegal and shall result in a type check error.
  • An empty string “” index is valid.
  • The ordering is lexicographical (lesser to greater).

Class index

Example: int array_name [ some_Class ];

Associative arrays that specify a class index have the following properties:

  • Indices can be objects of that particular type or derived from that type. Any other type is illegal and shall result in a type check error.
  • A null index is valid.
  • The ordering is deterministic but arbitrary.

Integer (or int) index

Example: int array_name [ integer ];

Associative arrays that specify an integer index have the following properties:

  • Indices can be any integral expression.
  • Indices are signed.
  • A 4-state index containing X or Z is invalid.
  • Indices smaller than integer are sign extended to 32 bits.
  • Indices larger than integer are truncated to 32 bits.
  • The ordering is signed numerical.

Signed packed array

Example: typedef bit signed [4:1] Nibble;

int array_name [ Nibble ];

Associative arrays that specify a signed packed array index have the following properties:

  • Indices can be any integral expression.
  • Indices are signed.
  • Indices smaller than the size of the index type are sign extended.
  • Indices larger than the size of the index type are truncated to the size of the index type.
  • The ordering is signed numerical.

Unsigned packed array or packed struct

Example: typedef bit [4:1] Nibble;

int array_name [ Nibble ];

Associative arrays that specify an unsigned packed array index have the following properties:

  • Indices can be any integral expression.
  • Indices are unsigned.
  • A 4-state Index containing X or Z is invalid.
  • Indices smaller than the size of the index type are zero filled.
  • Indices larger than the size of the index type are truncated to the size of the index type.
  • The ordering is numerical

Associative array methods

In addition to the indexing operators, several built-in methods are provided that allow users to analyze and manipulate associative arrays, as well as iterate over its indices or keys.

num()

The syntax for the num() method is:
function int num();

The num() method returns the number of entries in the associative array. If the array is empty, it returns 0.

int imem[*];
imem[ 2’b3 ] = 1;
imem[ 16’hffff ] = 2;
imem[ 4b’1000 ] = 3;
$display( "%0d entries\n", imem.num );
// prints “3 entries”

delete()

The syntax for the delete() method is:
function void delete( [input index] );

Where index is an optional index of the appropriate type for the array in question. If the index is specified, then the delete() method removes the entry at the specified index. If the entry to be deleted does not exist, the method issues no warning.

If the index is not specified, then the delete() method removes all the elements in the array.

int map[ string ];
map[ "hello" ] = 1;
map[ "sad" ] = 2;
map[ "world" ] = 3;

map.delete( "sad" ); // remove entry whose index is “sad” from “map”
map.delete; // remove all entries from the associative array “map”

exists()

The syntax for the exists() method is:
function int exists( input index );

Where index is an index of the appropriate type for the array in question. The exists() function checks if an element exists at the specified index within the given array. It returns 1 if the element exists, otherwise it returns 0.

if ( map.exists( "hello" ))
map[ "hello" ] += 1;
else
map[ "hello" ] = 0;

first()

The syntax for the first() method is:
function int first( ref index );

Where index is an index of the appropriate type for the array in question. The first() method assigns to the given index variable the value of the first (smallest) index in the associative array. It returns 0 if the array is empty, and 1 otherwise.

string s;
if ( map.first( s ) )
$display( "First entry is : map[ %s ] = %0d\n", s, map[s] );

last()

The syntax for the last() method is:
function int last( ref index );

Where index is an index of the appropriate type for the array in question. The last() method assigns to the given index variable the value of the last (largest) index in the associative array. It returns 0 if the array is empty, and 1 otherwise.

string s;
if ( map.last( s ) )
$display( "Last entry is : map[ %s ] = %0d\n", s, map[s] );

next()

The syntax for the next() method is:
function int next( ref index );

Where index is an index of the appropriate type for the array in question. The next() method finds the entry whose index is greater than the given index. If there is a next entry, the index variable is assigned the index of the next entry, and the function returns 1. Otherwise, the index is unchanged, and the function returns 0.

string s;
if ( map.first( s ) )
do
$display( "%s : %d\n", s, map[ s ] );
while ( map.next( s ) );

prev()

The syntax for the prev() method is:
function int prev( ref index );

Where index is an index of the appropriate type for the array in question. The prev() function finds the entry whose index is smaller than the given index. If there is a previous entry, the index variable is assigned the index of the previous entry, and the function returns 1. Otherwise, the index is unchanged, and the function returns 0.

string s;
if ( map.last( s ) )
do
$display( "%s : %d\n", s, map[ s ] );
while ( map.prev( s ) );

If the argument passed to any of the four associative array traversal methods first, last, next, and prev are smaller than the size of the corresponding index, then the function returns –1 and shall copy only as much data as can fit into the argument. For example:

string aa[*];
byte ix;
int status;
aa[ 1000 ] = "a";
status = aa.first( ix );

// status is –1
// ix is 232 (least significant 8 bits of 1000)

<< Previous | Next >>

Dynamic arrays

A dynamic array is one dimension of an unpacked array whose size can be set or changed at runtime. The space for a dynamic array doesn’t exist until the array is explicitly created at runtime.
The syntax to declare a dynamic array is:

data_type array_name [];

where data_type is the data type of the array elements. Dynamic arrays support the same types as fixed-size arrays.
For example:

bit [3:0] nibble[]; // Dynamic array of 4-bit vectors
integer mem[]; // Dynamic array of integers

The new[] operator is used to set or change the size of the array.
The size() built-in method returns the current size of the array.
The delete() built-in method clears all the elements yielding an empty array (zero size).

new[]

The built-in function new allocates the storage and initializes the newly allocated array elements either to their default initial value or to the values provided by the optional argument.

size()

The prototype for the size() method is:
function int size();

The size() method returns the current size of a dynamic array, or zero if the array has not been created.

int j = addr.size;

addr = new[ addr.size() * 4 ] (addr); // quadruple addr array

Note: The size method is equivalent to $length( addr, 1 ).

delete()

The prototype for the delete() method is:
function void delete();

The delete() method empties the array, resulting in a zero-sized array.

int ab [] = new[ N ]; // create a temporary array of size N

ab.delete; // delete the array contents

$display( "%d", ab.size ); // prints 0

Array assignment

Assigning to a fixed-size unpacked array requires that the source and the target both be arrays with the same number of unpacked dimensions and the length of each dimension be the same. The assignment is done by assigning each element of the source array to the corresponding element of the target array, which requires that the source and target arrays be of compatible types. Compatible types are types that are assignment-compatible.

Assigning fixed-size unpacked arrays of unequal size to one another shall result in a type check error.

int A[10:1]; // fixed-size array of 10 elements

int B[0:9]; // fixed-size array of 10 elements

int C[24:1]; // fixed-size array of 24 elements

A = B; // ok. Compatible type and same size

A = C; // type check error: different sizes

An array of wires can be assigned to an array of variables having the same number of unpacked dimensions and the same length for each of those dimensions, and vice-versa.

wire [31:0] W [9:0];
assign W = A;
initial #10 B = W;

A dynamic array can be assigned to a one-dimensional fixed-size array of a compatible type if the size of the dynamic array is the same as the length of the fixed-size array dimension. Unlike assigning with a fixed-size array, this operation requires a run-time check that can result in an error.

int A[100:1]; // fixed-size array of 100 elements
int B[] = new[100]; // dynamic array of 100 elements
int C[] = new[8]; // dynamic array of 8 elements
A = B; // OK. Compatible type and same size
A = C; // type check error: different sizes

A dynamic array or a one-dimensional fixed-size array can be assigned to a dynamic array of a compatible type. In this case, the assignment creates a new dynamic array with a size equal to the length of the fixed-size array. For example:

int A[100:1]; // fixed-size array of 100 elements
int B[]; // empty dynamic array
int C[] = new[8]; // dynamic array of size 8
B = A; // ok. B has 100 elements
B = C; // ok. B has 8 elements

The last statement above is equivalent to:

B = new[ C.size ] (C);

Similarly, the source of an assignment can be a complex expression involving array slices or concatenations.
For example:

string d[1:5] = { "a", "b", "c", "d", "e" };
string p[];
p = { d[1:3], "hello", d[4:5] };

The preceding example creates the dynamic array p with contents: “a”, “b”, “c”, “hello”, “d”, “e”.

Arrays as arguments

Arrays can be passed as arguments to tasks or functions. The rules that govern array argument passing by value are the same as for array assignment. When an array argument is passed by value, a copy of the array is passed to the called task or function. This is true for all array types: fixed-size, dynamic, or associative.

Note that unsized dimensions can occur in dynamic arrays and in formal arguments of import DPI functions. If one dimension of a formal is unsized, then any size of the corresponding dimension of an actual is accepted.

For example, the declaration:

task fun(int a[3:1][3:1]);

declares task fun that takes one argument, a two-dimensional array with each dimension of size three. A call to fun must pass a two-dimensional array and with the same dimension size 3 for all the dimensions. For example,

given the above description for fun, consider the following actuals:

int b[3:1][3:1]; // OK: same type, dimension, and size

int b[1:3][0:2]; // OK: same type, dimension, & size (different ranges)

reg b[3:1][3:1]; // OK: assignment compatible type

event b[3:1][3:1]; // error: incompatible type

int b[3:1]; // error: incompatible number of dimensions

int b[3:1][4:1]; // error: incompatible size

A subroutine that accepts a dynamic array can be passed a dynamic array of a compatible type or a one-dimensional fixed-size array of a compatible type

For example, the declaration:

task ABC( string arr[] );

declares a task that accepts one argument, a dynamic array of strings. This task can accept any one-dimensional array of strings or any dynamic array of strings.

An import DPI function that accepts a one-dimensional array can be passed a dynamic array of a compatible type and of any size if formal is unsized, and of the same size if formal is sized. However, a dynamic array cannot be passed as an argument if formal is an unsized output.

<< Previous | Next >>

Arrays

Introduction

An array is a collection of variables, all of the same type, and accessed using the same name plus one or more indices.

In Verilog-2001, arrays are indexed from left-bound to right-bound. If they are vectors, they can be assigned as a single unit, but not if they are arrays. Verilog-2001 allows multiple dimensions.

In Verilog-2001, all data types can be declared as arrays. The reg, wire and all other net types can also have a vector width declared. A dimension declared before the object name is referred to as the “vector width” dimension.

The dimensions declared after the object name are referred to as the “array” dimensions.

reg [7:0] r1 [1:256]; // [7:0] is the vector width, [1:256] is the array size

SystemVerilog uses the term “packed array” to refer to the dimensions declared before the object name (what Verilog-2001 refers to as the vector width). The term “unpacked array” is used to refer to the dimensions declared after the object name.

bit [7:0] c1; // packed array

real u [7:0]; // unpacked array

SystemVerilog enhances packed arrays by allowing multiple dimensions. SystemVerilog adds the ability to procedurally change the size of one of the dimensions of an unpacked array. Fixed-size unpacked arrays can be multi-dimensional and have fixed storage allocated for all the elements of the array. Each dimension of an unpacked array can be declared as having a fixed or un-fixed size.

A dynamic array allocates storage for elements at runtime along with the option of changing the size of one of its dimensions.

An associative array allocates storage for elements individually as they are written. Associative arrays can be indexed using arbitrary data types.

A queue type of array grows or shrinks to accommodate the number of elements written to the array at runtime.

Packed and unpacked arrays

A packed array is a mechanism for subdividing a vector into subfields which can be conveniently accessed as array elements. Consequently, a packed array is guaranteed to be represented as a contiguous set of bits.

An unpacked array may or may not be so represented. A packed array differs from an unpacked array in that when a packed array appears as a primary, it is treated as a single vector.

If a packed array is declared as signed, then the array viewed as a single vector shall be signed. The individual elements of the array are unsigned unless they are of a named type declared as signed. A part-select of a packed array shall be unsigned.

Packed arrays allow arbitrary length integer types, so a 48 bits integer can be made up of 48 bits. These integers can then be used for 48 bits arithmetic. The maximum size of a packed array can be limited but shall be at least 65536 (216) bits.

Packed arrays can only be made of the single bit types (bit, logic, reg, wire, and the other net types) and recursively other packed arrays and packed structures.

Integer types with predefined widths cannot have packed array dimensions declared. These types are byte, shortint, int, longint, and integer. An integer type with a predefined width can be treated as a single-dimension packed array. The packed dimensions of these integer types shall be numbered down to 0, such that the right-most index is 0.

byte c2; // same as bit [7:0] c2;

integer i1; // same as logic signed [31:0] i1;

Unpacked arrays can be made of any type. System Verilog enhances fixed-size unpacked arrays in that in addition to all other variable types, unpacked arrays can also be made of object handles and events.

System Verilog accepts a single number, as an alternative to a range, to specify the size of an unpacked array, like C. That is, [size] becomes the same as [0:size-1]. For example:

int Array[8][32]; is the same as: int Array[0:7][0:31];

The following operations can be performed on all arrays, packed or unpacked. The examples provided with these rules assume that A and B are arrays of the same shape and type.

  • Reading and writing the array, e.g., A = B
  • Reading and writing a slice of the array, e.g., A[i:j] = B[i:j]
  • Reading and writing a variable slice of the array, e.g., A[x+:c] = B[y+:c]
  • Reading and writing an element of the array, e.g., A[i] = B[i]
  • Equality operations on the array or slice of the array, e.g. A==B, A[i:j] != B[i:j]

The following operations can be performed on packed arrays, but not on unpacked arrays. The examples provided with these rules assume that A is an array.

  • Assignment from an integer, e.g., A = 8’b11111111;
  • Treatment as an integer in an expression, e.g., (A + 3)

If an unpacked array is declared as signed, then this applies to the individual elements of the array, since the whole array cannot be viewed as a single vector.

When assigning to an unpacked array, the source and target must be arrays with the same number of unpacked dimensions, and the length of each dimension must be the same. Assignment to an unpacked array is done by assigning each element of the source unpacked array to the corresponding element of the target unpacked array. Note that an element of an unpacked array can be a packed array.

For the purposes of assignment, a packed array is treated as a vector. Any vector expression can be assigned to any packed array. The packed array bounds of the target packed array do not affect the assignment. A packed array cannot be directly assigned to an unpacked array without an explicit cast.

Multiple dimensions

Like Verilog memories, the dimensions following the type set the packed size. The dimensions following the instance set the unpacked size.

bit [3:0] [7:0] john [1:10]; // 10 entries of 4 bytes (packed into 32 bits)

can be used as follows:

john[9] = john[8] + 1; // 4 byte add
john[7][3:2] = john[6][1:0]; // 2 byte copy

<< Previous | Next >>

Casting

A data type can be changed by using a cast ( ) operation. The expression to be cast must be enclosed in parentheses or within concatenation or replication braces and is self-determined.

int’(2.0 * 3.0)
shortint’{8’hFA,8’hCE}

A positive decimal number as a data type means a number of bits to change the size.

17’(x - 2)

The signedness can also be changed.

signed’(x)

A user-defined type can be used.

mytype’(x)

The expression inside the cast must be an integral value when changing the size or sign. When changing the size, the sign passes through unchanged. When changing the sign, the size passes through unchanged. When casting to a predefined type, the prefix of the cast must be the predefined type keyword. When casting to a user-defined type, the prefix of the cast must be the user-defined type identifier.

When a shortreal is converted to an int or to 32 bits, its value is rounded, as in Verilog. Therefore, the conversion can lose information. To convert a shortreal to its underlying bit representation without a loss of information, use $shortrealtobits. To convert from the bit representation of a shortreal value into a shortreal, use $bitstoshortreal.

Structures can be converted to bits preserving the bit pattern, which means they can be converted back to the same value without any loss of information. When unpacked data is converted to the packed representation, the order of the data in the packed representation is such that the first field in the structure occupies the most significant bits. The effect is the same as a concatenation of the data items (struct fields or array elements) in order. The type of the elements in an unpacked structure or array must be valid for a packed representation in order to be cast to any other type, whether packed or unpacked.

The following example demonstrates how the $bits attribute is used to obtain the size of a structure in bits which facilitates the conversion of the structure into a packed array:

typedef struct {
bit isfloat;
union { int i; shortreal f; } n;
// anonymous type
} tagged_st; // named structure
typedef bit [$bits(tagged_st) - 1 : 0] tagbits; // tagged_st defined above
tagged_st a [7:0]; // unpacked array of structures
tagbits t = tagbits’(a[3]); // convert structure to array of bits
a[4] = tagged_st’(t); // convert array of bits back to structure

Note that the bit data type loses X values. If these are to be preserved, the logic type should be used instead.

The size of a union in bits is the size of its largest member. The size of a logic in bits is 1.

For compatibility, the Verilog functions $itor, $rtoi, $bitstoreal, $realtobits, $signed, $unsigned can also be used.

$cast dynamic casting

SystemVerilog provides the $cast system task to assign values to variables that might not ordinarily be valid because of differing data type. $cast can be called as either a task or a function.

The syntax for $cast is:

function int $cast( singular dest_var, singular source_exp );
or
task $cast( singular dest_var, singular source_exp );

The dest_var is the variable to which the assignment is made.
The source_exp is the expression that is to be assigned to the destination variable.

Use of $cast as either a task or a function determines how invalid assignments are handled.

When called as a task, $cast attempts to assign the source expression to the destination variable. If the assignment is invalid, a runtime error occurs and the destination variable is left unchanged.

When called as a function, $cast attempts to assign the source expression to the destination variable, and returns 1 if the cast is legal. If the cast fails, the function does not make the assignment and returns 0. When called as a function, no runtime error occurs, and the destination variable is left unchanged.

It’s important to note that $cast performs a run-time check. No type checking is done by the compiler, except to check that the destination variable and source expression are singulars.

Example:

typedef enum { red, green, blue, yellow, white, black } Colors;
Colors col;
$cast( col, 2 + 3 );

This example assigns the expression (5 => black) to the enumerated type. Without $cast, or the static compile-time cast described below, this type of assignment is illegal.

The following example shows how to use the $cast to check if an assignment will succeed:

if ( ! $cast( col, 2 + 8 ) ) // 10: invalid cast

$display( "Error in cast" );

Alternatively, the preceding examples can be cast using a static SystemVerilog cast operation:
Example:

col = Colors’(2 + 3);

However, this is a compile-time cast, i.e, a coercion that always succeeds at run-time, and does not provide for error checking or warn if the expression lies outside the enumeration values.

Allowing both types of casts gives full control to the user. If users know that it is safe to assign certain expressions to an enumerated variable, the faster static compile-time cast can be used. If users need to check if the expression lies within the enumeration values, it is not necessary to write a lengthy switch statement manually, the compiler automatically provides that functionality via the $cast function. By allowing both types of casts, users can control the time/safety trade-offs.

Bit-stream casting

Type casting can also be applied to unpacked arrays and structs. It is thus possible to convert freely between bit-stream types using explicit casts. Types that can be packed into a stream of bits are called bit-stream types.
A bit-stream type is a type consisting of the following:

  • Any integral, packed, or string type
  • Unpacked arrays, structures, or classes of the above types
  • Dynamically-sized arrays (dynamic, associative, or queues) of any of the above types

This definition is recursive, for example, a structure containing a queue of int is a bit-stream type.
Assuming A is of bit-stream type source_t and B is of bit-stream type dest_t, it is legal to convert A into B by an explicit cast:

B = dest_t’(A);

The conversion from A of type source_t to B of type dest_t proceeds in two steps:

1) Conversion from source_t to a generic packed value containing the same number of bits as source_t. If source_t contains any 4-state data, the entire packed value is 4-state; otherwise, it is 2-state.

2) Conversion from the generic packed value to dest_t. If the generic packed value is a 4-state type and parts of dest_t designate 2-state types then those parts in dest_t are assigned as if cast to a 2-state.

If both source_t and dest_t are fixed-sized unpacked types of different sizes then a cast generates a compile-time error. If source_t or dest_t contain dynamically-sized types then a difference in their sizes will generate an error either at compile time or run time, as soon as it is possible to determine the size mismatch.

For example:

// Illegal conversion from 24-bit struct to int (32 bits) – compile time error
struct {bit[7:0] a; shortint b;} a;
int b = int’(a);

// Illegal conversion from 20-bit struct to int (32 bits) – run time error
struct {bit a[$]; shortint b;} a = {{1,2,3,4}, 67};
int b = int’(a);

// Illegal conversion from int (32 bits) to struct dest_t (25 or 33 bits),
// compile time error
typedef struct {byte a[$]; bit b;} dest_t;
int a;
dest_t b = dest_t’(a);

<< Previous | Next >>

Class

A class is a collection of data and a set of subroutines that operate on that data. The data in a class are referred to as class properties, and its subroutines are called methods. The class properties and methods, taken together, define the contents and capabilities of a class instance or object.

class_declaration ::=

[ virtual ] class [ lifetime ] class_identifier [ parameter_port_list ] [ extends class_type [ ( list_of_arguments ) ] ];

{ class_item }

endclass [ : class_identifier]

The object-oriented class extension allows objects to be created and destroyed dynamically. Class instances, or objects, can be passed around via object handles, which add a safe-pointer capability to the language. An object can be declared as an argument with direction input, output, inout, or ref. In each case, the argument copied is the object handle, not the contents of the object.

A Class is declared using the classendclass keywords. For example:

class Packet;

    int address; // Properties are address, data, and crc

    bit [63:0] data;

    shortint crc;

    Packet next; // Handle to another Packet

    function new(); // Methods are send and new

    function bit send();

endclass : Packet

<< Previous | Next >>