最近,我在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;
是否必要?
答案 0 :(得分:7)
不,它不是,并且在ASIC的情况下,它实际上可能增加面积和功耗。我不确定现代FPGA如何处理这个问题。在综合期间,该工具将看到该语句并要求在每个正时钟边沿更新q。如果没有最终的else子句,只要满足给定条件,该工具就可以自由更新声明q&lt; = q;必要?
q
。
在ASIC上,这意味着综合工具可以插入时钟门(假设库有一个)而不是多路复用器。对于单个DFF,这可能实际上更糟,因为时钟门通常远大于多路复用器,但如果q
是32位,则节省可能非常大。现代工具可以自动检测使用共享使能的DFF数量是否满足特定阈值,然后适当选择时钟门控或多路复用器。
在这种情况下,该工具需要3个多路复用器以及额外的路由
always @(posedge CLK or negedge RESET)
if(~RESET)
COUNT <= 0;
else if(INC)
COUNT <= COUNT + 1;
else
COUNT <= COUNT;
此处该工具为所有DFF使用单个时钟门
always @(posedge CLK or negedge RESET)
if(~RESET)
COUNT <= 0;
else if(INC)
COUNT <= COUNT + 1;
答案 1 :(得分:1)
就模拟而言,删除该语句不应该改变任何东西,因为q应该是reg(或SystemVerilog中的逻辑)类型,并且应该保持其值。
此外,大多数综合工具在两种情况下都应生成相同的电路,因为q是使用非阻塞分配更新的。也许更好的代码是使用always_ff而不是always(如果你的工具支持它)。这样,编译器将检查q是否始终使用非阻塞分配进行更新,并生成顺序逻辑。