A common source of errors: How to avoid making latches
When designing circuits, you must think first in terms of circuits:
- I want this logic gate
- I want a combinational blob of logic that has these inputs and produces these outputs
- I want a combinational blob of logic followed by a set of flip-flops
What you must not do is write the code first, then hope it generates a proper circuit.
- If (cpu_overheated) then shut_off_computer = 1;
- If (~arrived) then keep_driving = ~gas_tank_empty;
Syntactically-correct code does not necessarily result in a reasonable circuit (combinational logic + flip-flops). The usual reason is: "What happens in the cases other than those you specified?". Verilog's answer is: Keep the outputs unchanged.
This behaviour of "keep outputs unchanged" means the current state needs to be remembered, and thus produces a latch. Combinational logic (e.g., logic gates) cannot remember any state. Watch out for Warning (10240): ... inferring latch(es)" messages. Unless the latch was intentional, it almost always indicates a bug. Combinational circuits must have a value assigned to all outputs under all conditions. This usually means you always need else clauses or a default value assigned to the outputs.
译:
一个常见的错误来源:如何避免制造锁存器
在设计电路时,你必须首先从电路的角度来思考:
我想要这个逻辑门
我想要一个具有这些输入并产生这些输出的组合逻辑块
我想要一个组合逻辑块后面跟着一组触发器
你不应该做的是先写代码,然后希望它能生成一个合适的电路。
如果 (cpu_overheated) 那么 shut_off_computer = 1;
如果 (~arrived) 那么 keep_driving = ~gas_tank_empty;
语法正确的代码并不一定会产生一个合理的电路(组合逻辑 + 触发器)。通常的原因是:“在你指定的情况之外的案例中会发生什么?”。Verilog的答案是:保持输出不变。
“保持输出不变”的行为意味着需要记住当前状态,从而产生一个锁存器。组合逻辑(例如,逻辑门)无法记住任何状态。要注意警告(10240):...推断出锁存器的消息。除非锁存器是有意为之,否则它几乎总是表示一个错误。组合电路在所有条件下都必须为所有输出分配一个值。这通常意味着你总是需要 `else` 子句或者为输出分配一个默认值。
Demonstration
The following code contains incorrect behaviour that creates a latch. Fix the bugs so that you will shut off the computer only if it's really overheated, and stop driving if you've arrived at your destination or you need to refuel.
以下代码包含错误的行为,这会导致产生一个锁存器。修复这些错误,以便只有在计算机真正过热时才关闭计算机,并且在到达目的地或需要加油时停止驱动。
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving = 0;
end
endmodule
运行结果:
分析:
本题意为让人养成Verilog思维,Verilog本质上是电路,要先考虑电路的合理性,然后再写代码,比如 if 后面,一定要有else的调用,给电路一个备选项,以免造成死机