Wednesday, April 17, 2013

System Verilog few examples


Program block Vs Module

Guess the outputs with defined and undefined PGM

class A;
 function void my_t1 ;
   fork
     #300 $display("%0t:Anthing",$time);
   join_none
 endfunction

 task my_t2;
   fork
     #10;
     #20;
   join_any
   disable fork;
 endtask
endclass:A

`ifdef PGM
 program p;
`else 
 module p;
`endif
  A a;
  initial begin
   a=new();
   fork
    a.my_t1;
    a.my_t2;
   join
   $display("@%0t Wifi",$time);
  end

  final
    $display("It's a final countdown at %0t.", $time);
`ifdef PGM
endprogram
`else
endmodule
`endif

Enum Useage query 

Guess the outputs with defined and undefined CAST_YES

class test_enum_constr; 
typedef enum { EVEN=0, ODD=1} e_even_odd; 
typedef enum { HIGH=1, LOW=0} e_hi_lo; 
rand e_even_odd e1, e2;
rand e_hi_lo    e3;
constraint cEnum
{
    `ifdef CAST_YES
       e1 == e_even_odd'(HIGH);
    `else
       e1 == HIGH;
    `endif 
 }

constraint cSachoEnum
{
    e3 dist { HIGH := 30, LOW := 70 };
 }

function new();
   void'(this.randomize());
endfunction : new 

function void post_randomize();
    $display("\n==> %0p", this);
endfunction : post_randomize 

endclass : test_enum_constr

module test;
  test_enum_constr obj1, obj2;

  initial
  begin
    obj1 = new(); 
    obj2 = new();

    `ifdef CAST_YES
      obj1.e1 = e_even_odd'(obj2.e3);
    `else
      obj1.e1 = obj2.e3;
    `endif // CAST_YES

    obj1.post_randomize();
  end

endmodule : test

Dynamic Array of Class

Guess output with GOOD defined and undefined
class aha;
  shortint unsigned a;
 
endclass : aha

module test;
  aha Oho[];

  initial
  begin
    Oho = new[4];
    foreach(Oho[ii])
   
begin
      `ifdef GOOD
         Oho[ii] = new;
      `
endif          
        Oho[ii].a = $urandom_range(30,90);
      $display("==>>> Oho[%0d] is : %p", ii, Oho[ii]);
   
end
  end
endmodule : test

Threading query

while(1)
begin
fork
    begin:Thread1
      .....
    end
    begin:Thread2
      .....
     @(my_event);
      disable Thread1;
   
end 
 join_any
end//end_while(1)  


Here assume that after 100ns Thread1 is finished what will happen? Will simulator kill the Thread2 as there is a join_any and will start again with both the threads? Or it will generate new one? 


Friday, April 12, 2013

System Verilog let construct



Let construct
Very rarely known/used construct, but very helpful.

What it is?
A let declaration defines a template expression (a let body), customized by its ports. A let construct may be instantiated in other expressions.

It is basically a text macro. Just like the `define macro(compiler directive), but bit different than it. Difference between `define and let is that “let” is having local scope where as “`define” is having global scope.

So let macro can have different definition par task/function/module, whereas there could only one `define based macro.

How to use it?
Syntax:
  let (actual/formal variable)=(expression containing actual/formal variables);
Usage example1(Formal variable passed in declaration):
module my_mod(input I, input j);
……
…..
//Definition
let maxab(a,b)=(a>b?a:b);
//Usage
C=maxab(d,e);
…….
…….
endmodule

Usage example2(let construct in assertion):
module m;
logic clk, a, b;
logic p, q, r;
// let with formal arguments and default value on y
let eq(x, y) = x == y;
// without parameters, binds to a, b above
let tmp = a && b;
...
a1: assert property (@(posedge clk) eq(p,q));
always_comb begin
a2: assert (eq(r,s));
a3: assert (tmp);
end
endmodule : m

Usage example3(No formal variable passed in declaration):
module m;
logic clk, a, b;
logic p, q, r;
// let with formal arguments and default value on y
let eq(x, y=b) = x == y;
// without parameters, binds to a, b above
let tmp = a && b;
...
a1: assert property (@(posedge clk) eq(p,q));
always_comb begin
a2: assert (eq(r));
a3: assert (tmp);
end
endmodule : m

In cases where formal variables are not passed remaining variables are assigned value from local scope, in above example value of y is picked from local variable ‘b’.

Where it can be defined:
A let may be declared in any of the following:
— A module
— An interface
— A program
— A checker
— A clocking block
— A package
— A compilation-unit scope
— A generate block
— A sequential or parallel block
— A subroutine

Thursday, April 11, 2013

SFIs UVM based environment example

SFIs UVM based environment example:-
Basic components of environment
1)      SFIs data lane driver(Input agent)
2)      SFIs data lane monitor(Input agent)
3)      SFIs data lane Sequencer(Input agent)
4)      Output monitor(Output agent)
5)      Scoreborad
6)      Register model




