Tuesday, December 9, 2025

port generation

 Question:

You have a SystemVerilog class that represents a network packet, with the following properties:

  • src_port: a 16-bit integer representing the source port number
  • dst_port: a 16-bit integer representing the destination port number
  • packet_size: a 32-bit integer representing the size of the packet in bytes

You want to write a constraint to ensure that:

  • The src_port and dst_port fields are within the range of 0 to 65535 (inclusive)
  • The src_port and dst_port fields cannot be equal to each other (i.e., they must be distinct)
  • The packet_size field must be within the range of 1 to 1500 (inclusive)
  • At least one of the src_port or dst_port fields must be an even number
  • If the packet_size is greater than 1000, then the src_port field must be greater than 1024

Write a SystemVerilog constraint that satisfies these conditions.

======================================================

/// src dst 

  

  class packet;

    rand int src_port;

    rand int dst_port;

    rand int packet_size;


    constraint src_dst_port_c {

        src_port inside {[0:65535]}; // 0 to 65535 inclusive

        dst_port inside {[0:65535]}; // 0 to 65535 inclusive

        src_port != dst_port; // src_port and dst_port must be distinct

    }


    constraint packet_size_c {

        packet_size inside {[1:1500]}; // 1 to 1500 inclusive

    }


    constraint even_port_c {

        (src_port % 2 == 0) || (dst_port % 2 == 0); // at least one of src_port or dst_port must be even

    }


    constraint large_packet_c {

        (packet_size > 1000) -> (src_port > 1024); // if packet_size > 1000, then src_port > 1024

    }


endclass



// Testbench module

module tb;

    // Create a packet instance

    packet p;


    initial begin

        // Initialize the random seed

        //$random_seed = 1;


        // Create a new packet instance

        p = new();


        // Repeat the randomization and printing process

        repeat (10) begin

            // Randomize the packet fields

            p.randomize();


          $display("src  = %d , dst = %d , pkt size = %d", p.src_port , p.dst_port , p.packet_size );


            // Wait for 1ns before generating the next packet

            #1ns;

        end


        // Wait for 1ns before finishing the simulation

        #1ns;


        $finish;

    end

endmodule


packet generation question

 Q -> 

You have a SystemVerilog class that represents a network packet, with the following properties:

  • addr: a 32-bit integer representing the destination address
  • data: a 16-byte array of bytes representing the packet payload
  • proto: a 2-bit enumeration representing the protocol type (e.g. TCP, UDP, ICMP, etc.)

You want to write a constraint to ensure that:

  • The addr field is randomly assigned a value between 192.168.0.1 and 192.168.0.100 (inclusive)
  • The data field is randomly assigned a value, but with the following conditions:
    • At least 4 bytes of the payload must be non-zero
    • No more than 8 bytes of the payload can be zero
  • The proto field is randomly assigned one of the following values: TCP, UDP, or ICMP

Write a SystemVerilog constraint that satisfies these conditions.

=================================================================

// Define the enum for protocol type

typedef enum {TCP, UDP, ICMP} proto_e;


// Define the packet class with constraints

class packet;

    rand int addr;

    rand byte data[16];

    rand proto_e proto;

    int non_zero_count ;

    int zero_count ;


    // Constraints for packet fields

    constraint addr_c {

        addr inside {[32'hC0A80001 : 32'hC0A86401]}; // 192.168.0.1 to 192.168.0.100

    }



      constraint data_c {

        foreach (data[i]) {

            data[i] dist {0 := 50, [1:255] := 50}; // Uniform distribution for non-zero and zero bytes

        }

    }

    constraint proto_c {

        proto dist {TCP := 1, UDP := 1, ICMP := 1}; // Uniform distribution

    }


    // Method to print packet information

    function void print();

        $display("Packet Information:");

        $display("  Address: %d", addr);

        $display("  Data: ");

        foreach (data[i]) begin

            $display("    byte[%0d] = %d", i, data[i]);

        end

        case (proto)

            TCP: $display("  Protocol: TCP");

            UDP: $display("  Protocol: UDP");

            ICMP: $display("  Protocol: ICMP");

        endcase

    endfunction


