我在VCS(G-2012.09)中编写了一个测试台来验证SPI模块。
下面是一个从SPI主机获取字节的任务:
task get_byte;
begin
repeat(8) @(posedge spck)
begin
if (spss == 1'b0)
tmp = {tmp[6:0], mosi};
end
$display ("[Time:%dns]---->Get a byte: 0x%h", $stime, tmp);
end
endtask
它有效。然后我想参数化这个任务,并将代码替换为:
task get_byte;
input clk, oen, din;
output [7:0] byte;
begin
byte = 8'd0;
repeat(8) @(posedge clk)
begin
if (oen == 1'b0)
byte = {byte[6:0], din};
end
$display ("[Time:%dns]---->Get a byte: 0x%h", $stime, byte);
end
endtask
但是,当我用get_byte(spck, spss, mosi, tmp)
调用该任务并在VCS中运行测试台时,它卡住了。在该任务中,spck
似乎没有作为clk
进行传递。
那么,是否有一条规则,即时钟信号不能用作任务中的输入参数,或者我做错了什么?
在一个旧的stackerflow问题中,您可以找到以下答案:
在Verilog中,参数是按值传递给任务的。这意味着
clock
的值在任务调用的生存期内是固定的。您的任务将永远找不到clock
中的posedge
,并且将永远等待。
所以答案是:您可以使用clk
作为任务的输入参数,但它不能作为"标准"时钟工作。
如果您将任务声明为automatic并通过引用传递输入(在任务的端口定义中使用ref关键字而不是input关键词),则可以按照您的要求执行
使用时钟而不将其声明为输入,就像在第一个任务中所做的那样。通过引用传递也不起作用,因为任务将尝试在任务结束时设置时钟信号,模拟器将抛出错误。
您可能想要有几个引用不同clk名称的任务,例如:
get_byte_spclk(...)
get_byte_clk(...)
正如邱所说,这是行不通的。然而,你可以做一个技巧。请参阅下面的代码:
task my_task;
@(posedge testbench.name_of_the_signal_you_want_to_use_as_refernce)
Do something here
endtask
所以你基本上必须给出时钟信号的路径,类似于:
testbech.instance_of_instantiated_module.clock_signal_name