Features to be verified:
Major feature which should be verified for SFIs are as given below
For SFIs interacting between Optic to System side
1)      Deskew lane generation as per SFIs standard.
2)      Data inversion during odd parity frame element of deskew reference frame.
3)      Constantly check generated deskew against received deskew lane.
4)      Check that once lanes are aligned they remain aligned not skew is added.
5)      Data integrity.
For SFIs interacting between System to Optic side
1)      Deskewing all data lanes is possible with skew within limit(supported by RTL).
2)      Check that adding any runtime skew will cause alignment failure.
3)      Check that adding any error in any of the lane will cause alignment failure.
4)      Data inversion during odd parity frame element of deskew reference frame.
5)      Data integrity.
6)      Manual alignment mode if any.

Data flow:-
1) Sequencer to Driver:-
Data to be transmitted will be generated by sequencer and will be in form of bit queue or fixed size of array, minimum size of this array must be (number of lanes * data width of lane). So packet coming from the sequencer must be of this size.

In async/soft reset will drive 0 on each lane. Once async reset is removed driver will wait for register configuration to get completed. In async/soft reset drive thread will not pop any packet and will wait till reset is removed.

Driver will take data from packet and will stripe down this data over lanes. It will also form deskew lane from this packet. It will form bit queues for each lane and will put the data from packet into this queues. Once data is put into all bit queues, further below mentioned operations over it can be done

1)Lane Corruption:-
     When enabled particular lane or lane data will be corrupted, information of lane/lanes to be corrupted will be residing in the packet from sequencer. Driver will send random data on lanes when lane corruption is enabled. Checkers should be stopped once lane corruption starts.

2)Inject errors in lanes:-
      When enabled errors will be inserted in particular lane or lanes. These errors are distributive in nature unlike lane corruption. Here only bit of lane will be corrupted via inverting that bit from its original value. Checkers should be stopped once error injection starts.

3)Add runtime skew:-
      When enabled it will add skew in addition to what added initially in all lanes.

4)Data inversion:-
      When enabled it will invert data of lanes on during odd parity frame.

2)Monitor:-
Monitor will snoop data from each lane and will form bit queue. It will try to lock to reference deskew parity pattern. Once deskew reference is locked it will try to find each lane data on deskew and via this process it will be able to find the skew between lanes.

Normally when SFIs is transmitting data(System to Optic side case) it is assumed that there will not be any skew between the lanes and monitor will shout for errors if there is any skew.

Once all data lanes are successfully mapped on deskew lane, monitor will be in sync. Once this initial synchronization is done, monitor will be able to form deskew lane from the data lane samples and can compare it with actual deskew lane.

Monitor will continuously compare internally generated deskew lane against snooped deskew lane and whenever they are not matching it will shout for error and will go out of synchronization. Once it will go out of synchronization it will again try to lock itself.

Once it is in sync it will start forming packets. As driver stripes the data over the lanes, monitor will perform reverse operation and will generated packet. When monitor is not in sync it will not send any packet.

SFIs transaction Class:-

Name:-SfisTxn

Variables:-
1)data[`NO_OF_LANES*`LANE_WIDTH-1:0]
This filed indicates data to be transmitted/received. As such there is no hard limit on the size of this variable but whatever is size it must be in integer multiples of `NO_OF_LANES*`LANE_WIDTH. Also this filed will have data of each for one/multiple cycles.

2)curr_lane_en
If this bit is set then driver will corrupt particular lane as indicated by curr_lane_no

3)curr_lane_no[n:0]
This field will indicate which lane is to be corrupted. It could be in between 0 to n lanes supported by rtl.

4)curr_all_lane
This bit when set will corrupt all the lanes.

5)inject_err_en
If this bit is set then driver will inject error particular lane as indicated by inject_err_lane_no

6)inject_err_lane_no[7:0]
This field will indicate in which lane error is to be injected. It could be in between 0 to n lanes supported by rtl.

7)add_run_time skew
If this bit is set then driver will add skews on lane runtime.

8)DeskewLnRtSkew[3:0] , Ln0-15RTSkew[3:0]
When runtime skew is addition is enabled driver add skew values to data lane as per above variables.

Sequencer,sequences:-
Sfis sequencer/sequence will be based on SfisTxn packet. While connecting Sfis UVC to cluster level environment virtual sequencer should take care of converting OTN packets to SfisTxn type.