endclass


// Testbench module

module tb;

    // Create a packet instance

    packet p;


    initial begin

        // Initialize the random seed

        //$random_seed = 1;


        // Create a new packet instance

        p = new();


        // Repeat the randomization and printing process

        repeat (10) begin

            // Randomize the packet fields

            if (!p.randomize()) begin

                $error("Failed to randomize packet");

            end


            // Print the packet information

            p.print();


            // Wait for 1ns before generating the next packet

            #1ns;

        end


        // Wait for 1ns before finishing the simulation

        #1ns;


        $finish;

    end

endmodule


Tuesday, December 2, 2025

Write code that will create the four processes. Process_C should begin when Process_A has finished, and then Process_D. However, Process_B ought to wait for Process_D to finish.

 module tb; 

event process_A_done; // Declare events for synchronization 

event process_D_done; 

event process_C_done; 

initial 

begin 

fork: process_fork

begin: process_A 


$display("Process_A completed %0t",$time);

 -> process_A_done; // Trigger process_A_done event 

end 

begin: process_B 

wait(process_D_done.triggered); // Wait for process_B_done event 


 $display("Process_B completed %0t",$time); 

end 

begin: process_C 

wait(process_A_done.triggered);


$display("Process_C completed %0t",$time); 

-> process_C_done; 

end 

begin: process_D 

wait(process_C_done.triggered); 


$display("Process_D completed %0t",$time); 

->process_D_done; 

end 

join

end

endmodule


Key points - events , wait , -> , triggered , 

wait_order Waits for events to be triggered in the given order, and issues an error if any event executes out of order.


Friday, November 21, 2025

Check duty cycle of a clock

 High time check:

@(posedge clk) (1, start_t = $realtime) |-> @(negedge clk) ($realtime - start_t == half_period);


Low time check:
@(negedge clk) (1, start_t = $realtime) |-> @(posedge clk) ($realtime - start_t == half_period);

Write a system verilog assertion to check clock of 50 MHz

 // Code your testbench here


// or browse Examples


module clk_check;


     timeunit 1ns;     


   timeprecision 100ps;  


realtime clk_period = 20.0/1.0ns; 


bit clk, RESET_N, ENABLE;


  property T_clk(real clk_period);


time current_time;


// disable iff(!RESET_N || !ENABLE)


