Menu

Verilog Vector와 Array: 멀티 비트 신호 정리

[7:0]로 멀티 비트 신호를 선언하고 슬라이스하고 결합하는 방법, 그리고 packed vector와 memory array의 차이.

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

한 줄 vs 여러 줄

지금까지 본 모든 신호는 1비트 너비였습니다. 실제 설계는 거의 그렇지 않습니다 - 주소는 16비트나 32비트, 데이터 버스는 8 또는 64비트, RGB 픽셀은 24비트입니다. Verilog은 어떤 신호든 멀티 비트로 만드는 단일 메커니즘을 제공합니다: 대괄호 안에 범위를 더하기.

wire [7:0] data;       // 8비트 wire, 비트 7이 MSB, 비트 0이 LSB
reg  [15:0] address;   // 16비트 reg
output reg [31:0] result; // 32비트 모듈 출력

대괄호 안의 숫자는 최상위와 최하위 비트의 비트 위치 입니다. [7:0]은 "이 신호는 7부터 0까지 번호 매겨진 비트들을 가진다"는 뜻이고, 총 8비트가 됩니다. 첫 숫자가 상위 인덱스이고 둘째가 하위입니다.

가끔 [0:7]로 적힌 것도 보입니다 - 같은 비트 수에 슬라이스 목적의 endianness가 반대입니다. [high:low] 형태가 압도적인 산업 관례이니, 특별한 이유가 없다면 그대로 두세요.

작은 예시: 8비트 가산기

+는 두 8비트 vector를 더해 9비트 결과를 만듭니다. 8'd10 같은 숫자 리터럴은 "8비트 너비의 decimal 값 10"입니다 - Number Literal에서 다룹니다.

슬라이싱: 비트 꺼내기

vector가 있으면 개별 비트나 연속 범위를 꺼낼 수 있습니다.

testbench의 force 줄에 너무 얽매이지 마세요 - 슬라이싱을 보여 주기 위해 값을 주입할 방법이 필요했을 뿐입니다. 흥미로운 부분은 슬라이스 자체입니다.

규칙 몇 가지.

  • 슬라이스 방향은 선언과 일치해야 합니다. [7:0]로 선언했다면 [high:low]로 슬라이스합니다. 방향을 뒤집으면 syntax error입니다.
  • 범위 밖 슬라이싱은 시뮬레이션에서 x(unknown)를 만듭니다. synthesis 도구는 경고하거나 오류 처리합니다.
  • 비트 선택은 적은 인덱스 기준입니다 - data[0]은 이름이 0인 비트이며, [7:0] 선언에서는 LSB입니다.

가변 base 슬라이스: +:-:

흔한 요구: "비트 N부터 시작하는 8비트를 줘". data[N+7:N]은 직접 쓸 수 없습니다 - Verilog은 범위의 양 끝이 상수일 것을 요구합니다. 이를 해결하는 문법은

data[base +: width]   // `base`부터 시작해 위쪽으로 width 비트
data[base -: width]   // `base`부터 시작해 아래쪽으로 width 비트

너비는 상수(매번 8비트를 고른다)이지만 base는 런타임 식일 수 있습니다. byte-addressable 메모리, shift-register tap 등에 딱 맞습니다.

Array: vector를 넘어서

vector는 단일 멀티 비트 신호입니다. array 는 독립적으로 인덱싱되는 vector의 모음입니다.

reg [31:0] mem [0:1023];

이 선언에는 두 범위가 있고 둘은 다른 것을 의미합니다.

  • [31:0]packed 차원 - 각 word의 너비.
  • [0:1023]unpacked 차원 - word의 개수.

그래서 mem은 1024개의 독립적인 32비트 register입니다. 단일 인덱스로 접근합니다.

mem[5] = 32'hCAFE_BABE;       // 5번 word에 쓰기
data   = mem[address];        // address의 word 읽기

제곱수를 담는 작은 메모리입니다. 실제 설계는 같은 패턴으로 register file, lookup table, FIFO, 그리고 단일 vector보다 큰 다른 on-chip 저장소를 보존합니다.

