Site icon Hardware Design and Verification

Sytem Verilog Questions and Answer Part1

What is the difference between a reg, wire and logic in SystemVerilog?
reg and wire are two data types that existed from Verilog, while logic is a new data type that was introduced in SystemVerilog.
1) A wire is a data type that can model physical wires to connect two elements.
Wires can only be driven by continuous assignment statement and cannot hold onto value if not driven. Wires can hence only be used to model combinational logic.
2) A reg is a data type that can model a storage element or a state. They need to be driven by an always block and cannot be driven by continuous assignment
statement. A reg can be used to model both sequential and combinational logic
3) A logic is a new data type in SystemVerilog that can be used to model both
wires and state information (reg). It also is a 4 state variable and hence can hold 0, 1, x and z values. If a wire is declared as a logic (wire logic), then it can be used to model multiple drivers and the last assignment will take the value.
What is the difference between a bit and logic data type?
bit is a 2-state data type that can take only values 0 and 1, while logic is a 4-state data type which can take values 0, 1, x, and z. 2-state variables will help in a small simulation speed up but should not be used if it is used to drive or sample signals from RTL design in which uninitialized and unknown
values will be missed.
What is the difference between logic[7:0] and byte variable in SystemVerilog?
byte is a signed variable which means it can only be used to count values till 127. A logic [7:0] variable can be used for an unsigned 8 bit variable that can count up to 255.
Which of the array types: dynamic array or associative array, are good to model really large arrays, say: a huge memory array of 64KB?
Associative arrays are better to model large arrays as memory is allocated only when an entry is written into the array. Dynamic arrays on the other hand need memory to be allocated and initialized before using.
For example: If you want a memory array of 64KB to be modelled using dynamic array, you would first need to allocate 64K entries and use the array for read/write. Associative arrays doesn’t need allocation and initialization of memory upfront and can be allocated and initialized just when an entry of the 64K array needs to be referenced. However, associative arrays are also slowest as they internally implement search for elements in the array using a hash.
Suppose a dynamic array of integers ( values ) is initialized to values as shown below. Write a code to find all elements greater than 3 in the array using array locator method “ find ”?

int values [] = ‘{9,1,8,3,2,4,6,7,5,7},
int match_q[$];
match_q = values.find with (item > 3);

What is the difference between a struct and union in SystemVerilog?

A structure represents a collection of data types that can be referenced as a whole, or the individual data types that make up the structure can be referenced by name. For example:
In the example below, we have a struct defined called instructions that groups a 24 bit address field and an 8 bit opcode field.
typedef struct {
bit [7:0] opcode;
bit [23:0] addr;
} instruction_s
instruction_s current_instruction;
current_instruction.addr=’h100;
The instruction_s struct can be referenced together or individual members can be accessed. The total memory allocated would be the sum of memory needed for all the data types. Hence in above example, the currect_instruction struct would take a total memory of 32 bits (24 bit address and 8 bit opcode)
A union is a data type which can be accessed using one and only one of the named member data type. Unlike struct you cannot access all member data types together. The memory allocated for the union would be the maximum of the memory needed for the member data types. Unions are normally useful if you want to model a hardware resource like register that can store values of different types. For example: if a register can store an integer and a real values, you can define a union as follows:
typedef union {
int data;
real f_data;
} state_u;
state_u reg_state;
reg_state.f_data = ‘hFFFF_FFFF_FFFF_FFFF;
$display(“ int_data =%h“, reg_state.data);
In this example, the union state_u can either hold a 32 bit integer data or it can hold 64 bit real data. Hence, the memory allocated for the union reg_state will be 64 bits (bigger of the two data types). Since, there is shared memory for all member data types, in above example, if we assign a 64 bit value to reg_state.f_data, we will be also able to reference the 32 bit of same using the other data type.

What is the concept of a “ref” and “const ref” argument in
SystemVerilog function or task?

A ref keyword is used to pass arguments by reference to a function instead of a value. The subroutine/function shares the reference handle with the caller to access values. This is an efficient way of passing arguments like class objects or arrays of objects where otherwise creating a copy would consume more memory on the stack. Also, since the caller and the function/task shares same reference, any change done inside the function using the reference would also be visible to the caller.
For Example: Here is an example of a CRC function which needs a big packet as argument to compute CRC. By passing as reference, each call to CRC function doesn’t need to create a copy of the packet on stack memory.
function automatic int crc(ref byte packet [1000:1] );
for( int j= 1; j <= 1000; j++ ) begin
crc ^= packet[j];
end
endfunction
A const keyword is used if user wants to make sure that the ref argument is not modified by the function. For example: in the same CRC function, the argument can be declared as a “ const ref “ argument as shown below to make sure that the original packet contents are not modified accidentally by the CRC function.

