Monday, February 29, 2016

Packed and Unpacked Array : Memory Allocation

SystemVerilog stores each element in long word (32 bits). For example, following declaration will use 32 bits in the memory, although only 8 bits are really used .
Bit [7:0] a;
‘a’ is a single element with 8 bits.The memory use will be as below.


Rewriting the above declaration like following
Bit [7:0] a_unpacked [2:0];
Now 'a' become an array which contains 3 elements with the size of 8 bits each. As ‘SystemVerilog stores each element in a longword (32 bits)’. In the above declaration will look like this



The memory is not used efficiently (not well packed), but sometimes it is necessary to declare this way. It is called unpacked array. Let’s rewrite the above declaration into following way
Bit [2:0] [7:0] a_packed;
The word dimension [2:0] moved next to bit dimension [7:0]. ‘a’ is an element (note it is single element) which has 3 sets of 8 bit words. Since a single element stored in a long word, memory usage will look like this


The memory used efficiently (well packed). It is called packed array.

Code:









Output: 
@@@@ packed 111 unpacked 0
@@@@ packed 1 unpacked 0

Friday, February 5, 2016

Why we need virtual interface? If I don't want to use it what is an alternate method.

Interface is static entity. We can not use it in dynamic entity like class. So we have a new type called virtual interface. We can bind interface with virtual interface in top module. Virtual interface will be treated like a class handle.

Let me explain.

Classes in system verilog are created at run time. Port connection between modules and creating direct reference to the dut signals are done at elaboration time. We can not do direct connection with DUT signals like that with class because as I said class are created at run time.

We need another mechanism to do that. To do the same thing work at compile and elaboration time we can use hierarchical defines. Like ,
`define PATH top.design.block1
and then the write `PATH.sig1 <= 1; in the testbench. This approach does not work when there are multiple instances of testbench objects that need to communicate multiple paths of the DUT. Another problem is that most classes are written inside SystemVerilog packages, and packages are not supposed to have any outside dependencies other than other package imports. 

So SystemVerilog, which already has dynamic references to class objects, added a dynamic reference to an interface instance and called it a virtual interface.
virtual interface variable can dynamically accept a handle to an actual interface instance. Then you can then dynamically reference members of that interface instance.

Still if you don't like virtual interface, here is another method you can use. :)

To create a class inside interface and use it. How? Let me show



package abstract_pkg;
  virtual class abstract_intf #(int awidth);
    pure virtual function void set_address(
    input logic [awidth-1:0] a);
    pure virtual task posedge_clock;
  endclass
endpackage

interface dut_itf#(int dwidth, awidth);
 logic clock,reset;
 wire [dwidth-1:0] data;
 logic [awidth-1:0] address;
  import abstract_pkg::*;
  class concrete_intf#(int width) extends abstract_intf#(width);
    function void set_address(
      input logic [width-1:0] a);
      address = a;
    endfunction
    task posedge_clock;
      @(posedge clock);
    endtask
  endclass
  concrete_intf#(awidth) c = new();
endinterface

package my_pkg;
 import abstract_pkg::*;
  class driver;
    abstract_intf#(16) c_h;
    task run;
      forever begin
      c_h.posedge_clock;
      c_h.set_address(‘h1234);
      end
    endtask
  endclass
endpackage

module testTop;
  dut_itf #(8,16) i1();
  DUT d1(.itf(i1));
  TEST t1(.itf(i1));
endmodule

module TEST();
  import my_pkg::*;
  driver d;
  initial begin
  d = (new);
  d.c_h = i1.c;
  d.run;
  end
endmodule

Here c_h is class defined in interface, which we used in driver and from it we can toggle or use interface signal. 

What is difference between reg ,wire and logic

Difference in very simple terms.

Reg = used to store value. Used in sequential assignments. It will store the value in variable until next assignments.

Wire = used for continuous assignment. Its net (network) type. used for combinational logic. Used in assign statment. It can not store the value. It will connect two port.

Logic :  Logic and reg is slightly different. Logic can also be used for continuous assignment. That mean it can be used at LHS for assign statement.
Implicitly it can be seen as


logic A; //is a shortcut for

var logic A; // This is like Reg A

And

wire A; // is a shortcut for

wire logic A; // This is like wire A


http://inst.eecs.berkeley.edu/~cs150/Documents/Nets.pdf

Wire Elements (Combinational logic) wire elements are simple wires (or busses of arbitrary width) in Verilog designs. The following are syntax rules when using wires:
1. Wire elements are used to connect input and output ports of a module instantiation together with some other element in your design.
2. Wire elements are used as inputs and outputs within an actual module declaration.
3. Wire elements must be driven by something, and cannot store a value without being driven.
4. Wire elements cannot be used as the left-hand side of an = or <= sign in an always@ block.
5. They are the only legal type on the left-hand side of an assign statement.
6. This elements are a stateless way of connecting two pieces in a Verilog-based design.
7. It can only be used to model combinational logic.