Packed vs Unpacked: 왜 중요한가

packed와 unpacked 차원의 분리는 어디서나 등장합니다. 어느 게 어느 건지 아는 것이 디버깅 시간을 많이 줄여 줍니다.

  • packed vector는 하나의 신호입니다. 전체를 숫자처럼 다룰 수 있습니다: data + 1도 되고, data == 32'h0도 되고, data[7:0]도 됩니다.
  • unpacked array는 여러 신호입니다. 전체를 숫자처럼 다룰 수 없습니다: mem + 1은 syntax error입니다. 먼저 특정 word를 골라야 합니다.

여러 packed 차원도 합법입니다.

reg [3:0][7:0] regs;   // 4바이트가 packed되어 32비트 신호로

regs[0]은 한 바이트(low byte)입니다. regs 전체는 32비트입니다. SystemVerilog은 이를 광범위하게 사용합니다.

여러 unpacked 차원은 2D 메모리를 만듭니다.

reg [31:0] frame [0:479][0:639];  // 480x640의 32비트 픽셀

단일 픽셀은 frame[y][x]로 접근합니다. HDL에서 이미지 버퍼가 이렇게 생깁니다.

다음에 볼 내용

이제 필요한 어떤 너비의 신호든 선언하고 다룰 수 있습니다. 다음 문서 - Parameter - 는 그 너비를 구성 가능하게 만들어 같은 모듈이 한 인스턴스에서는 8비트, 다른 인스턴스에서는 32비트로 동작하게 하는 방법을 보여 줍니다. 그다음에는 숫자 리터럴(8'b1010_1100, 32'hDEAD_BEEF) 작성 규칙, 그리고 무언가가 구동되지 않을 때 등장하는 x/z 값을 다룹니다.

자주 묻는 질문

Verilog의 vector란 무엇인가요?

vector는 멀티 비트 신호입니다. wirereg에 범위를 더해 선언합니다: wire [7:0] data는 8비트 wire입니다. 대괄호 안의 숫자는 비트 위치입니다 - 이 경우 비트 7이 최상위 비트, 비트 0이 최하위입니다. 개별 비트(data[3])나 연속 범위(data[7:4])를 슬라이스할 수 있습니다.

Verilog에서 [7:0]은 무엇을 의미하나요?

[7:0]은 비트 7부터 비트 0까지(포함) 범위를 선언합니다 - 비트 7이 MSB인 8비트 신호입니다. 첫 숫자가 상위 인덱스, 둘째가 하위입니다. little-endian 인덱싱을 위해 [0:7]로 적을 수도 있지만 산업 코드에서는 [high:low] 형태가 압도적으로 많은 관례입니다.

Verilog에서 비트는 어떻게 슬라이스하나요?

대괄호 인덱싱을 사용합니다. data[3]은 단일 비트를 고릅니다. data[7:4]는 상위 네 비트를 4비트 vector로 고릅니다. 슬라이스는 선언과 같은 방향이어야 합니다 - [7:0]으로 선언했다면 [high:low]로 슬라이스하세요. SystemVerilog은 가변 base 슬라이스를 위해 data[3 +: 4]도 추가합니다.

Verilog에서 packed array와 unpacked array의 차이는?

packed array는 단일 연속 bus입니다 - reg [31:0] word는 하나의 32비트 신호입니다. unpacked array(또는 '메모리')는 독립적인 word들의 모음입니다 - reg [31:0] mem [0:1023]은 1024개의 별도 32비트 register입니다. unpacked array의 word 하나를 읽거나 쓸 수는 있지만 전체를 단일 신호로 다룰 수는 없습니다.

Verilog에서 memory는 어떻게 선언하나요?

reg [31:0] mem [0:1023];은 1024개 항목의 메모리이고 각 항목은 32비트입니다. 첫 대괄호 세트는 word 너비(packed)이고, 둘째는 word 개수(unpacked)입니다. mem[address]로 항목에 접근하고, SystemVerilog-2005 인덱싱이 활성화되면 mem[address][7:0]로 슬라이스를 읽고 쓸 수 있습니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기