在 FPGA 中,执行诸如 `b <= a; 之类的非阻塞分配是否安全?a <= 0;` 在同一个时钟周期内?

电器工程 FPGA 验证日志 平行线 顺序逻辑
2022-01-04 17:19:55

我在 Verilog 中有一段代码需要在移位完成后将移位寄存器的值分配给输出寄存器,并且我想在同一时钟周期内重置移位寄存器的值。如下所示:

[shift register processing during several clock cycles...]

output_buffer <= shift_register;
shift_register <= 0;

我知道非阻塞分配是并行完成的,这意味着它们是“同时”完成的。考虑到这一点,上面的代码应该有一个未定义的行为:如果两个分配“并行”发生,因为最终什么都不会同时发生。

我已经在模拟器上尝试过了,它可以按我的预期工作,也就是说,output_buffer得到了 shift reg。值,后者被重置。但是,一般来说,在真正的 FPGA 上执行它是否安全?

3个回答

虽然我无法深入了解 Verilog 的原始设计者,但我怀疑 99% 的使用它的工程师会告诉您,您的代码片段体现了非阻塞分配的全部意义。

一旦你明白了它,一个非阻塞赋值基本上就是说“在这里放一个寄存器”。如果您的代码块都是非阻塞分配,那么分配右侧的所有内容都是在时钟沿之前立即存在于这些信号中的值;左侧的值是紧接时钟沿之后分配的值。

因此,您的代码说“将输出缓冲区设置为移位寄存器的值并将移位寄存器清零”,全部在一个时钟内完成。

* 在模拟领域。如果您想快速发展,确实需要注意所有设置和保持业务。

是的,假设 Verilog 代码如下所示,您应该在 FPGA 中获得与在仿真中相同的行为:

always @(posedge clk) begin
    if (load) begin
        output_buffer  <= shift_register;
        shift_register <= 0;
    end else ...
    ...
end

此代码确实具有定义的行为。在时钟的上升沿,Verilog 模拟器首先读取非阻塞分配的 RHS 值,然后再更新 LHS 值。这意味着output_buffer保证得到 的先前值shift_register,而不是 0。

类似地,假设应用了适当的时序约束,FPGA 综合工具应该创建一组具有适当时序的触发器,以保证output_buffer获得 的先前值。shift_register

如果您为工具的代码示例绘制逻辑图,事情会变得更加清晰:

逻辑图

output_buffer 的输入不能在时钟上升沿后变化太快(称为保持时间要求)。如果 shift_register 非常快地变为 0,并且这种变化在保持时间内达到 output_buffer,它将违反保持时间要求,并可能导致亚稳态和各种问题。

综合工具确保满足所有时序要求。在 FPGA 中,满足保持时间要求很少成为问题。如果是,综合工具可以将“虚拟逻辑”从 shift_register 引入 output_buffer,以减缓信号变化。