조합 로직의 case에서 latch를 피하려면 분기마다 모든 출력을 할당하거나, case 전에 기본값을 먼저 할당한다. default도 함께 두면 빠진 상태나 입력 조합을 처리할 수 있다.
case와 if-else 선택
case는 하나의 표현식을 여러 값과 비교할 때 읽기 쉽다. if-else는 조건의 우선순위나 범위 비교가 중요할 때 적합하다.
case가 자동으로 병렬 하드웨어를 만든다고 단정할 수는 없다. 겹치는 wildcard 조건, 합성기가 해석하는 문맥, 대상 장치에 따라 결과가 달라질 수 있으므로 합성 보고서를 확인한다.
조합 블록의 기본 할당
아래는 상태에 따라 next_state와 result를 결정하는 SystemVerilog 예다.
always_comb begin
next_state = state;
result = '0;
case (state)
IDLE: begin
if (start)
next_state = RUN;
end
RUN: begin
result = input_data;
next_state = DONE;
end
DONE: next_state = IDLE;
default: next_state = IDLE;
endcase
end
result는 기본값을 먼저 받으므로 IDLE, DONE, 미정의 상태에서도 값이 정해진다. 기본값은 예제의 선택일 뿐이다. 실제 회로에서는 미정의 입력이나 상태에서 출력으로 내보낼 안전한 값을 설계 요구사항에 맞춰 정한다.
Verilog 문법만 쓰는 코드라면 always_comb 대신 always @*를 사용할 수 있다. 블록 안의 모든 경로에서 같은 신호를 할당하는 원칙은 같다. 조합 블록과 순차 블록의 할당 방식은 blocking과 non-blocking 할당 기준도 참고한다.
default와 wildcard 주의점
- 일반
case는X와Z를 포함한 값을 정확히 비교한다. casez는Z와?를 wildcard로 취급하므로 입력의 미정 상태를 무시할 수 있다.casex는X까지 wildcard로 취급해 설계 오류를 감출 수 있으므로 RTL에서 피하는 편이 안전하다.default에서 값을 지정해도 실제로 의도한 복구 동작인지 별도로 검토한다.
합성 후 확인
- 조합 블록에서 각 출력이 모든 분기에 할당되는지 확인한다.
- lint와 synthesis warning에서 latch inference를 찾는다.
- 합성 결과의 latch 개수와 schematic을 확인한다.
case항목이 서로 겹치는 wildcard 패턴을 쓰는지 확인한다.
스타일 규칙만으로 합성 결과를 보장할 수는 없다. 사용하는 FPGA, 합성 설정과 실제 RTL의 전체 문맥에서 결과를 확인한다.
공식 자료
- AMD UG901: Verilog Case Statements
- AMD UG901: Incomplete Case Statements
- AMD UG901: Using Sequential Always Blocks
원문 기록
한 줄 요약
case는 값 선택을 읽기 쉽게 만들고, 조합 블록의 기본 할당과 각 경로의 완전한 할당은 latch를 막는 데 도움이 되지만 합성 보고서로 결과를 확인해야 한다.