Sei sulla pagina 1di 55

System Verilog Part II

Random Constraints

Constraint-driven test generation allows users to automatically generate tests for functional verification. Random verification is more effective as compared to traditional directed methodology By specifying constraint one can easily creates testcase that are hard to reach

class Bus; rand bit[15:0] addr; rand bit[31:0] data; constraint word_align {addr[1:0] == 2b0;} endclass

Difference between rand & randc

Rand : standard random variables

rand bit [7:0] y; randc bit [1:0] y; initial permutation:0 3 2 1 next permutation: 2 1 3 0 next permutation: 2 0 1 3 ...

Randc: random cyclic variables

Constraint Block

class XYPair; rand integer x, y; constraint c; endclass // external constraint body declaration constraint XYPair::c { x < y; }

XYPair object1; object1.randomize() both x and y object1.randomize(x) will only randomize x

Constraint block with inheritance

class A; rand integer x; constraint c { x < 0; } endclass

Randomize is a virtual function; So nomatters what handle is the handle of the object , constraint block specific to instance will be used

class B extends A; constraint c { x > 0; } endclass


x dist {100 := 1, 200 := 2, 300 := 5}

x is equal to 100, 200, or 300 with weighted ratio of 1-2-5.

x inside { 5, 10, 15, 20 }; x dist { [100:102] :/ 1, 200 := 2, 300 := 5} A dist operation shall not be applied to randc variables. A dist expression requires that expression contain at least one rand variable.

Implication operator

Implication operator

mode == small -> len < 10; mode == large -> len > 100; if (mode == small) len < 10; else if (mode == large) len > 100;

If else constraints

Iterative Constraints

class C; rand byte A[] ; constraint C1 { foreach ( A [ i ] ) A[i] inside {2,4,8,16}; } constraint C2 { foreach ( A [ j ] ) A[j] > 2 * j; } endclass

Variable Ordering

class B; rand bit s; rand bit [31:0] d; constraint c { s -> d == 0; } constraint order { solve s before d; } endclas

Restriction of value ordering

Only random variables are allowed, that is, they must be rand. randc variables are not allowed. randc variables are always solved before any other. The variables must be integral values. A constraint block can contain both regular value constraints and ordering constraints. There must be no circular dependencies in the ordering, such as solve a before b combined with solve b before a.

In line constraints

class SimpleSum rand bit [7:0] x, y, z; constraint c {z == x + y;} endclass task InlineConstraintDemo(SimpleSum p); int success; success = p.randomize() with {x < y;}; endtask

pre_randomize() and post_randomize()

They are automatically called with randomize()

pre_randomize(); $display(Starting Randomization); post_randomize(); $display(Randomization done);

Rand_mode & constraint_mode

rand_mode is used to define the random mode of particular variable, by default is ON, It can be put into off mode with <var_name>.rand_mode(0) Simlerly constraint mode is used for constraint


System tasks for randomization


addr=$urandom(); Addr= $urandom_range(1000,2000)


Clocking Block

specify any timing disciplines, synchronization requirements, or clocking paradigms. clocking bus @(posedge clock1); default input #10ns output #2ns; input data, ready, enable = top.mem1.enable; output negedge ack; input #1step addr; endclocking

Interface and clocking block

interface A_Bus( input bit clk ); wire req, gnt;wire [7:0] addr, data; clocking sb @(posedge clk); input gnt; output req, addr; inout data; endclocking modport DUT ( input clk, req, addr, output gnt, inout data ); modport STB ( clocking sb ); modport TB ( input gnt, output req, addr, inout data ); endinterface


Two phases: Addr phase, Data Phase

Both phases are latched by Hready , Hsel begin high

Transactions with wait states

Multiple transfers

Hsize tells bout the size of one beat and hburst tells bout the no of beats with Transaction type (INCC/WRAP) Start addr=32'h00000000 hburst=INCR4 Hsize=0 , beat address will be 0,1,2,3 Hsize=1, beat address will be 0,2,4,6 Hsize=2 beat address will be 0,4,8,C

Example for writing constraint

Class ahb_trans; rand bit [31:0] addr;bit [31:0] hwdata,hrdata; bit [1:0] hsize; rand bit [2:0] hburst,htrans; constraint basic; constraint additional; constraint additional0, additional1, additional2; endclass

Constraint for word alighned address

Addr[1:0] ==2'b00

Constraint for generating transaction only with hsize 2'b00

hsize==2'b00 hsize==2'b00 hsize==2'b10

Constraint solver fails

Basic Constraint