function automatic int crc( const ref byte packet [1000:1] );
for( int j= 1; j <= 1000; j++ ) begin
crc ^= packet[j];
end
endfunction
What would be the direction of arguments a and b in following?
task sticky(ref int array[50], int a, b);
Each argument of a task or function can have a direction which can be one of input, output, inout or ref. If no direction is specified, the default value of input is selected. If one of the arguments specifies a direction, then all following arguments hold on to same direction unless explicitly changed.
So in above example, the first argument has a direction defined as “ref” which means it is an argument passed by reference. Since the following arguments “a” and “b” have no explicit directions defined, these also get the same direction. Hence, “a” and “b” also become pass by reference arguments.
What is the difference between a packed array and an unpacked array?
A packed array represents a contiguous set of bits while an unpacked array need not be represented as a contiguous set of bits. In terms of difference in declarations, following is
how a packed and unpacked array is declared
bit [7:0] data ; // packed array of scalar bit types
real latency [7:0]; // unpacked array of real types
Packed arrays can be made of only the single bit data types (bit, logic, reg), or enumerated
types. Example: logic[31:0] addr; //packed array of logic type
Unpacked arrays can be made of any data type. Example:
class record_c;
record_c table[7:0]; //unpacked array of record objects
What is the difference between a packed and unpacked struct?
A packed structure is a way in which a packed bit vector can be accessed as struct members. Or in other words, if all the members of a struct consist of only bit fields and can be packed in memory without any gaps, it can be a packed structure. For example: in the structure definition below, all the members can be represented as bit vectors (int is equivalent to 32 bits, short int to 16 bits, byte to 8 bits) and a struct can be packed into a single contiguous memory of 56 bits.

struct packed {
int a;
short int b;
byte c;
} pack1_s;
An unpacked struct need not be packed into contiguous set of bits and hence different members could be placed in memory with gaps. Following is an example with a structure having different data types that cannot be packed in memory.
struct record {
string name;
int age;
string parent;
} record_s
Which of the following statement is true?
1) Functions should execute in Zero Simulation Time.
2) Tasks should execute in Zero Simulation Time.

Functions always need to be executed in zero simulation time and cannot contain any construct that can induce a time delay (Example: waiting for clock edge or # delays etc.). Tasks can have constructs causing timing delays and hence, need not complete execution in zero time.

Given a dynamic array of size 100, how can the array be re-sized to hold 200 elements while the lower 100 elements are preserved as original?
A dynamic array needs memory allocation using new[] to hold elements. Here is an example with an integer array that grows from an initial size of 100 elements to 200
elements.
integer addr[]; // Declare the dynamic array.
addr = new[100]; // Create a 100-element array.
………
// Double the array size, preserving previous values.
addr = new[200](addr);
What is the difference between “forever” and “for” in SystemVerilog ?
The “forever” loop repeatedly executes a statement without any limit. The only way execution can stop is by using a break statement. A forever loop if used without any timing controls (like clock or time delay) can result in a zero-delay infinite loop and cause hang in simulation. The “for” loop is used for executing a statement for a defined number of times based on conditions that are defined.
What is the difference between “case”, “casex” and “casez” in
SystemVerilog?
The case statement is a multiway decision statement that tests whether an expression matches one of a number of possible values and branches accordingly. Following is a
simple example to implement a 3:1 MUX using a case statement
case (select[1:0])
2’b00: out_sig = in0;
2’b01: out_sig = in1;
2’b10: out_sig = in2;
default: out_sig = ‘x
endcase
In the above example of using a “case” statement, the expression match happens exactly with what is specified. For example, in above case statement, if at least one of the select lines is X or Z, then it will not match any conditions and will execute the default statement.
“ casez ” is a special version of case expression which allows don’t cares in comparison of the expressions. These are typically useful in decoder logic which only treats fewer bits. Here is an example where a 3 bit interrupt request queue (irq) bus is decoded into 3 separate interrupt pins based on which bit in the bus is high, while other bits are don’t
care.
casez (irq)
3’b1?? : int2 = 1’b1;
3’b?1? : int1 = 1’b1;
3’b??1 : int0 = 1’b1;
Endcase

“casex” is another special version where in addition to don’t cares, it also ignores X and Z values in comparison.

Which of the logical equality operators “==” or “===” are used in case
expression conditions for case, casex, and casez?
All of the 3 case statements use “===” logical equality comparison to evaluate condition matches.
What is the difference between $display, $write, $monitor and $strobe in
SystemVerilog?
1) $display : Print the values immediately when executed.
2) $strobe : Print the values at the end of the current timestep.
3) $monitor : Print the values at the end of the current timestep if any values
change. If $monitor is called more than once, the last call will override previous
one.
4)$write : This is same as $display but doesn’t terminate with a newline (\n).

Exit mobile version