7

最近,我在verilog中看到了一些D触发器RTL代码,如下所示:

    module d_ff(
            input d,
            input clk,
            input reset,
            input we,
            output q
    );

    always @(posedge clk) begin
            if (~reset) begin
                    q <= 1'b0;
            end
            else if (we) begin
                    q <= d;
            end
            else begin
                    q <= q;
            end
    end
    endmodule

声明q <= q;有必要吗?

4

2 回答 2

7

语句 q <= q; 必要的?

不,不是,对于 ASIC,它实际上可能会增加面积和功耗。我不确定现代 FPGA 如何处理这个问题。在综合期间,该工具将看到该语句并要求在每个正时钟沿更新 q。如果没有最后的 else 子句,该工具只能q在满足给定条件时自由更新。

在 ASIC 上,这意味着综合工具可以插入时钟门(如果库有时钟门)而不是多路复用器。对于单个 DFF,这实际上可能更糟,因为时钟门通常比多路复用器大得多,但如果q是 32 位,那么节省的费用可能非常显着。现代工具可以自动检测使用共享使能的 DFF 数量是否满足某个阈值,然后适当地选择时钟门或多路复用器。

带有最后的 else 子句

在这种情况下,该工具需要 3 个多路复用器以及额外的路由

always @(posedge CLK or negedge RESET)
  if(~RESET)
    COUNT <= 0;
  else if(INC)
    COUNT <= COUNT + 1;
  else
    COUNT <= COUNT;

没有最后的 else 子句

在这里,该工具对所有 DFF 使用单个时钟门

always @(posedge CLK or negedge RESET)
  if(~RESET)
    COUNT <= 0;
  else if(INC)
    COUNT <= COUNT + 1;

图片来自这里

于 2012-06-13T14:47:25.700 回答
1

就模拟而言,删除该语句不会改变任何内容,因为 q 应该是 reg 类型(或 SystemVerilog 中的逻辑),并且应该保持其值。

此外,大多数综合工具在这两种情况下都应该生成相同的电路,因为 q 是使用非阻塞分配更新的。也许更好的代码是使用 always_ff 而不是 always(如果您的工具支持它)。这样,编译器将检查 q 是否始终使用非阻塞赋值进行更新,并生成顺序逻辑。

于 2012-06-13T07:00:39.623 回答