System Verilog Interview Question
System Verilog Interview Question
Ans:-
-> $random returns a signed 32-bit integer; $urandom and $urandom_range return
unsigned 32-bit integers.
-> The random number generator for $random is specified in IEEE Std 1800-2012. With
the same seed you will get exactly the same sequence of random numbers in any
SystemVerilog simulator.
That is not the case for $urandom and $urandom_range, where the design of the
random number generator is up to the EDA vendor.
-> Each thread has its own random number generator for $urandom and $urandom_range,
whereas there is only one random number generator for $random shared between all
threads
(ie only one for the entire simulation).
This is really important, because having separate random number generators for each
thread helps you simulation improve a property called random stability.
-> An expect statement is very similar to an assert statement, but it must occur
within a procedural block (including initial or always blocks, tasks and
functions), and is
used to block the execution until the property succeeds.
task mytask;
...
if (expr1)
expect (my_property)
pass_block();
else // associated with the 'expect',
// not with the 'if'
fail_block();
...
endtask
-> A bind directive can tie them together even though they are in two separate
files.
-> A bind directive can tie a module, an interface or a program instance with a
module or module instance and can be specified in a module, an interface, or a
compilation-unit scope.
-> A property can be specified within a module differnt from the design module.
These modules can then be tied together using a bind directive. The following
example shows how to do it.
In the first case, all instances of the design_module get the properties defined
within prop_module_1 instance of prop_module. In the second case,
only instance design_module_1 receives these properties.
Ans:- Direct programming interface or DPI is a interface between the System Verilog
and the C language. It allows you to call the sytem verilog functions in C language
and Vice Versa
-> you can reuse your existing c code with system verilog
Sytem Verilog :
module hello();
import "DPI-C" function void print_hello();
initial
begin
print_hello();
end
endmodule
C :
===
void print_hello() {
printf("Hello World From C \n");
}
How to run :
output :
VSIM 1> run -all
# Hello World From C
# ** Note: $finish : hello.sv(7)
# Time: 0 ns Iteration: 0 Instance: /hello
GCC option :
-shared
Produce a shared object which can then be linked with other objects to form an
executable.
Explanation :
we need to import the C function in system verilog with statement 'import "DPI-
C"'
we should have actual funtion implementiaon in C file
Call the C funtion in your system verilog code
remember to link library at loading time
import declaration can occur anywhere where a SystemVerilog task or function
definition is allowed
NOTE : C function should not comsume time like the system verilog functions
Imported Functions :
Exported Functions :
System verilog functions that are called from foeign language should appear in
exported function declerations
Adding modports to an interface does not require that any of the modports be used
when the interface is used. If no modport is specified in the module header or in
the port
connection, then all the nets and variables in the interface are accessible with
direction inout or ref, Below example shows this in greater detail.
Q-> What is clocking block? // I need to read cummings paper for the same
Ans:- Specifying the timing and synchronisation requirements of a design in a
testbench.
A clocking block is a set of signals synchronised on a particular clock. It
basically separates the time related details from the structural, functional and
procedural
elements of a testbench. It helps the designer develop testbenches in terms of
transactions and cycles. Clocking blocks can only be declared inside a module,
interface or program.
initial begin
ok = std::randomize(i,j);
...
end
endmodule
->The user can define constraints to generated random variables using with
form.
ex:-
int x;
-> Class Variable:- Default all variable and class method are automatic. Each
instance of class will have its own copy of variable. If it is declared as static
only one copy will
be created and all instance will use that copy. Static variable can be accessed
with out creating object of class. It can be accessed with out making object and by
scope resolution operation.
-> Method Variable:- Default lifetime of variable declared in method (Function and
Task) is automatic. Scope of the variable is limited to execution of that method.
Its lifetime is automatic as its memory will be deallocated when the task and
function gets over.
-> Loop Variable:- Default local variable of loop is automatic. Its scope is
limited to execution of call and its memory deallocated when execution of loop is
over.
-> Module or Program Block:- Default lifetime of variable is Static for Module and
Program. They will have memory till end of simulation and its scope will be limited
to that module or program called.
-> Method in module and program block:- Default life time of method in program and
module block is static. This is to keep it same with existing verilog reference.
So for module function lifetime is static. Its variable and return type is static.
So if we call recursive function, it will not create multiple stack entry for call
of function and stack memory for internal variable.
-> Each element of an associative array gets allocated as you access them. So there
is a lot more overhead for the creation of an associative array versus the same
size dynamic array. And since the elements of an associative array are not always
in a contiguous block of memory, there is overhead in accessing each element. (i.e.
have to check if the element is allocated, and then where is it located)
-> The benefit of an associative array is since each element gets allocated
individually, you don't need to allocate a contiguous set of array elements.
This is useful when you only plan to access a relatively few (sparse) elements of
an memory address space.
Another benefit is that you don't have to use an integer as an index to each
element. You can associate any type of key, like a string to access each element.
Q-> What is input skew and output skew in clocking block ? // I need to short
answer for the same
Ans:- A skew number for an input denotes when that input is sampled before the
clocking event (such as posedge or negedge) occurs. For an output, it is just the
opposite -
it denotes when an output is synchronized and sent after the clocking event.
-> 1step
A 1step is a special unit of time. It denotes a negative time delay from the
edge of a clock when all inputs are steady and ready to be sampled.
In terms of scheduling semantics, a 1step unit denotes the Postponed region
immediately before a clock edge.
The default skew statement in the above example is optional. A clocking block
without this statement (as shown below) is still legal.
In this case, the default input skew is 1step and the default output skew is 0.
For example, the example below overwrites the default input skew for signal a1 (to
1step) and output b1 (to 5 ns), but the input skew for a2 remains unchanged at 2
ns.
A skew value of #0 changes the way input values are sampled and output values are
synchronized, even though both will still be done at the simulation time when a
clock event occurs.
A skew value of #0 for any input means that the input will be sampled at the
Observed region. An output skew value of #0 indicates that the output will be
synchronized out in the Non-blocking assignment (NBA) region.
-> Parameterized skew value
Ans:- Apparently there is not difference between queue and mailbox. Both can store
data (push or put) and we can get stored data from is (pop and get.)
Difference lies when there is multiple thread (or process), putting or getting
element to or from queue.
For a single thread or process there is no difference between queue and mailbox.
Above mailbox can only store 4 element. If we try to put more element then 4 it
will block the method until space is created.
endtask
Here we only push element if size is less than 4. If it is single thread doing this
there is no difference (except we have to add wait statement).
But what mailbox is provide is : above test and set operation are performed
atomically (uninterrupted). While for queue it is two different process. (test and
set).
1. The first is that when there are multiple threads waiting on the size of the
queue to change, there is no guaranteed ordering which thread will wake up and
proceed when the
condition is satisfied. Mailboxes/semaphores guarantee that the order that the
threads suspend is the same as the order they wake up (FIFO order First In/First
Out).
As part of the integration with SystemVerilog, the program was turned into a
module-like construct with ports and initial blocks are now used to start the test
procedure.
Because an always block never terminates, it was kept out of the program block so
the concept of test termination would still be there.
Today, most people do not utilize this termination feature because the OVM/UVM have
their own test termination mechanisms.
The program block is no longer a necessary feature of the language other than to
help people converting over from Vera to SystemVerilog.
Another Ans:- In a design, an always block might trigger on every positive edge of
a clock from the start of simulation.
A test-bench, on the other hand, goes through initialization, drive and respond to
design activity, and then completes.
When the last initial block completes, simulation implicitly ends just as if you
had executed $finish.
If you had an always block, it would never stop, so you would have to explicitly
call $exit to signal that the program block completed.
Q-> How can you get an assertion pass and fail in the same time slot?
Ans:-
Q-> What is the difference between task and function in class and Module?
Ans:-
class constraint_container;
rand int unsigned a, b, c;
constraint a_constraint {
a == 5;
// I expect "b" to be equal to "a", but, surprise, surprise...
b == get_a();
// I expect "c" will be equal to "a"
c == value_of(a);
}
endclass
module top;
initial begin
automatic constraint_container cc_inst = new();
void'(cc_inst.randomize());
$display($sformatf("a: %0d, b: %0d, c: %0d", cc_inst.a, cc_inst.b, cc_inst.c));
end
endmodule
At first glance one would guess that all three fields will be 5, but one will get
instead:
OUTPUT:
a: 5, b: 0, c: 5
-> Functions shall be called before constraints are solved, and their return
values shall be treated as state variables.
-> Function calls in active constraints are executed an unspecified number of
times (at least once) in an unspecified order.
-> The conclusion is that functions used by constraints should compute the result
based ONLY on function’s arguments and NOT on class members.
class parent_class;
protected bit [31:0] tmp_addr;
function display();
$display("tmp_addr = %0d",tmp_addr);
endfunction
endclass
// module
module encapsulation;
initial begin
child_class c_c = new(10);
class X;
int i;
endclass
RESULT
When the compiler encounters the handle x of class type X referred to in class Y,
it does not yet know the definition for class X since it is later in the file.
Thus, compilation fails.
To rectify this situation, typedef is used to forward reference the class
declaration.
EXAMPLE:
typedef class X;
class Y ;
X x; // refers to Class X, which is not yet defined
endclass
class X;
int i;
endclass
The typedef of class X allows the compiler to process Y before X is fully defined.
Note that typedef cannot be used to forward reference a class definition in another
file.
This must be done using the inclusion of a header file.
EXAMPLE:
class Y ;
int i;
Y y; // refers to Class Y, which is not yet defined
endclass
As you seen, there is a compilation error. To avoid this situation, typedef is used
to forward reference the class declaration and this circular dependency problem can
be avoided.
program main
initial begin
Base B;
B = new();
B.disp();
end
endprogram
RESULT:- Error: pure virtual task disp(); must be overridden in derived class
Q-> What are the main regions inside a SystemVerilog simulation time step?
Ans:- Read cummings paper
module tb;
initial begin
Fruits f = new ();
1. Override with an empty constraint, and add new constraint. This runs the
risk of having a typo and winding up with both constraints active.
2. Override with a replacement constraint. This shows your intent with the
most clarity.
3. Disable the base constraint using constraint_mode in the extended
constructor. This allows you to turn it back on later if needed in the sequence, or
an extended sequence.
4. Use a soft constraint. This allows you to add new constraints, and only
removes the existing soft constraint if it conflicts.
Q-> Given a Packet class with following constraints, how can we generate a packet
object with address value greater than 200?
Ans:-
Q-> There are two task and both are under fork and join and second task will
execute only when first task finishes its work, how can it be done ?
Ans:- This can be achieved though semaphore, once first task finises it work it
will release its key and other task will pick it up and continue its execution.