Constraint ahb_htrans:: basic { Hsize inside {2'b00, 2'b01,2'b10,2'b11}; Hburst inside {3'b000, 3'b001, 3'b010, 3'b011, 3'b100, 3'b101, 3'b110, 3'b111};

Constraint additional0 { addr inside { [32'h00000000: 32'h0000F000]} }

Constraint additional0 { addr inside { [32'h0000F000: 32'h0001F000]} }

Both constraints can not be on at the same time ahb_trans_object.additional0.constraint_mode(0); ahb_trans_object.additional1.constraint_mode(1);

Parameterised classes

class vector #(int size = 1); bit [size-1:0] a; endclass

class stack #(type T = int); local T items[]; task push( T a ); ... endtask task pop( ref T a ); ... endtask endclass

stack is; stack#(bit[1:10]) bs; stack#(real) rs;


Immediate assertions follow simulation event semantics for their execution

assert_foo : assert(foo) $display("%m passed"); else $display("%m failed");

Concurrent assertions are based on clock semantics and use sampled values of variables


property pr1; @(posedge clk) !reset_n |-> !req; //when reset_n is asserted (0),keep req 0 endproperty

property pr2; @(posedge clk) ack |=> !req; // one cycle after ack, req must be de-asserted endproperty


sequence s; a ##1 b ##1 c; endsequence

sequence rule; @(posedge sysclk) trans ##1 start_trans ##1 s ##1 end_trans; endsequence

Repitition in sequence

Consecutive repitition

(a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b)

(a ##2 b)[*5]

(a ##2 b) or (a ##2 b ##1 a ##2 b) or (a ##2 b ##1 a ##2 b ##1 a ##2 b) or (a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b) is equivalent to (a ##2 b)[*1:4]

a[*0:3] ##1 b ##1 c) (b ##1 c) or (a ##1 b ##1 c) or (a ##1 a ##1 b ##1 c) or (a ##1 a ##1 a ##1 b ##1 c)

Sequence operations

te1 adn te2 are two sequences

Matches if te1 and te2 match The end time is the end time of either te1 or te2 which matches last

Sampled value function


Detects signal gets from 0 to 1 Detects signal goes from 1 to 0 Detects the valus has not changes sinsce last clk



Manipulating data in a sequence

property e; int x; (valid_in,(x = pipe_in)) |-> ##5 (pipe_out1 == (x+1)); endproperty


The assert statement is used to enforce a property as a checker The purpose of the assume statement is to allow properties to be considered as assumptions for formal analysis as well as for dynamic simulation tools. Cover is used to monitor sequences and other behavioral aspects of the design for coverage

Controlling Threads

Concurrency: Thread running in parallal concurrency is essential for verification


If there are multiple threads ready to execute at a given simulation time the order of execution is indetermine; Execution order of threads scheduled at the same time can be manipulated within the code using delays and semaphore


Exchange message objects between otwo threads Features:

FIFO with no size limit get/put are atomic operator, no possible race condition Can suspend a process Default mailbox has no data

mailbox mbx; // Declare a mail box mbx = new(); //allocate mailbox mbx.put(p) ; // put p object into mailbox mbx.get(p);// object is removed from FIFO Success = mbx.try_get(); //non blocking version mbx.peek(p) ; //look but dont remove count = mbx.num(); // no of elements in mbx

Class Driver; Transaction t; task main; repeat (10) begin mbx.get(t); @(posedge clk) .... end endtask endclass

Class generator; Transaction t; task main; repeat (10) begin t =new(); assert(randomize()); mbx.put(t); end endtask endclass

Program mbx_ex(..); Mailbox mbx =new(); Generator g = new () Driver d =new(); Initial begin Fork g.main(); d.main(); Join End endprogram


Used for mutual exclusion and synchronization Variable no of keys can be put and removed Controlled access to a shared object Syntax

Semaphore sem; Semaphore = new(optional_initial_keycount=0); sem.get(optional_num_key=1); sem.put(optional_num_key=1);

Program test; semaphore sem; Initial begin sem=new(1); fork sequencer(); sequenceer() join end ...

Task sequencer(); repeat ($random() %10) @bus.cb; sendTrans();endtask

Task sendTrans(); sem.get(1); ... sem.put(1); endtask


Program test; Event start, check, done; initial begin #10 -> start; #2000 -> done; #10; -> check; end

//generator task main(); wait(start);






An interface encapsulates the connection information An interface can be:

Connected at compile time Connected at run time (Virtual interface)

Interface simple_if (input bit clk); logic grant, request,reset; Clocking cb @(posedge clk); Input grant; output request; endclocking Modport TB (clocking cb,output reset);


Program block

Program test(simple_if.TB s_if); initial begin s_if.reset<=0; #15 s_if.reset=1; #35 s_if.reset=0; //synch drive request ##1 s_if.request<=1 ; ##1 s_if.request <=0; end


Top block

Module top; Bit clk;test t1 (.*); simple_if s_if(clk); dut d1; always #50 clk = !clk;