Verilog 산술에서 값이 예상과 다르면 먼저 literal의 폭과 signed 여부를 확인한다. 같은 비트 패턴도 unsigned와 signed 선언에 따라 해석 값이 다르다.
같은 비트, 다른 값
logic [7:0] unsigned_value;
logic signed [7:0] signed_value;
always_comb begin
unsigned_value = 8'hF0; // 240
signed_value = 8'shF0; // -16
end
두 신호의 비트는 모두 1111_0000이다. unsigned 8-bit 값의 범위는 0..255, signed 8-bit 2의 보수 범위는 -128..127이다.
폭과 진법을 literal에 표시
<폭>'<진법><값> 형태로 폭과 진법을 명시할 수 있다.
logic [7:0] opcode;
assign opcode = 8'h2A;
이렇게 쓰면 코드에서 의도한 폭을 읽기 쉽고, 주변 표현식과의 폭 불일치도 찾기 쉬워진다. 크기가 지정되지 않은 정수 literal이나 서로 다른 폭의 피연산자는 표현식 크기 규칙에 따라 확장 또는 잘림이 일어날 수 있다.
signed와 unsigned를 섞지 않기
한 산술식에 signed와 unsigned 피연산자를 섞으면 비교와 확장 결과가 의도와 달라질 수 있다. 비교하거나 더하기 전에 각 신호의 선언, literal의 signed 표기, 중간 결과 폭을 함께 확인한다.
음수 범위가 필요한 신호는 선언부터 signed로 둔다.
logic signed [7:0] temperature;
assign temperature = -8'sd16;
signed와 unsigned 값을 함께 계산해야 한다면 연산의 의도를 먼저 정하고, 필요한 폭으로 명시적으로 확장하거나 명시적 cast를 사용한다. 최종 대입 폭이 연산 중간값을 항상 보존한다고 가정하지 않는다.
잘림과 overflow 점검
대입 대상이 더 좁으면 상위 비트가 버려질 수 있다. 예를 들어 8-bit 계산 결과를 4-bit 신호에 대입하면 상위 4bit를 저장할 수 없다.
- 피연산자의 선언 폭과 signed 여부를 확인한다.
- 연산 결과에 필요한 폭을 계산한다.
- carry 또는 overflow를 보존할 출력 폭을 선언한다.
- lint에서 width mismatch와 truncation 경고를 확인한다.
비트 패턴만으로 음수 여부를 판단하기보다 signed 선언을 사용해 비교 의도를 드러낸다.
공식 자료
원문 기록
한 줄 요약
산술 오류를 찾을 때는 literal 폭, signed 선언, 표현식의 확장과 대입 시 잘림을 한 번에 확인한다.