最近,我看到了在这样的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;
必要?
是否该语句q <= Q; 必要?
不,它不是,在ASIC它可能会增加面积和功耗的情况下。 我不知道现代FPGA是怎样处理这个问题。 在合成过程中的工具将看到声明,并要求q也对每一个时钟上升沿更新。 如果没有最后一个else子句中的工具是免费的,只更新q
只要给定的条件得到满足。
在ASIC上,这意味着合成工具可以插入一个时钟门(提供的库有一个),而不是多路复用器。 对于单个DFF这实际上可能更糟,因为时钟门通常比多路复用器大得多,但如果q
是32位,则节省可以很显著。 如果使用一个共享使DFFs的数目达到一定的阈值,然后选择一个时钟门或多路复用器适当地现代工具可以自动检测。
在这种情况下,工具需要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;
从这里图片
至于模拟而言,移除该声明不应该改变什么,而且,由于Q应该是类型REG(或逻辑SystemVerilog中),而应保持其价值。
另外,由于q被使用非阻塞分配更新最综合工具应该产生在两种情况下相同的电路。 也许一个更好的代码是使用always_ff,而不是总(如果你的工具支持的话)。 通过这种方式,编译器将检查q被使用非阻塞分配总是被更新,并产生时序逻辑。