In fact, when writing design or verification, the code basically unloads tasks or functions. This chapter mainly introduces the improvement of SV like C language - processing parameter cases.
3.1 procedure statement
- Loop variables are defined in the for loop, and the scope is limited to the inside of the loop to avoid some code vulnerabilities.
- Auto increment / decrement
- An identifier can be used in a begin/fork statement and the same label can be placed in its corresponding end or join statement.
Example:
initial begin:example integer array[10],sum,j; // Declare i in a for statement for(int i=0;i<10;i++ ) array[i]=i; // Add the elements of the array sum = array[9]; j=8; do sum+=array[j]; // while Loop while(j--); $display("Sum=%4d",sum); // %4d - specify width end: example // continue and break functions can also be added to the loop. initial begin bit[127:0] cmd; int file,c; file = $fopen("commands.txt",'r'); while(!$feof(file)) begin c = $fscanf(file,"%s",cmd); case(cmd) "": continue; //Empty line, terminate this cycle "done": breakļ¼// Terminate and jump out of loop .... endcase end $fclose(file); end
3.2 tasks, functions and void functions
In Verilog, there is an obvious difference between any and functions. The biggest difference is that the task can consume time, and the function cannot have delay statements such as #100 or blocking statements such as @ (pose clock) and wait(ready), nor can it call the task. The function must have a return value and must be used (basically used in assignment statements).
In SV, if there is a task that does not consume time, it should be defined as void() function, which can be called by functions and tasks at this time.
Example: void function for debugging
function void print_state(...); $display("@%0t:state=%s",$time,cur_state.name()); endfunction // Some emulators allow the return value to be ignored when void is not applicable.
3.3 task and function overview
A slight improvement: subprograms without parameters do not need empty parentheses when they are defined or called.
3.3.1 remove begin... end from the subroutine
It is optional in SV and must be carried for multi line subroutines in Verilog.
// Without begin end task multiple_lines; $display("First line"); $display("Second line"); endtask:multiple_lines
3.4 subroutine parameters
The improvement in SV makes the declaration of parameters more convenient, and extends the transmission mode of parameters.
Verilog directly replicates the passed parameters, and the parameter passing method in SV - ref is reference rather than copy.
// Using ref between multiple threads task bus_read(input logic[31:0] addr, ref logic [31:0] data); // Request bus and drive address bus.request =1'b1; @(posedge bus.grant) bus.addr = addr; // Waiting for data from memory @(posedge bus.enable) data = bus.data; // Release the bus and wait for permission bus.request = 1'b0; @(posedge bus.grant); endtask logic[31:0] addr,data; initial fork bus_read(addr,data); thread2:begin @data; // Triggered when data changes $display("Read %h from bus",data); end join
3.4.4 default values of parameters
Set a default value for the parameter in SV. If the parameter is not specified during the call, the default value is used.
function void print_checksum(ref bit[31:0] a[], input bit[31:0] low=0, input int high =-1); bit[31:0] checksum =0; if(high==-1 || high>=a.size()) high = a.size()-1; for(int i=low;i<high;i++) checksum+=a[i]; $display ("The array checksum is %0d",checksum); endfunction // Call using parameter defaults print_checksum(a); // Checksum of all elements in a[0:size-1] print_checksum(a,2,4); // Checksum of all elements in a[2:4] print_checksum(a,1); // Start with 1 print _checksum(a, ,2); //Checksum of all elements in a[0:2] print_checksum(); // Compilation error: a has no default value // Use - 1 (or any other out of bounds value) as your default value to determine whether the specified value is given during the call
3.4.5 parameter transfer by name
In SV language, the parameters of any or function are sometimes called port "port", just like the interface of the module.
// Parameter passing by name task many(input int a=1,b=2,c=3,d=4); $display("%0d %0d %0d %0d",a,b,c,d); endtask initial begin many(6,7,8,9); //a,b,c,d many(); // Use Default many(.c(5)); // Specify only c many(,6,.d(8)); // Mixed mode end
3.4.6 clearly indicate the direction of all parameters
task sticky(ref int array[50], input int a,b); // Clearly specify the direction
3.5 return of subroutine
In Verilog, it is the last statement after executing the subroutine, and the program will return to the code of the subroutine. In addition, the function returns a value assigned to a variable with the same name as the function. Add a return statement to SV. It will return when it encounters a return.
3.5.1 return an array from a function
Only one simple value can be returned in Verilog, such as bit, integer or vector.
In SV, the function returns an array in many ways.
//The first is to define an array type and then use it in the declaration of the function typedef int fixed_array5[5]; // Define a new array type fixed_array5 f5; function fixed_array5 init(int start) foreach(init[i]) init[i] = i+start; endfuncton initial begin f5 = init(5); foreach(f5[[i]]) $display("f5[%0d] =%0d", i,f5[i]); end // When creating an array, the array value is assigned, which wastes space // Second: use reference 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",fa[i]); end // The third method: encapsulate the array into a class, and then return the handle of the object
3.6 local data storage
Verilog hardware language allocates data statically, especially subroutines and local variables are placed in fixed positions. The C preloading equation is stored based on the stack area.
In the latest version of Verilog, you can specify that tasks, functions and modules use automatic storage - stack area, forcing the emulator to use stack area. In SV, module and program blocks use the keyword automatic to use the stack area.
Example: a task for monitoring when data is written to memory
program aumomatic test; task wait_for_mem(input [31:0] addr, expect_data, output success); while(bus.addr!=addr) @(bus.addr); success = (bus.data ==expect_data); endtask ....... endprogram
3.6.2 initialization of variables
Example: after monitoring the bus for five cycles, create a local variable and assign the value of the current address bus to it as the initial value
program automatic initialization; task check_bus; repeat(5) @(posedge clock); if(bus_cmd ='READ) begin //When to local_addr initial value logic[7:0] local_addr =addr<<2; $display("Local Addr=%h",local_addr); end endtask endprogram
3.7 time value
The new structure in SV helps to indicate the time value in the system
3.7.1 time unit and accuracy
Statement: ` timescale time unit / time precision
3.7.2 time parameters
Delay after formatting with $timeformat() and% t specifier
3.7.3 time and variables
This specific encounter will be more understandable. Now I'm confused.
- $time: the return value is an integer rounded according to the time precision requirements of the module, without decimal part.
- The return value of $realtime is a complete real number with a decimal part.
3.8 summary
The programming structure in SV, that is, the new characteristics of any and functions, makes it closer to the characteristics of C + +, which is convenient to write the test platform.
Compared with C + +, SV has its own special structure, timing control, simple thread control and four state logic.