Program 1  Legal uses of the wire element

wire A , B , C , D , E ; // simple 1 -bit wide wires
wire [8:0] Wide ; // a 9 -bit wide wire
reg I ;

assign A = B & C ; // using a wire with an assign statement

always @ ( B or C ) begin
I = B | C ; // using wires on the right - hand side of an always@
// assignment
 end

 mymodule mymodule_instance (. In ( D ) ,
 . Out ( E ) ) ; // using a wire as the output of a module

Reg Elements (Combinational and Sequential logic) reg are similar to wires, but can be used to store information (‘state’) like registers. The following are syntax rules when using reg elements.
1. reg elements can be connected to the input port of a module instantiation.
2. reg elements cannot be connected to the output port of a module instantiation.
3. reg elements can be used as outputs within an actual module declaration.
4. reg elements cannot be used as inputs within an actual module declaration.
5. reg is the only legal type on the left-hand side of an always@ block = or <= sign.
6. reg is the only legal type on the left-hand side of an initial block = sign (used in Test Benches).
7. reg cannot be used on the left-hand side of an assign statement.
8. reg can be used to create registers when used in conjunction with always@(posedge Clock) blocks. 9. reg can, therefore, be used to create both combinational and sequential logic.

Program 2 Legal uses of the reg element

wire A , B ;
2 reg I , J , K ; // simple 1 -bit wide reg elements
3 reg [8:0] Wide ; // a 9 -bit wide reg element
4
5 always @ ( A or B ) begin
6 I = A | B ; // using a reg as the left - hand side of an always@
7 // assignment
8 end
9
10 initial begin // using a reg in an initial block
11 J = 1 ’ b1 ;
12 #1
13 J = 1 ’ b0 ;
14 end
15
16 always @ ( posedge Clock ) begin
17 K <= I ; // using a reg to create a positive -edge - triggered register
18 end

When wire and reg Elements are Interchangeable? 
Wire and reg elements can be used interchangeably in certain situations:
1. Both can appear on the right-hand side of assign statements and always@ block = or <= signs.
2. Both can be connected to the input ports of module instantiations.

Setup and Hold time and clocking block in system verilog

Set up time : A time before clock edge for which input data should be stable.

Hold time : A time after clock edge for which input data should be stable.

If any of above is violated the output may go meta-stable.


In above image shaded region before dashed line is setup time. Shaded region after dashed line is hold time. Here it violates setup and hold time.



Above is timing for D flipflop. See here we do not change input in shaded (restricted) region. Input is changed before setup time and remain stable while in hold time.

In system verilog we use clocking block to avoid race condition as well setup/hold violation.

Here I am just giving an idea that how we can use clocking block

module test();
clocking cb @(posedge CLK);
  default input #setup_time output #hold_time;
  output a;
  output b;
  output c;
 
  input x;
  input y;
  input z;
endclocking

We can put clocking block inside module or program.
Here input will be sampled before #setup_time @posedge of CLK.
Output will be driven after #hold_time @posedge of CLK

Signed and Unsigned variable

Lets take example of bits (unsigned) and byte (signed) data type.

8 bit packed array of bit : bit [7:0] a (0 to 255)
byte b (-128 to 127)

module test();
  bit[7:0] a=2'h00,b=2'h01,c,bit_sum1,bit_sum2;
  byte d,byte_sum1,byte_sum2;
  initial
  begin
    c = a-b;
    d = a-b;
    bit_sum1 = c - 1;
    bit_sum2 = d -1;
    byte_sum1 = c -1;
    byte_sum2 = d - 1;
    $display("Binary Representation : %b d %b bit_sum1 %b bit_sum2 %b byte_sum1 %b byte_sum2 %b",c,d,bit_sum1,bit_sum2,byte_sum1,byte_sum2);
    $display("Decimal Representation : c %0d d %0d bit_sum1 %0d bit_sum2 %0d byte_sum1 %0d byte_sum2 %0d",c,d,bit_sum1,bit_sum2,byte_sum1,byte_sum2);
  end
endmodule
Output :

Binary Represantation: c 11111111 d 11111111 bit_sum1 11111110 bit_sum2 11111110 byte_sum1 11111110 byte_sum2 11111110
Decimal Represantation: c 255 d -1 bit_sum1 254 bit_sum2 254 byte_sum1 -2 byte_sum2 -2

Does System Verilog support Method Overriding and Method Overloading.

Method Overriding : Method of base class enhanced in derived class. Used that as virtual method. Concept of polymorphism

Method Overloading : Multiple method with same name but different signature. Different set of argument .

virtual void print(int x); 
virtual void print(bit y)

This is not supported in System Verilog.

What is difference between Mailbox and Queue.

