input端口是输入端口;output是输出端口;还有inout端口。
inout端口用于双向连接。如果使用多个inout端口驱动一个信号,sv将会根据所有驱动器的值,驱动强度来计算最终的值。
ref是对变量(不能是net)的应用,它的值是该变量最后一次赋的值。如果将一个变量连接到多个ref端口,就有可能产生竞争,因为多个模块的端口都有可能更新同一个变量。
在sysytemverilog中,参数的传递方式可以指定为引用而不是复制,这种ref函数类型比input,output和inout更好用,首先你可以把数组传递给子程序;
使用ref和const传递数组,如下
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修饰符,虽然数组变量a指向了调用程序中的数组,但是子程序不能修改数组的值,如果你试图改变数组的值,编译器将报错。
systemverilog允许不带ref进行数组的传递,这时数组会被复制到堆栈区中,这种操作的代价很高,除非是对特别小的数组。
**systemverilog的语言参考手册规定了ref参数只能用于带自动存储的子程序中(automatic funtion/automatic task/void function)。**如果你对程序或模块指定了automatic属性,则整个程序内部都是自动存储的。
ref参数的第二个好处是在任务里可以修改变量而且修改结果对调用他的函数是可见的。
task bus_read(input logic [31:0] addr, ref logic [31:0] data);
bus.request = 1'b1;
@(posedge bus.grant) bus.addr = addr;
@(posedge bus.enable) data = bus.data;
bus.request = 1'b0;
@(negedge bus.grant);
endtask
logic [31:0] addr, data;
initial fork
bus_read(addr, data);
thread2: begin
@data; //数据变化时触发
$display("read %h from bus", data);
end
join