在 Verilog 中使用任务的正确方法

Correct way of using tasks in Verilog

我有一个用于 FIFO 的 Verilog 测试台,我认为使用任务来执行推送和弹出会比我现在正在做的更有效。目前,我使用一系列 repeat (ticks) @ (negedge clk) 语句在长初始 begin/end 块中推送、弹出或推送和弹出。

这使得代码难看且难以阅读。我宁愿有一个任务,push_task(ticks),我可以调用。像这样 -

initial begin
    task_push(5);
    task_pop(2);
    task_push(10);
    ...
end

问题是,如果我这样写 push_task -

task push_task;
    input [31:0] ticks;
    repeat (ticks) begin
            push <= 1'b1;
            push_data <= $random % (2**DATA_WIDTH);
            @ (negedge clk);
            push <= 1'b0;
        end
    end
endtask

我有一个类似的 pop_task,那么我可以推送或弹出但不能同时两者。如何让两者同时执行或按顺序执行取决于我想做什么?

一个明显的方法是创建第三个任务来完成这两项任务。另一种方法是使用 three 输入、ticks、push 和 pop 进行单一任务,并根据 inputs 是否对 push 和 pop 进行断言任务是否断言。

有没有人有其他(更好的?)方法来做到这一点?我可以在网上找到大量关于任务语法是什么以及如何编写它们的信息。没有太多关于它们的正确使用方法是什么。

使用 fork-join 进行并行操作,begin-end 进行顺序操作。允许嵌套。

例如:

initial begin
  task_push(10);
  fork // parallel operations
    task_push(4);
    task_pop(7);
  join
  // back to sequential
  fork // another parallel operation
    task_push(6);
    begin // sequential within parallel
      task_pop(2);
      @(negedge clk); // no pop for one cycle
      task_pop(3);
    end
  join
end

仅供参考,我建议将您的任务更改为更像以下内容。 header 更常规; IEEE1364-2001 及更高版本和 IEEE1800 风格,而不是传统的 IEEE1364-1995 风格。将分配移至循环外的 push 将在模拟中节省一些 CPU 周期。您的 CPU 时间可能不算什么,但在扩展到更大的项目时需要考虑。

task push_task(input [31:0] ticks);
begin
  push <= 1'b1;
  repeat (ticks) begin
    push_data <= $random % (2**DATA_WIDTH);
    @(negedge clk);
  end
  push <= 1'b0;
end
endtask