组合逻辑环路(Combinational Loops):指组合逻辑的输出信号不经过任何时序逻辑(FF等),而是直接反馈到输入节点,从而构成的电路环路。
此外,如果直接将寄存器的输出端通过组合逻辑反馈到该寄存器的异步端口(异步复位或异步置位),也会形成组合逻辑环路。
在FPGA设计中,绝大多数的应用场景都不需要使用组合逻辑环路,我暂时能想到的例外只有随机数发生器(评论区可以补充一下)。
在实践中,避免使用组合逻辑环路更是因为它的特性所导致的危害:
情况1:组合逻辑的输出信号仅经过组合逻辑电路后又反馈到了输入节点。比如下面的代码:
module test(
input in,
output out
);
wire temp;
assign out = temp;
assign temp = ~ (temp & in);
endmodule
这样的设计在Vivado中不会报错,但会报严重警告(Critical warning)。
组合逻辑环路警告:1个LUT单元形成了组合循环环路。这可能会造成竞争条件。时序分析可能会不准确。推荐的解决方案是修改设计以去除组合逻辑环路。如果组合逻辑环路是已知的预期设计,则可以通过确认条件并在循环中的任何一个网络上设置以下XDC约束来绕过此DRC:“set_property ALLOW_COMBINATORIAL_LOOPS TRUE[get_nets
]”。
情况2:寄存器的输出端通过组合逻辑反馈到该寄存器的异步端口(异步复位或异步置位)。 比如下面的代码:
module test(
input in,
input clk,
output reg out
);
wire rst_n;
always@(posedge clk or negedge rst_n)begin
if(~rst_n)
out <= 1'b0;
else
out <= in;
end
assign rst_n = ~ out;
endmodule
这种情况所导致的组合逻辑环路在实践中还是比较少出现的,因为一般情况下,寄存器的异步端口都是直接由模块外部连接的信号所驱动的,很少会有这种反馈回路的出现。
最重要的一点:一定要坚决避免组合逻辑环路!现在的EDA工具基本上都可以把组合逻辑环路识别出来,并报错或者报警告。写完RTL代码后请一定要记得看EDA工具的Message!
组合逻辑环路的避免首先应该通过良好的编码习惯来避免,比如上述的两种示例代码就是典型的错误。请不要在设计中使用类似的代码。
如果出现了组合逻辑环路且当前设计修改困难,则请修改你的代码----通过添加寄存器的方式来切断反馈回路。就像这样:
如果组合逻辑环路的出现是符合我们的预期设计目的的(比如随机数发生器),想将其保留该如何操作?
这种情况只要在约束文件中添加这一句即可:
set_property ALLOW_COMBINATORIAL_LOOPS TRUE[get_nets
]