更好的编码D触发器的方法

时间:2012-06-13 03:10:59

标签: verilog

最近,我在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;是否必要?

2 个答案:

答案 0 :(得分:7)

  

声明q&lt; = q;必要?

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

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

With final else clause

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

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

Without final else clause

此处该工具为所有DFF使用单个时钟门

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

Images from here

答案 1 :(得分:1)

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

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