Menu

Verilog Number Literal: binary, hex, decimal, sized 상수

Verilog의 상수 표기법: sized vs unsized, 'b 'h 'd 'o base, 부호 있는 숫자, 가독성을 위한 underscore, 그리고 초보자를 무는 함정들.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

sized literal의 해부

Verilog literal은 최대 세 부분으로 구성됩니다.

8'b1010_1100
│  │ │
│  │ └─ 선택한 base의 자릿수
│  └─── base 지정자: b (binary), h (hex), d (decimal), o (octal)
└────── 비트 너비 (decimal)

왼쪽에서 오른쪽으로 읽으면: "8비트 값, binary로 표기, 자릿수는 10101100". 그건 decimal 172, hex 0xAC이며, 어떻게 쓰든 같은 비트입니다. 너비는 컴파일러에게 정확히 몇 비트를 할당할지 알려 주고, base는 자릿수를 어떻게 해석할지 알려 줍니다.

underscore는 시각적 구분자입니다. 32'b1010_1100_0011_010132'b1010110000110101과 같습니다. 사용하세요.

네 가지 base

Hex(h)는 4비트보다 넓은 어떤 값에든 표준입니다. Binary(b)는 비트 패턴을 직접 읽고 싶을 때 표준입니다. Decimal(d)은 사람에게 의미 있는 개수에 씁니다. Octal(o)은 존재하지만 거의 볼 일이 없습니다.

Hex 자릿수는 대소문자 구분 없음: 8'hAB8'hab는 같습니다.

값이 너비에 안 맞으면?

자릿수가 선언된 너비를 채우지 못하면 Verilog은 왼쪽에서 zero-extension 합니다.

8'b101       // 8'b00000101에 해당 (= 5)
8'hF         // 8'h0F에 해당        (= 15)

자릿수가 선언된 너비를 초과 하면 Verilog은 상위 비트를 잘라내고 경고합니다.

4'hFF        // 4'hF로 잘림, 시뮬레이터 경고
4'b10000     // 4'b0000으로 잘림

그 경고는 친구입니다. 억누르지 마세요.

sized vs unsized

너비가 없는 literal은

'd10    // unsized, 기본 크기를 가짐 (≥32비트)
10      // 역시 unsized - base가 없으면 decimal

unsized literal은 대부분의 도구에서 기본 32비트입니다. 이게 한 부류의 버그를 만들어 냅니다.

reg [7:0] count;
if (count == -1) ...      // -1은 unsized 32비트; 비교가 이상해짐

해법은 -1 대신 8'hFF, 또는 8'd255, 또는 {8{1'b1}}로 적는 것입니다. 너비 의존적 식에 사용되는 literal은 항상 sizing하세요.

unsized literal이 괜찮은 한 곳은 testbench의 for 루프 정수 카운터입니다. 정수가 충분히 넓어 놀랄 일이 없을 때.

부호 있는 literal

기본적으로 sized literal은 부호 없음 입니다.

8'd255   // unsigned 255
8'b1111_1111   // unsigned 255 - 같은 비트 패턴을 다르게 쓴 것

부호 있는 것으로 해석되길 원하면 아포스트로피 뒤에 s를 더하세요.

8'sd10           // signed 10
8'sb1111_1111    // signed -1 (two's complement)

s 플래그는 다음에서 의미가 있습니다.

  • <<<>>> 연산자(arithmetic shift) - 부호 있는 피연산자를 sign-extension.
  • 부호 있는 혼합 식의 비교 연산자.
  • $signed/$unsigned cast.

버스 신호의 일반 산술 대부분에서는 s를 빼고 씁니다.

X와 Z가 있는 number literal

literal의 자릿수는 x(unknown) 또는 z(high-impedance)일 수 있습니다.

8'bx는 "모든 8비트가 unknown"의 단축 표기입니다 - 값이 전파되어 선언된 너비를 채웁니다. x 자릿수는 상태 머신의 default case와 초기화에서 흔합니다. 의미는 X and Z Values에서 다룹니다.

실전에서 sized literal이 등장하는 곳

실제 모듈을 작성하기 시작하면 sized literal이 어디서나 등장합니다.

// 버스 너비
input  wire [31:0] addr;
wire [31:0] zero = 32'h0;
wire [31:0] all_ones = 32'hFFFF_FFFF;

// 상태 인코딩
localparam IDLE = 3'd0;
localparam BUSY = 3'd1;
localparam DONE = 3'd2;

// Mask
wire is_msb_set = data & 32'h8000_0000;

// 비교
if (counter == 8'd255) ...

// Reset 값
always @(posedge clk) begin
    if (reset) data_out <= 8'd0;
    else       data_out <= data_in;
end

패턴은 일관됩니다: 너비를 적고, base를 적고, 자릿수를 적기. 어떤 literal이든 같은 모양입니다.

시승

이제 Verilog 모듈이 원할 만한 어떤 상수든 적을 수 있는 모든 것을 갖췄습니다. 데이터 타입 이야기의 마지막 조각은 신호가 깔끔한 0이나 1이 아닐 때 - xz 값입니다.

자주 묻는 질문

Verilog에서 8'b1010은 무엇을 의미하나요?

sized binary literal입니다: binary 표현이 00001010인 8비트 값입니다. 아포스트로피 앞의 숫자는 비트 너비, 아포스트로피 뒤의 글자는 base(b binary, h hex, d decimal, o octal), 그 뒤의 자릿수는 값입니다. 자릿수가 너비를 채우지 못하면 왼쪽이 zero-padding됩니다.

Verilog에서 sized와 unsized 숫자의 차이는?

8'd10 같은 sized literal은 정확히 8비트입니다. 'd10이나 그냥 10 같은 unsized literal은 기본적으로 32비트인데, 보통 너무 큽니다. 너비 의존적 식에 unsized literal을 섞으면 미묘한 버그가 생깁니다 - 일회성 테스트 코드 외에는 어디서나 sized literal을 선호하세요.

Verilog에서 hex 숫자는 어떻게 쓰나요?

'h base 지정자를 사용합니다: 8'hFF는 255를 나타내는 8비트 값입니다. hex 자릿수는 대소문자를 구분하지 않습니다: 8'hff8'hFF는 같습니다. 가독성을 위해 underscore로 자릿수를 그룹화할 수 있습니다: 32'hDEAD_BEEF. underscore는 파서가 무시합니다.

Verilog 숫자에서 underscore는 어떻게 동작하나요?

underscore는 파서가 무시하는 시각적 구분자입니다. 32'b1010_1100_0011_010132'b1010110000110101과 정확히 같은 값이지만 훨씬 읽기 쉽습니다. base 접두사 직후의 첫 글자는 underscore일 수 없지만, 자릿수 안 어디에든 둘 수 있습니다.

Verilog에서 부호 있는 숫자는 어떻게 쓰나요?

아포스트로피 뒤에 s를 추가합니다: 8'sd10은 부호 있는 8비트 decimal 10이고, 8'sb1111_1111은 부호 있는 -1입니다. 기본적으로 sized literal은 부호 없음 이고; s 한정자가 그것을 뒤집습니다. 대부분의 산술은 부호 없는 피연산자를 사용합니다 - 음수가 <, >>> 같은 연산자를 통해 진짜로 전파되어야 할 때만 부호 있는 형태를 쓰세요.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기