System Verilog notes Procedure statements and subroutines

Posted by jhenary on Mon, 20 Dec 2021 01:22:40 +0100

Chapter III procedure statements and subroutines

1. Procedure statement

sv absorbs some features of C + +, including break and continue statements.

//for loop statements and do... while statements
initial begin:example             //You can give this initial a number and name, which is called example here
    integer a[10],sum,j;
    
    for(int i=0;i<10;i++)        //Assign a value to each array element
        a[i]=i;
    
    sum=0;    
    j=9;
    do
        sum+=a[j]               //Add and sum each element of the array
    while(j--);
    
    $display("Sum is %4d",sum);
end :example

Examples of reading files

initial begin
	bit[127:0] cmd;
	int file,c;
	
	file=$fopen("a.txt"."r");
	while(!$feof(file)) begin
    c=$fscanf(file,"%s",cmd); //cmd reads a row of data
	case(cmd)
		"": continue;         //Read the blank line and continue reading
        "done": break;        //Read done and end the while loop
	endcase
    end
	$fclose(file);
end

2. task and function

verilogsystemverilog
taskCan consume time (can use #100)Same as v
functionYou can't call task, delay statements and blocking statements (you can't use #100, wait (), posedge and other statements). In other words, tasks can consume time, but functions can'tAllows functions to call functions, but can only be invoked in threads generated by (fork... join_none statement).
//If you need a task that does not consume time, you can use the function void function
function void print_state(...);
	$display("@%0t:state=%s",$time,cur_state.name());
endfunction

//If you want to call a function and ignore the return value, you can use void '(available in some emulators)
void'($fscanf(file,"%d",i));

In sv, begin... end is no longer required for both task and function definitions (obviously in V).

3. Subroutine

3.1 subroutine parameters

As we all know, in a C language function program, you can not only copy variables, but also directly modify the size of variables through pointers. This pointer technology is also used in sv, which can be referenced (ref) instead of copying. Now, you can pass the array to the function to modify the array directly, which is equivalent to giving a pointer to the array.

//Use ref and const to pass arrays
function void print_checksum(const ref bit[31:0] a[]);
	bit [31:0] checksum = 0;
	for(int i=0;i<a.size();i++)
		checksum^=a[i];
	$display("The array checksum is %0d",checksum);
endfunction
//const here is used to ensure that the value size of the array corresponding to the pointer is not modified
//Using ref ensures that the variable is modified and that the modification result is visible to the calling function
//In sv, you can also pass an array without ref, but this operation actually copies the array to the local variable stack where the function is located

Functions can also use default values

function void print_state(input int low=0,input int high=-1);
endfunction

print_state();     //low=0,high=-1
print_state(1,3);  //low=1,high=3
print_state(,2);   //low=0,high=2

It is believed that normal people should know that the instantiation method in v is used a(a) in this mode, if there are too many function parameters, port transfer can also be adopted.

function void print_state(input int a=1,b=2,c=3,d=4);
endfunction

print_state();         //1,2,3,4 default values
print_state(5,6,7,8);  //5,6,7,8 specify all values
print_state(.a(2));    //2,2,3,4 port mode
print_state(.a(2),3);    //2,3,3,4 mixed mode

By default, the type of the parameter is the same as that of the previous parameter.

task s(ref int a[10],int b,c);
//Since b and c do not indicate the direction, it defaults to ref, but ref is obviously invalid for int, so it needs to be modified as follows
task s(ref int a[10],input int b,c);

3.2 subroutine return

In sv, you can use return statements in task and function.

Three ways to return an array

//1. Define an array type and return the new data type
typedef int my_arrray[5];  //Defines a type that is an array of five elements
my_array f5;

function my_array init(int start)
	foreach(init[i])
		init[i]=i+start;
endfunction

initial begin
	f5=init(5);
	foreach(f5[i])
		$display("f5[%0d]=%0d",i,f5[i]);
end

//2. Use ref reference to return the array
function void init(ref int f[5],input int start)
    foreach(f[i])
		f[i]=i+start;
endfunction

int fa[5];
initial begin
    init(fa,5);
    foreach(fa[i])
        $display("fa[%0d]=%0d",i,fa[i]);
end

//3. Wrap the array into a class, and then return the handle of the object (to be supplemented)

4. Local data storage

4.1 automatic access

Multiple calls to the same task in verilog will cause overwriting because local variables use shared local static variables. Therefore, you need to use the following statement to force the stack to access.

program automatic test;

endprogram

4.2 variable initialization

In fact, local static variables have been assigned before simulation, rather than in begin and end statements.

Workaround 1 automatic

program automatic test;

endprogram

Solution 2: split declaration and initialization

logic [31:0] local_addr;

local_addr = addr<<2;

5. Time value

//Both $time and $realtime can return time, but the former is an integer and the latter is a decimal

//time cannot save decimal delay. If decimal delay is required, real needs to be used
`timescale 1ps/1ps
module ps;
	initial begin
		real a = 800 fs;
		time b = 800 fs;
		$display("%t",a);   //800fs
		$display("%t",b);   //1000fs,time will be rounded
end
endmodule

//timeuint (unit), timeprecision (minimum precision)
//$timeformat (time scale, number of digits after decimal point, suffix string, width of displayed value) - 9 is ns, and - 12 is ps
module time;
    timeuint 1ns;
    timeprecision 1ps;
    initial begin
        $timeformat(-9,3,"ns",8);
        #1 $display("%t",$realtime);  //1.000ns;
        #2ns $display("%t",$realtime);  //3.000ns;
        #0.1ns $display("%t",$realtime);  //3.100ns;
        #41ps $display("%t",$realtime);  //3.141ns;
        end
endmodule

Topics: systemverilog