sv_labs learning notes - sv_lab4(System Verilog)

lab4 OOP encapsulation

Experimental overview

OOP encapsulation means object-oriented encapsulation. What Lab4 does is encapsulate some group information into a Packet class. Then call the class to implement the same function of lab3. Implementation block diagram

You can see. The experiment deals with the data sent and collected by gen(). The rest is lab3 consistent.

Task code parsing

First implement the Packet.sv file, and then modify the test program

Package implementation and understanding

Similarly, here is a simple modification to compare. Students can compare the writing method in the original solution with that here. The code is as follows.

`ifndef INC_PACKET_SV
`define INC_PACKET_SV
class Packet;
    rand bit[3:0] sa, da;
    rand logic[7:0] payload[$];
    string   name;
    
    constraint valid {
		sa inside { [0:15] };
		da inside { [0:15] };
		payload.size() inside { [2:8] };
}
    extern function new(string name = "Packet");//The default parameter passed in here is Packet
    extern function bit compare(Packet pkt2cmp, ref string message);// need a package
    extern function void display(string prefix = "NOTE");
endclass: Packet

function Packet::new(string name);
    this.name = name;
endfunction: new

function bit Packet::compare(Packet pkt2cmp, ref string message);
    if(payload.size() != pkt2cmp.payload.size()) begin//The payload.size of the incoming package is compared with that of the class variable
        message = "Payload size Mismatch:\n";
        message = { message, $sformatf("payload.size() = %0d, pkt2cmp.payload.size() = %0d\n", payload.size(), pkt2cmp.payload.size()) };
        return (0);
    end
    if(payload == pkt2cmp.payload) ;
    else begin
        message = "Payload Content Mismatch:\n";
        message = { message, $sformatf("Packet Sent:   %p\nPkt Received:   %p", payload, pkt2cmp.payload) };
        return (0);
    end
        message = "Successfully Compared";
        return(1);
endfunction: compare

function void Packet::display(string prefix);
    $display("[%s]%t %s sa = %0d, da = %0d", prefix, $realtime, name, sa, da);
    foreach(payload[i])
        $display("[%s]%t %s payload[%0d] = %0d", prefix, $realtime, name, i, payload[i]);
endfunction

Let's first look at the specific members in the package. The variable members contained in the package are as follows.

  • Random variables sa and da. Is the sending address and the source address.
  • The random variable queue payload is used to store the data sent or received.
  • String variable name. The ID of each Packet class, which is used for debugging and printing related information. For debugging
  • Constructor new()
  • The compare function is used to compare whether the received and transmitted data are consistent
  • Finally, the display function is used to print the comparison results

Syntax point parsing

extern

SV allows you to declare examples outside a block. Use the keyword extern. Examples are as follows

class Transaction;
	extern function void display ();
endclass

function void Transaction::display ();
	$display ("...");
endfunction
`Use of ifndef macro definition

`ifndef/`define/`endif is used to prevent repeated compilation. Take an example.
a. SV contains two files b.sv and c.sv. At the same time, b.sv and c.sv contain d.sv respectively. When compiling a.sv at this time, d.sv will be compiled repeatedly. Adding ` ifndef/`define/`endif will not introduce the above problems.

this.name = name;

Assign the passed parameter to a variable in a class
When you use a variable name, system Verilog will first look in the current scope, and then look in the upper scope until the variable is found. This is also the algorithm used by Verilog. But what if you want to explicitly reference class level objects in the deep underlying scope of a class? This style of code is most common in constructors because programmers use the same class variable name and parameter name. The keyword this can realize this function.

class Scoping;
	string oname;
	function new ( string oname ) ;
		this.oname = oname // Class variable oname = local variable oname
	endfunction
endclass
$sformatf
$sformatf("payload.size() = %0d, pkt2cmp.payload.size() = %0d\n", payload.size(), pkt2cmp.payload.size())

The return value of $sformatf is a string. The incoming content will be sorted and a string property will be returned.

Random constraint

Random and constrained time are two concepts. Refer to Chapter 6 of the green paper, randomization

randomconstraint
rand bit[3:0] sa, da; A random variable is defined, and the RAND modifier is used to indicate that each time the class is randomized, a value will be given to the variable.Use constraints to process random values. The keyword is constraint

sa inside { [0:15] }; SA is in the range of 0-15

Implementation and understanding of main program

We have omitted the code consistent with lab3. The main modifications are gen(),recv() and check. Relevant comments are placed in the code

`include "Packet.sv"
program automatic test(router_io.TB rtr_io);
    int run_for_n_packets;
    bit[3:0] sa;
    bit[3:0] da;
    logic[7:0] payload[$];
    logic[7:0] pkt2cmp_payload[$];      // actual packet data array

    Packet pkt2send = new();
	//Use similar classes. The new() function opens up space for two packets. The packet is used for sending and is used in the gen() function. It is also used in the check() function
    Packet pkt2cmp  = new();
initial begin
    ...//Consistent with lab3
end

task reset();
    ...//Consistent with lab3
endtask: reset

task gen();
	static int pkts_generated = 0;//Static variable
	pkt2send.name = $sformatf("Packet[%0d]", pkts_generated++);
    if(!pkt2send.randomize()) begin //Call the function to check whether the initialization status is successful. call function randomize. meanwhile check it's work situation 
	    $display("\n%m\n [ERROR] %t: Randomize Error!!", $realtime);
        $finish;
	end 
    sa = pkt2send.sa; //Transmit random results to sa
    da = pkt2send.da; 
    $display("this package from sa = %0d ,and da = %0d",sa,da);
    payload = pkt2send.payload;
endtask: gen

task send();
	...//Consistent with lab3
endtask: send

task recv();
	static int pkt_cnt = 0;
    get_payload();
    pkt2cmp.da = da;//Send the received address to the received packet variable
    pkt2cmp.payload = pkt2cmp_payload;//Send the received data to the received packet variable
    pkt2cmp.name = $sformatf("rcvdPkt[%0d]", pkt_cnt++);
endtask : recv 

task get_payload();
	...//Consistent with lab3
endtask: get_payload

task check();
    string message;
    static int pkts_checked = 0;
    if (!pkt2send.compare(pkt2cmp, message)) begin // need two package,need to use payload data compare with introduce package data. will print two package some information about address,data.
	//Pass pkt2cmp into the pkt2send.compare() function. Compare the variables of the original class with those sent in. Judge whether it is successful. The ref parameter is used for the string parameter here. You can change the value of message in the function
        $display("\n%m\n[ERROR]%t Packet #%0d %s\n", $realtime, pkts_checked, message);
        pkt2send.display();
	    pkt2cmp.display();
        $finish;
    end
    $display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);
endtask: check
endprogram: test

Syntax point parsing

`include

The so-called "file inclusion" processing means that one source file can include all the contents of another source file, that is, another file can be included in this file. You can compose some common macro definition commands or tasks into a file, and then use the ` include command to include these macro definitions in your own source file, which is equivalent to the standard components in the industry.

Understanding of ref

click here ref . The simple explanation is that if you change message in the function, the value of the message variable will change.

reference resources

Tags: systemverilog

Posted on Sat, 04 Dec 2021 19:30:17 -0500 by DWaller10