SystemVerilog -- 3.10 SystemVerilog Functions
SystemVerilog Functions
SystemVerilog函数具有与Verilog中的function
相同的特征。
Functions
a的主要用途是返回一个可在表达式中使用且不能消耗模拟时间的值。function
function
不能具有时间控制语句,如@
#
fork join
wait
function
无法启动task
,因为允许task
消耗模拟时间。
ANSI-C style declaration
module tb;
// There are two ways to call the function:
initial begin
// 1. Call function and assign value to a variable, and then use variable
int s = sum(3, 4);
$display ("sum(3, 4) = %0d", s);
// 2. Call function and directly use value returned
$display ("sum(5, 9) = %0d", sum(5, 9));
$display ("mul(3, 1) = %0d", mul(3, 1));
end
// This function returns value of type "byte", and accepts two arguments "x" and "y". A return variable of the same name as function is implicitly declared and hence "sum" can be directly assigned without having to declare a separate return variable
function byte sum (int x, int y);
sum = x + y;
endfunction
// Instead of assigning to "mul", the computed value can be returned using "return" keyword
function byte mul (int x, y);
return x * y;
endfunction
endmodule
模拟日志
ncsim> run
sum(3,4) = 7
sum(5,9) = 14
mul(3,1) = 3
ncsim: *W,RNQUIE: Simulation is complete.
Using declarations and directions
尽管后来在Verilog中引入了ANSI-C样式的声明,但端口方向的旧式声明仍然有效。SystemVerilog function可以将参数声明为输入和输出端口,如以下示例所示。
module tb;
initial begin
int res, s;
s = sum(5, 9);
$display ("s = %0d", sum(5, 9));
$display ("sum(5, 9) = %0d", sum(5, 9));
$display ("mul(3, 1) = %0d", mul(3, 1, res));
$display ("res = %0d", res);
end
// Function has an 8-bit return value and accepts two inputs and provides the result through its output port and return val
function bit [7:0] sum;
input int x, y;
output sum;
sum = x + y;
endfunction
// Same as above but ports are given inline
function byte mul (input int x, y, output int res);
res = x * y + 1;
return x * y
endfunction
endmodule
模拟日志
ncsim> run
s = 14
sum(5,9) = 14
mul(3,1) = 3
res = 4
ncsim: *W,RNQUIE: Simulation is complete.
How to pass arguments by value ?
传递值是将参数传递给子例程的默认机制。每个参数都复制到子例程区域中,并且在子例程区域中对此局部变量所做的任何更改在子例程之外都不可见。
module tb;
initial begin
int a, res;
// 1. Let's pick a random value from 1 to 10 and assign to "a"
a = $urandom_range(1, 10);
// Function is called with "" which is the default mode
res = fn(a);
// Even if value of a is changed inside the function, it is not reflected here
$display ("After calling fn: a=%0d res=%0d", a, res);
end
// This function accepts arguments in "pass by value" mode and hence copies whatever arguments it gets into this local variable called "a".
function int fn (int a);
// Any change to this local variable is not reflected in the main variable declared above within the initial block
a = a + 5;
// Return some computed value
return a * 10;
endfunction
endmodule
请注意,从下面显示的日志中,即使为function中定义的局部变量分配了不同的值,块内的a
值也不会更改。initial
模拟日志
ncsim> run
Before calling fn: a=2 res=0
After calling fn: a=2 res=70
ncsim: *W,RNQUIE: Simulation is complete.
How to pass arguments by reference ?
通过引用传递的参数不会复制到子例程区域,而是将对原始参数的引用传递给子例程。参数声明前面是关键字。对子例程内变量所做的任何更改都将反映在子例程外的原始变量中。ref
// Use "ref" to make this function accept arguments by reference
// Also make the function automatic
function automatic int fn (ref int a);
// Any change to this local variable will be reflected in the main variable declared within the initial block
a = a + 5;
// Return some computed value
return a * 10;
endfunction
Its illegal to use argument passing by reference for subroutines with a lifetime of `static` |
模拟日志
ncsim> run
Before calling fn: a=2 res=0
After calling fn: a=7 res=70
ncsim: *W,RNQUIE: Simulation is complete.