从 always_ff 块内调用的任务内的阻塞分配行为

Behaviour of Blocking Assignments inside Tasks called from within always_ff blocks

在网上到处找这个问题的答案,但我还没有找到答案。

我目前有一个 SystemVerilog 项目,我在主模块的单独模块中实现了循环缓冲区。队列模块本身有一个从一组信号中获取数据的同步部分,但它也有一个响应输入的组合部分。现在,当我想在我的主模块中查询该队列的状态时,一个任务在 always_ff 块内使用阻塞赋值设置输入,然后下一条语句读取输出并对其进行操作。

在几乎 SystemVerilog 中,一个示例看起来像这样:

module foo(clk, ...)

    queue = queue(clk, ...)   

    always_ff@(posedge clk)
    begin
        check_queue(...)
    end

    task check_queue();
    begin
        query_in = 3;
        if (query_out == 5)
        begin
            <<THINGS HAPPEN>>
        end
    end
    endtask
endmodule

module queue(clk, query_in, query_out)
    always_comb
    begin
      query_out = query_in + 2;
    end
endmodule

我的问题基本上归结为,这个想法行得通吗?在我看来,因为队列是组合的,所以它应该在应用输入刺激后立即响应它应该没问题,但因为它在 always_ff 块内的任务中,我有点担心阻塞分配的使用。

有人可以帮忙吗?如果您需要更多信息,请告诉我,我可以提供一些说明。

这会造成竞争条件,很可能不会起作用。它与您使用任务无关。您正在尝试读取在另一个并发进程中分配的信号 (queue_out) 的值。当您到达 If 语句时它是否得到更新是一场竞赛。对 always_ff 块之外的所有变量使用 non-blocking 赋值,它保证你得到以前的值。

为了弄清楚这些东西,您可以在脑子里将任务内联到 always_ff 中。顺便说一句,在你的情况下它看起来真的像一个函数。现在,请记住,任何 always 块的执行必须在任何其他块执行之前完成。因此,以下将永远不会在同一时钟边沿评估为“5”:

    query_in = 3;
    if (query_out == 5)

query_out 将变为 5 after 这个块(你的任务)被评估并且仅在下一个时钟边沿准备就绪。所以,你应该得到一个周期的延迟。

你需要把它分成几个 always 块。