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
verilog | systemverilog | |
---|---|---|
task | Can consume time (can use #100) | Same as v |
function | You 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't | Allows 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