It is very common question asked in interview.

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.

I will show you with example below, how it affects.

Mailbox is special class (enhanced functionality of queue) in std package of system verilog. It can be bounded or unbounded. Bounded means size of mailbox is fixed, you can not put more element more than its defined size.

mailbox mbx = new(4);

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.

Bounded Queue : Can we make that??? Yes we can mimic it as below.

task put(input int data);
  wait(q.size < 4); // test
  q.push_back(data); // set
endtask
task get(output int data);
 wait(q.size > 0); // test
  q.pop_front(data); // set 
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).

There are two problem using that queue approach.

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). 

2. The other problem is there is no guaranteed ordering of statements between two or more concurrently running threads. It's possible for multiple threads to wake up when the queue size changes so that either q.size < 4 is true for a put(), or q.size > 0 for a get(). All the threads could execute the test and succeed, then all the threads do their set operation when only one operation should have been allowed. Mailboxes/semaphores guarantee that put() and get() act atomically so that no other thread interrupt the test and set operation. So only one thread will succeed in the put() or get().

What is difference between ++i and i++

  • ++i will increment the value of i, and then return the incremented value.
     i = 1;
     j = ++i;
     (i is 2, j is 2)
  • i++ will increment the value of i, but return the original value that i held before being incremented.
     i = 1;
     j = i++;
     (i is 2, j is 1)

What is the difference between $rose and posedge?

posedge returns event where as $rose returns a boolean value. Events cannot be used in expression, $rose can be used. 

System Verilog : Misc

Here I am Putting some small statement which I learn in day to day work.

1. If you don't write super.new inside new function of current class, the compiler itself add super.new() automatically.

2.  When a child class object is created by new constructor, its parent class (if its abstract then also) is created implicitly. Without parent child can never be exists.

3. You can inherit any method from base class. I mean you can call any method define in base class by child class handle (if it is not defined in child class. That is inheritance concept). But if in base class you have created new function (i.e constructor) with argument, you cant inherit that in child class. You need to define new again in child class with argument.

class animal;
   int age=-1;
  function new(int a = 20);
      age = a;
   endfunction : new
endclass : animal
class lion extends animal;
   //function new(int age);
      //super.new(age);
   //endfunction : new
endclass : lion
module test();
  animal a;
  lion l;
  initial
    l = new(10); // l = new() will work
endmodule

Output : 
Error-[TMAFTC] Too many arguments to function/task call
testbench.sv, 18
"lion::new(10)"
  The above function/task call is done with more arguments than needed.

Run Here :

Below will also work as new is defined in derived class but argument is not passed in super.new, since it has default value. If base class new did not had default value it would shout an error 



Output:
@@@@ age is 20
Below will give error as default value is not assigned in new.

Output:
Error-[TFAFTC] Too few arguments to function/task call testbench.sv, 15 "animal::new()" The above function/task call is not done with sufficient arguments.

3. A class variable can be declared as a rand type. Like rand class_abc abc; 
Thus when class in which class_abc is created, will call .randomize function, it will also randomize rand variable declared in class_abc.
See below example.
class base;
  rand int vari =1 ;
endclass
class obj;
  rand base baseh = new();
endclass
module test;
  obj objh = new() ;
  initial
  begin
    if(objh.randomize())
    begin
      $display(" Randomization is done ");
    end
    $display(" objh.baseh.var : %d ", objh.baseh.vari );
  end
endmodule

Output : 
 Randomization is done 
 objh.baseh.var :  -902462825 

Run Here


4. Constraint are by default virtual in nature. If any constraint with the same name is written in derived class, it will override the constraint written in base class. So If we assign derived class handle to base class, randomize method will solve constraint written in derived class.

class A;
rand integer x;
  constraint c { x > 0; }
endclass
class B extends A;
  constraint c { x < 0; }
endclass
module top();
  A a;
  B b;
  initial
    begin
      b = new();
      a=b;
      a.randomize();
      $display("@@@ %0d",a.x);
    end
endmodule

Output : 
@@@ -1223315946

Run Here
4. Mailbox and semaphore are classes defined in std package

5. intial and always block executes at time 0. If there are more than one block in a module all are executed concurrently and independently.   
6. Class can have an object of its own type.
See below code. 

class test;
  test self;
  function create_me();
    self = new();
    self.display("self");
  endfunction
  function display(string s = "this");
    $display("from function display %s",s);
  endfunction
endclass
 
module test_module();
  test test_ob;
  initial
    begin
      test_ob = new();
      test_ob.create_me();
      test_ob.display();
    end 
endmodule
Output : 
from function display self
from function display this
it has a class variable self that will eventually hold a handle that can reference another class object of the same type. This is a very common data structures like a queue or tree used in many other programming languages. Seehttp://www.cprogramming.com/tutorial/lesson18.html