Always if2 - HDLBits
hdlbits.01xz.net
# 들어가며
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.
# 문제 해결
Latch란 원하지 않는 상황에서 회로 안에 메모리 등의 저장 요소가 생기는 현상을 의미한다. 이는 보통 Verilog가 동작하는 방식에 의해서 생성되며, always-if문 등에서 else 등을 사용해서 예외처리를 하지 않는 경우에 발생한다. Latch는 설계 단계에서 명시해 줘야 하는 하나의 기능이므로, 나중에 디버깅을 할 때 문제가 될 수 있기에 반드시 미리 모든 상황을 염두에 두고 설계 한 후에 코드를 작성해야 한다.
아래의 설계도와 코드는 원치 않는 상황에서 Latch를 발생시키고 있으며, 진짜로 cpu_overheated가 발생했는지를 제대로 검사할 수 없다. 이 코드를 Latch가 발생하지 않도록 바꾸는 것이 목표이다.

cpu_overheated일때 computer를 끄지만, cpu_overheated가 아닐때는 computer를 끄지 않는다는 로직이 없기에, else로 추가해야한다. 또한, arrived일때는 운전을 아예 하면 안되므로, else로 case를 추가해줘야한다.
아래는 정답 코드이다.
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) begin
shut_off_computer = 1;
end
else begin
shut_off_computer = 0;
end
end
always @(*) begin
if (~arrived) begin
keep_driving = ~gas_tank_empty;
end
else begin
keep_driving = 0;
end
end
endmodule
'Verilog > HDLBits' 카테고리의 다른 글
[HDLBits] Wire (0) | 2024.10.15 |
---|---|
[HDLBits] Zero (1) | 2024.10.15 |
[HDLBits] Getting Started (0) | 2024.10.15 |