Thursday, February 28, 2013

Clock Generation with jitter

System Verilog Code:-

//---------------------------------------------------------------------------------------
// Name: jitter_clock_gen
// Author: Bharath Kumar Y
// Description: This module will generate a clock with
//              period                = 16ps
//              Max Skew/half clock   = +/-1ps
//              Max Skew/clock period = +/-2ps
// Copyright (C) Bharath Kumar Y
//----------------------------------------------------------------------------------------

`timescale 1ps/1ps

module jitter_clock_gen;
//Initializations
  bit req0=0;
  bit clk=0;
  integer seed;
  real zero_time=0;
  real one_time=8;


// Just to run the sim for some good amount of time to get
// enough clock edges
initial begin
  # 100 $finish;
end

// Actual clock generation clock
always
  #(8+$dist_uniform(seed,-1,1)) clk = ~clk;

// Checking of clock geneation implemented using
// Immediate assertions
// This block will assert errors when the
// half clock period != 8
always @* 
begin
  if(clk==0) begin
    req0=1;
    zero_time = $realtime;
    $display("zero_time = %t",$realtime);
    assert(!(($realtime<(one_time+8))));
    assert(!(($realtime>(one_time+8))));
  end

  if (req0==1 && clk==1) begin
    req0=0;
    one_time=$realtime;
    $display("time:%t:-req0=%b,req=%b",$realtime,req0,clk);
    assert(!(($realtime<(zero_time+8))));
    assert(!(($realtime>(zero_time+8))));
  end
end

endmodule


Output for the same code using ncsim:-

ncsim> run
zero_time =                   15
ncsim: *E,ASRTST (./fun1.sv,41): (time 15 PS) Assertion jitter_clock_gen.__assert_1 has failed
time:                  22:-req0=0,req=1
ncsim: *E,ASRTST (./fun1.sv,49): (time 22 PS) Assertion jitter_clock_gen.__assert_3 has failed
zero_time =                   29
ncsim: *E,ASRTST (./fun1.sv,41): (time 29 PS) Assertion jitter_clock_gen.__assert_1 has failed
time:                  37:-req0=0,req=1
zero_time =                   46
ncsim: *E,ASRTST (./fun1.sv,42): (time 46 PS) Assertion jitter_clock_gen.__assert_2 has failed
time:                  53:-req0=0,req=1
ncsim: *E,ASRTST (./fun1.sv,49): (time 53 PS) Assertion jitter_clock_gen.__assert_3 has failed
zero_time =                   60
ncsim: *E,ASRTST (./fun1.sv,41): (time 60 PS) Assertion jitter_clock_gen.__assert_1 has failed
time:                  68:-req0=0,req=1
zero_time =                   76
time:                  85:-req0=0,req=1
ncsim: *E,ASRTST (./fun1.sv,50): (time 85 PS) Assertion jitter_clock_gen.__assert_4 has failed
zero_time =                   93
Simulation complete via $finish(1) at time 100 PS + 0
./fun1.sv:26   # 100 $finish;

Wednesday, February 27, 2013

UVM Ports - Illustrated

There is always this question as to when to use uvm_analysis_port, uvm_analysis_export and uvm_analysis_import

The below diagram illustrates the correct use of all types of ports mentioned above through the 'Stacked UVCs' example.  This diagram illustrates the connection of BOTTOM UVC's monitors with the monitors of TOP UVCs. 

The requirement here is that any of the BOTTOM UVCs can be connected to any of the TOP UVCs. This means that we need to have a router component with uvm_analysis_exports since only exports can forward the data coming from the source 'port's of BOTTOM UVC's monitors. BOTTOM UVC's Monitor is the originator of the transacation and hence its required to have the uvm_analysis_port.

Monitors of the TOP UVCs are supposed to have the uvm_analysis_imports as they are the ultimate consumers of the transactions

Monday, February 11, 2013

UVM Questions - 6

                                               Courtesy - Paradigm Works Inc

 Q:  Why there should be a seperate sequencer and driver in an UVM agent?
                                              OR
 Q:  Why UVM doesn't have single component which combines Driver and Sequencer?


Firstly,
     Typically if you are dealing with a packet/frame with layered architecture where lower layer level data encapsulate the higher layer level data. In this case its better to architect the UVC in a layered way.  This renders the testbench modular and facilitates the easy reusability and parallel development of Testbench.
    Once we do the layered architecture of UVCs, only Bottom UVCs need to have Driver since its attached to the DUT interface, higher leayer UVCs don't need to have driver since they don't attach to any DUT interface instead they attach to the bottom UVCs. Higher layer sequences in the sequencer interact with to the lower level UVCs through sequence item as shown in the above diagram.

Secondly,
     At the SoC level verification environment, its often required to use the virutal sequences to sequence/bypass the lower level sequences
                                   Courtesy - Accellera UVM1.1 User guide

As per the guide,

     There are three ways in which the virtual sequencer can interact with its  subsequencers:
a) “Business as usual”—Virtual subsequencers and subsequencers send transactions simultaneously.
b) Disable subsequencers—Virtual sequencer is the only one driving.
c) Using grab() and ungrab()—Virtual sequencer takes control of the underlying driver(s) for a limited time


(b) and (c) makes the separation of sequencer and driver obvious and hence they are independent components in UVM. Without this seperation, its difficult for virtual sequencer to grab the control of the underlying drivers and achieve interesting scenarios at the SoC/full chip level testbench.