(('1,current_time=$realtime) |=>


         (clk_period <= $realtime-(current_time-0.001ns))  &&


         (clk_period >= $realtime-(current_time + 0.001ns))); 


endproperty


 


assert_period:assert property (@(posedge clk)T_clk(clk_period))


$display("%t TB_INFO : clk  correct",$realtime); 


else


$warning("%t TB_INFO : clk not correct",$realtime);


initial forever #10 clk=!clk; 


initial begin 


$display("START CHECKING ");


repeat(10) @(posedge clk); 


// $display("%t %t TB_INFO : clk  correct",$realtime, $realtime);


$finish; 


end


   


endmodule : clk_check 

Thursday, November 20, 2025

Check that when A goes HIGH , B goes HIGH for 1 to 3 cycles within the next 10 cycles

 $rose(A) |-> B[=1:3] throughout 1'b[*10]

Generate Non overlapping addresses

 Start address 

 End address 

Cannot be over lapping.

class a;

      rand   bit [31:0]  start_address[] ;

      rand   bit [31:0]  end_address[] ;

      rand   int size ; 

      //100 -1000

      //1000-5000

  constraint c1 {

        foreach(start_address[i]) start_address[i] != end_address[i] ;

    }                      


  constraint c2 {

    foreach(start_address[i]) 

      foreach(start_address[j])

        if(i!=j) 

          !(start_address[j] inside {[start_address[i]:end_address[i]]}); }                      

  constraint c3 {

    foreach(end_address[i]) 

      foreach(end_address[j])

        if(i!=j) 

             !(end_address[j] inside {[start_address[i]:end_address[i]]}) ;}                 

  endclass


module top ;

  a a1;

  initial begin 

    a1 = new();

    a1.start_address= new[20];

    a1.end_address = new[20];

    repeat (20) begin

      a1.randomize();

      //foreach(a1.start_address[i])

      $display("start addr = %p ", a1.start_address );

        $display("end addr = %p",  a1.end_address );

    end 

  end

  

endmodule


    

Wednesday, November 19, 2025

flight scheduler - SV randomization

 Q. How many combinations can be there for the below scenario?

There are 3 flights and 8 passengers (a,b,c,d,e,f,g,h) 

1.a and b should always be together 

2. each flight needs to fly . minimum passengers that can go in an flights are = 1 , 

Maximum passengers that can go in an flights are = 4 .

Answer : 

Instaed of manually thinking of all scenarios , we can write in in system verilog . (using constarints) .

1. create an enum of passengers 

 typedef enum {a,b,c,d,e,f,g,h} passenger ;

2. create a queue called flight like this :

    passenger flight[]; 

// Code your testbench here

// or browse Examples

class FlightScheduler;

  // Passenger list

  typedef enum {a, b, c, d, e, f, g, h} passengers_t;


  // The flights array stores the flight allocation for each passenger

  rand passengers_t flights[8]; // Array of flight assignments for 8 passengers

  rand int flight_count[3];     // Number of passengers on each flight (0, 1, 2)


  constraint flight_constraints {

    // Each passenger must be assigned to one of the three flights

    foreach (flights[i]) flights[i] inside {0, 1, 2};


    // Ensure passengers 'a' and 'b' always travel together

    flights[0] == flights[1]; // Both passenger a and b travel on the same flight


    // Count how many passengers are on each flight

    foreach (flight_count[i]) {

      flight_count[i] == (flights.count(i)); // Count passengers in flight i

    }


    // Each flight must have between 1 and 4 passengers

    foreach (flight_count[i]) flight_count[i] inside {[1:4]};

  }


  // Display the flight assignments

  function void display_flight_allocation();

    $display("Flight assignments:");

    foreach (flights[i]) begin

      $display("Passenger %0d -> Flight %0d", i, flights[i]);

    end

    $display("Flights distribution: Flight 0: %0d, Flight 1: %0d, Flight 2: %0d",

             flight_count[0], flight_count[1], flight_count[2]);

  endfunction

endclass


// Testbench

module tb_flight_scheduler;

  initial begin

    FlightScheduler scheduler = new();

    if (scheduler.randomize()) begin

      scheduler.display_flight_allocation();

    end else begin

      $display("Failed to randomize!");

    end

  end

endmodule

Q.  3*3 Array question :


class A ;

  rand int mem[3][3];

  constraint c1{ 

      unique{mem}; 

    foreach(mem[i,j]) 

    {

      mem[i][j] inside {[1:9]}; 

    }

  };

    

  constraint c2{

    foreach(mem[i])

    {

      foreach(mem[k])

      {

        mem[i].sum() == mem[k].sum();

      } 

    }

  };

      

  constraint c3{

    foreach(mem[,j])

    {

      foreach(mem[,k])

      {

        mem.sum() with (mem[item.index][j]) == mem.sum() with (mem[item.index][k]);

      } 

    }

  }; 

  

endclass




module t();

  A a_h ;

  initial begin

   a_h = new ; 

      a_h.randomize();

      $display("value is %p", a_h.mem); 

   end 

endmodule

       

Thursday, November 13, 2025

Fifo depth , randc function using rand

Calculate the depth of FIFO :

Writing frequency = fA = 80MHz. Reading Frequency = fB = 50MHz. Burst Length = No. of data items to be transferred = 120. There are no idle cycles in both reading and writing which means that, all the items in the burst will be written and read in consecutive clock cycles.

====================================================================

Ans:  1 write = 80 MHZ = 12.5 ns   (  1MHz is 1000 ns) 

        120 writes = 120*12.5 ns = 1500 ns 

        reading 1 = 50 MHz = 20 ns  

       in 1500 ns how many reads = 1500/20 = 75 

  deapth = wrire -read = 120-75 = 45  

=============================================

Question 

 Writing Side = 80 words in 100 clocks • Reading Side = 8 words in 10 clocks • BURST wr 160 

What will be the FIFO depth 

=======================================================

Solution : • Worst scenario of overflow of data is when there is 160 clocks of continuous write. Lets assume first 20 cycle is idle and then 80 clock cycle writing. Other set of writing starts at 101 clock cycle. Worst scenario : 160 words are written in 160 clocks Reading possibility : 8*16 = 128 words can be read So depth of FIFO : 160-128 = 32


================

constraint for a rand variable to behave like a randc.

credit https://www.linkedin.com/pulse/constraint-45-mohamed-irsath-i-qs58c/ 

In order to achieve the requested constraint, we first need to understand the difference between rand and randc variables.

Rand: By defining a variable as rand, it becomes an active variable when you randomize the object created for the class where the variable is defined. While randomizing, it will take possible values that obey the constraints written for that variable. If no constraints are specified, it can generate any value in its range and may repeat the same value multiple times without producing all possible values.

Randc: randc behaves similarly to rand, but with an additional feature denoted by the "c" for cyclic. This cyclic behavior allows the variable to generate all possible values, but without repeating any value until it has generated all possible values at least once.

For example, consider a 3-bit variable a. If a is declared as rand, it can take any value from 0 to 7 while randomizing. It may repeat values before generating all values from 0 to 7. On the other hand, if a is declared as randc, it won't repeat any generated value until it has generated all values from 0 to 7.

class sample;
  rand  bit [2:0] rand_a;
  bit [2:0] rand_q[$];
  
  constraint rand_a_c {
    unique{rand_a,rand_q}; 
  }
  
  function void post_randomize();
    if(rand_q.size() == 7) rand_q.delete();
    rand_q.push_back(rand_a);
  endfunction
endclass

module top;
  sample s=new();
  initial begin
    $display("############## OUTPUT ###############");
    $display("the Behvariablef rand variable as randc");
  	repeat(10) begin
    	s.randomize();
      $display(" rand_a = %0d",s.rand_a);
      $display(" rand_q = %p",s.rand_q);
  	end
    $display("see there is no repetition till \n it generate 0 to 7 \n even though it is a rand variable ");
    $display("################ END ################");
  end
endmodule

 Things to prepare : 

byte wise sorting a queue in system Verilog 

reverse a fifo

constraints related 


1. Few questions on writing constraints for certain scenarios. 2. FSM for number divisible by 3 3. UVM subscriber, sequences, TLM ports and FIFO. 4. write code for random number generation for given distribution and ranges. 5. byte addressing in an integer memory system. 6. constrain for non-overlapping segment-addresses generation. 7. Explain any testbench architecture you have worked on. 8. Lots of simple questions to test SystemVerilog and OOP concepts.



1.  have a 7 bit par_groups. Every time I randomize, I need to pick 3 groups that are unique and less than 32. Below is an example on how I did it.

Is there an better way to do it? This does not scale well. If I need to pick 15 unique groups from 32, this becomes a not so good solution.


Ans 

class example1;
 
  rand bit [6:0] par_groups; // why is this size different?
  rand bit[4:0] group[3];
 
  constraint group_c{unique {group};}
 
  constraint par_groups_c{par_groups inside {group};}
 
  function void post_randomize();
    $display("group = %p", group);
  endfunction  
 
endclass