目次
1. 소개
Verilog는 하드웨어 기술 언어(HDL)로 널리 사용되며 FPGA와 ASIC 개발을 위한 회로 설계에 필수적입니다. Verilog를 효율적으로 설계하려면 배열에 대한 확고한 이해가 중요합니다. 배열을 활용하면 데이터를 간결하고 직관적으로 관리할 수 있어 회로 기술서의 가독성과 유지보수성이 향상됩니다. 특히 여러 신호를 그룹화하거나 RAM과 같은 메모리 구조를 표현할 때 배열이 효과적입니다. 이 문서는 “Verilog 배열”이라는 키워드에 초점을 맞추어 배열 정의의 기본부터 실용적인 적용 기법까지 포괄적으로 설명합니다. 배열 종류, SystemVerilog 확장, 흔히 발생하는 오류 및 FAQ 등을 다루어 이해도를 높이고자 합니다. 초보자도 실용적인 코드 예제를 통해 쉽게 따라 할 수 있도록 구성했으며, 전체적인 개요를 위해 끝까지 읽어 보시기 바랍니다.2. Verilog의 기본 데이터 타입
Verilog에서 배열을 사용하기 전에 기본 데이터 타입을 이해하는 것이 중요합니다. Verilog는 회로 설계에 사용되는 논리 신호를 처리하기 위한 여러 핵심 데이터 타입을 제공합니다.reg와 wire의 차이점
Verilog에서 가장 흔히 사용되는 데이터 타입은 “reg”(레지스터)와 “wire”(와이어)입니다. 논리 신호의 동작 방식에 따라 적절히 사용해야 합니다.- wire 타입 와이어는 모듈이나 회로 사이의 연결선으로 사용됩니다. 항상 다른 신호에 의해 구동되어야 하며,
assign문을 사용해 할당합니다. 조합 논리 회로의 출력에 적합합니다. 예시:
wire a;
assign a = b & c;
- reg 타입 레지는 값을 일시적으로 보관하는 변수로 사용됩니다.
always와 같은 프로세스 블록 내부에서 할당되며, 일반적으로 저장소 요소(래치 또는 플립플롭)를 모델링하는 데 사용됩니다. 예시:
reg q;
always @(posedge clk) begin
q <= d;
end
배열에서 사용할 수 있는 데이터 타입
Verilog에서는 배열을 정의할 때 주로reg 타입을 사용하지만, 경우에 따라 wire 배열도 사용할 수 있습니다. 다만, 초기 Verilog 버전에서는 다차원 배열을 지원하지 않았으며, 이 제한은 SystemVerilog에서 크게 개선되었습니다.
다음은 배열 구문의 간단한 예시입니다:reg [7:0] data_array [0:15]; // An array storing 16 elements, each 8 bits wide
데이터 타입의 기본을 이해하면 배열 선언 및 사용 시 혼란을 피할 수 있습니다. reg와 wire를 잘못 사용하면 시뮬레이션이나 합성 오류가 발생할 수 있으니 주의하세요.3. 배열의 기본 개념
Verilog에서 배열은 동일한 타입의 여러 신호를 한 번에 관리하고자 할 때 사용합니다. 배열을 사용하면 신호를 체계적으로 정리할 수 있어 코드 가독성과 재사용성이 향상됩니다.배열 선언
Verilog는 주로 1차원 배열을 지원합니다. 구문은 다음과 같습니다:reg [bit-width] array_name [index-range];
예시:reg [7:0] data_array [0:15]; // An array of 16 elements, each storing 8-bit data
위 예시에서 data_array는 0부터 15까지 인덱싱되는 16개의 요소를 가지며, 각 요소는 8비트(1바이트) 값을 저장합니다.배열 요소 접근
배열의 각 요소는 인덱스 번호를 지정하여 접근할 수 있습니다. C 언어와 마찬가지로 배열 인덱스는 0부터 시작합니다.data_array[0] = 8'hFF; // Assign hexadecimal FF to the first element
data_array[1] = 8'd12; // Assign decimal 12 to the second element
always 블록 내부에서 루프를 사용해 배열을 초기화하거나 조작할 수도 있습니다.integer i;
always @(posedge clk) begin
for (i = 0; i < 16; i = i + 1) begin
data_array[i] <= 8'd0;
end
end
배열의 장점
- 배치 처리 :
for루프를 사용하면 여러 신호에 동일한 연산을 한 번에 적용할 수 있습니다. - 구조화된 회로 : 배열은 여러 레지스터나 신호를 정리하는 데 도움을 주어 회로 표현을 명확하게 유지합니다.
- 메모리 모델링 : RAM이나 ROM과 같은 간단한 메모리 구조를 구현할 수 있습니다(다음 장에서 설명).
주의 사항
Verilog에서는 전체 배열에 직접 값을 할당할 수 없습니다(예:data_array = value). 대신 요소별로 연산을 수행해야 합니다. 또한 초기 Verilog에서는 1차원 배열만 공식적으로 지원했으므로 다차원 배열을 사용하려면 Verilog 2001 또는 SystemVerilog이 필요합니다.4. 다차원 배열 사용
Verilog의 배열은 설계를 단순화하고 회로 구조를 정리하는 데 도움을 줍니다. 다차원 배열을 사용하면 보다 복잡한 데이터 구조를 효율적으로 처리할 수 있습니다. 하지만 구버전 Verilog(IEEE 1364‑1995)는 다차원 배열을 지원하지 않았습니다. 다차원 배열은 Verilog 2001에서 공식적으로 도입되었습니다. 더 큰 유연성을 원한다면 SystemVerilog을 권장합니다.다차원 배열 선언
Verilog 2001부터는 하나의 변수에 대해 여러 인덱스를 지정하여 다차원 배열을 정의할 수 있습니다. 기본 구문은 다음과 같습니다.reg [7:0] matrix [0:3][0:3]; // Defines a 4×4 matrix of 8-bit elements
이 선언은 matrix라는 2D 배열을 생성하며, 16개의 요소를 가지고 각 요소는 8비트 폭을 가집니다.요소 접근 및 할당
다차원 배열의 특정 요소에 접근하고 할당하려면 인덱스를 사용합니다.matrix[0][0] = 8'hA5;
matrix[2][3] = 8'd255;
for 루프 사용
다차원 배열은 중첩for 루프를 사용해 조작할 수 있습니다. 초기화 예시는 다음과 같습니다.integer i, j;
always @(posedge clk) begin
for (i = 0; i < 4; i = i + 1) begin
for (j = 0; j < 4; j = j + 1) begin
matrix[i][j] <= 8'd0;
end
end
end
다차원 배열의 활용
- 행렬 연산이나 필터 처리가 필요한 설계에 유용합니다.
- 이미지 처리 또는 디지털 신호 처리(DSP)에서 픽셀 수준 데이터 처리를 위해 사용할 수 있습니다.
- ROM/RAM 블록 구조 및 주소‑데이터 쌍을 정리하는 데 사용됩니다.
제한 사항 및 고려점
- 합성 도구 호환성을 확인하세요. 일부 도구는 다차원 배열을 완전히 지원하지 않을 수 있습니다.
- 인스턴스화나 인터페이스와 결합할 때 제한이 적용될 수 있습니다.
- SystemVerilog과의 차이를 이해하여 호환성 문제를 방지하세요(후에 설명).

5. 배열을 이용한 메모리 모델링
Verilog에서는 배열을 사용해 간단한 메모리 구조를 모델링할 수 있습니다. 이를 통해 RAM 및 ROM과 같은 저장 회로를 간결하고 유연하게 기술하고 시뮬레이션할 수 있습니다. 특히 1차원 배열 기반 메모리 모델은 CPU 설계와 통신 시스템에서 자주 사용됩니다.메모리 모델의 기본 구문
다음 예시는 32비트 워드와 1024 주소(0–1023)를 갖는 간단한 RAM을 나타냅니다.reg [31:0] memory [0:1023]; // 32-bit × 1024-word memory
이 선언은 memory라는 배열을 생성하며, 각 인덱스(주소)는 32비트 워드를 저장합니다.메모리 쓰기 및 읽기
배열을 이용한 메모리 읽기/쓰기 연산은 다음과 같이 기술할 수 있습니다.// Write operation
always @(posedge clk) begin
if (we) begin
memory[addr] <= data_in;
end
end
// Read operation
assign data_out = memory[addr];
핵심 포인트:- 쓰기 연산은
posedge clk에 동기화되며 조건부(we—쓰기 활성)로 수행됩니다. - 읽기 연산은 일반적으로
assign을 사용해 조합 논리(비동기) 읽기로 구현됩니다.
메모리 초기화
테스트벤치나 초기 상태 설정을 위해initial 블록 안에서 배열을 초기화할 수 있습니다.integer i;
initial begin
for (i = 0; i < 1024; i = i + 1) begin
memory[i] = 32'd0;
end
end
외부 파일에서 초기 값을 $readmemh 또는 $readmemb를 사용하여 로드할 수도 있습니다:initial begin
$readmemh("rom_init.hex", memory); // Initialize from a hex file
end
실용적인 사용 사례
- CPU 또는 마이크로컨트롤러의 레지스터 파일
- FPGA 내부 Block RAM (BRAM)의 동작 시뮬레이션
- 캐시 메모리 동작 검증
- ROM 데이터 읽기 시뮬레이션
유의 사항
- 배열 크기가 커질수록 시뮬레이션 시간 및 합성 자원도 증가합니다.
- 설계 사양과 툴에 따라 동기식 vs 비동기식 읽기 타이밍을 신중히 선택하십시오.
- 합성을 목표로 할 경우, 툴 공급업체가 권장하는 메모리 추론 규칙을 따르세요.
6. SystemVerilog의 배열 확장
Verilog 2001까지는 배열 기능이 제한적이어서 설계가 번거로웠습니다. 이를 해결하기 위해 SystemVerilog는 중요한 확장을 도입하여 보다 유연하고 강력한 배열 처리를 가능하게 했습니다. 이 섹션에서는 SystemVerilog에서 사용할 수 있는 세 가지 주요 배열 유형인 동적 배열, 연관 배열, 큐에 대해 설명하고, 각각의 특징과 사용 사례를 다룹니다.동적 배열
특징
- 실행 중에 배열 크기를 변경할 수 있습니다.
- 크기를 미리 알 수 없거나 실행 중에 변할 때 유용합니다.
선언 및 예시
int dyn_array[]; // Declare a dynamic array
dyn_array = new[10]; // Initialize with 10 elements
dyn_array[0] = 100;
사용 사례
- 테스트벤치에서 임시 데이터 저장
- 가변 크기 버퍼 관리
연관 배열
특징
- 인덱스를 임의의 값(정수, 문자열 등)으로 사용할 수 있습니다.
- 해시 테이블처럼 동작합니다.
선언 및 예시
int assoc_array[string]; // Associative array using strings as keys
assoc_array["id_001"] = 42;
사용 사례
- 파라미터용 설정 값 저장
- ID 또는 이름으로 값 조회
큐
특징
- FIFO(First-In, First-Out) 구조처럼 동작합니다.
- 삽입 및 삭제가 쉬워 동적 데이터 스트림에 이상적입니다.
선언 및 예시
int queue_array[$]; // Declare a queue array
queue_array.push_back(10); // Add element at the end
queue_array.push_front(5); // Add element at the front
int val = queue_array.pop_front(); // Remove element from the front
사용 사례
- 임시 데이터 저장(FIFO 버퍼)
- 이벤트 처리 및 트랜잭션 관리
비교 및 활용
| 배열 타입 | Resizable | 인덱스 유형 | 최적의 선택 |
|---|---|---|---|
| 동적 배열 | 예 | Integer | 크기가 알 수 없거나 가변인 경우 |
| 연관 배열 | 네 | 임의 (int, string 등) | 해시 테이블과 같은 조회 |
| Queue | 네 | 자동 (전면/후면) | 빈번한 삽입/제거 |
유의 사항
- 이러한 확장된 배열은 SystemVerilog 전용 기능이며 Verilog에서는 사용할 수 없습니다.
- 합성 지원 범위는 툴에 따라 다르며, 주로 테스트벤치에서 사용됩니다.
- FPGA 또는 ASIC을 목표로 할 경우, 구현 전에 해당 기능이 지원되는지 반드시 확인하십시오.
7. 배열 연산을 위한 모범 사례
Verilog 또는 SystemVerilog에서 배열을 다룰 때 효율적이고 가독성 높은 코딩에 집중하면 하드웨어 설계 품질이 크게 향상됩니다. 이 장에서는 배열을 안전하고 효과적으로 다루기 위한 모범 사례를 강조합니다.주석과 네이밍으로 의도 명확히 하기
배열은 확장성이 높고 편리하지만, 각 요소가 무엇을 의미하는지 항상 명확하지 않을 수 있습니다. 혼동을 방지하려면 다음 지침을 따르세요:- 배열에 의미 있는 이름을 사용하세요:
reg [7:0] sensor_data [0:7]; - 목적이나 단위를 설명하는 주석을 추가하세요:
// Stores 8-bit data from 8 sensors
reg [7:0] sensor_data [0:7];
루프 경계에 주의하기
for 루프를 사용해 배열을 조작할 때 인덱스 경계를 정확히 정의하는 것이 중요합니다:- 잘못된 상한값 → 범위 초과 접근(논리 오류 또는 시뮬레이터 경고)
- 루프 종료 조건에
<와<=중 어느 것을 사용할지 신중히 결정하세요
integer i;
always @(posedge clk) begin
for (i = 0; i < 8; i = i + 1) begin
sensor_data[i] <= 8'd0;
end
end
항상 명시적으로 초기화하기
Leaving arrays uninitialized can affect simulation results. This is especially critical for arrays modeling RAM or register banks. Always initialize explicitly:initial begin
for (i = 0; i < 256; i = i + 1)
mem[i] = 32'd0;
end
In SystemVerilog, constructors or foreach loops allow even simpler initialization.재사용 가능한 모듈 설계
Array-based designs can adapt flexibly to changes in instance count or bit width. To maximize reusability, consider:parameter를 사용하여 배열 크기를 설정 가능하게 만들기:
parameter DEPTH = 16;
reg [7:0] buffer [0:DEPTH-1];
- 외부 파라미터 전달을 허용하면 모듈 재사용성이 향상됩니다.
합성 가능성 고려
When using arrays, always take synthesis tool compatibility into account:- Verilog 1차원
reg배열: 일반적으로 합성 가능 - SystemVerilog 동적/연관/큐 배열: 합성 불가 (시뮬레이션 전용)
reg 배열을 사용하십시오.배열 vs. 모듈 적절히 사용
While arrays can reduce code size, overly complex designs may benefit more from splitting functionality into separate modules for maintainability.- 작은, 동일한 연산 →
for루프를 이용한 배열 - 기능이 다르거나 대규모 설계 → 모듈화 및 계층적 설계
8. 자주 묻는 질문 (FAQ)
When using arrays in Verilog or SystemVerilog, beginners to intermediate users often encounter the same stumbling blocks. Here we address three common questions about “Verilog arrays,” providing practical answers and insights from real‑world design experience.Q1. Verilog에서 다차원 배열을 사용할 때 오류가 발생합니다. 왜인가요?
A1.
This happens because Verilog 1995 and earlier versions of Verilog 2001 either did not support multidimensional arrays at all or only supported them in a limited way. 예를 들어, 다음 코드는 Verilog 1995에서 컴파일 오류를 일으킵니다:reg [7:0] matrix [0:3][0:3]; // Supported only in Verilog 2001 or later
Solution:- 개발 환경이 Verilog 2001 이상을 지원하도록 확인하십시오.
- 제한이 남아 있다면, 계산된 인덱스를 사용한 1차원 배열로 다시 작성하십시오.
reg [7:0] matrix_1d [0:15]; // Flattened 4x4 array, accessed with (i*4 + j)
Q2. Verilog에서 배열을 사용해 RAM을 기술하면 실제 하드웨어에서 동작하나요?
A2.
Yes. RAM described using arrays in Verilog is supported by most synthesis tools. A common example:reg [31:0] mem [0:255]; // 32-bit × 256-word RAM
Points to watch:- 합성 도구가 이 기술을 블록 RAM 추론으로 인식해야 합니다.
- 읽기/쓰기 타이밍(동기식 vs 비동기식) 및 접근 방식은 특정 템플릿을 따라야 하며, 그렇지 않으면 메모리를 올바르게 추론하지 못할 수 있습니다.
- FPGA/ASIC 공급업체가 제공하는 합성 가이드를 따르십시오.
- 시뮬레이션과 하드웨어 동작이 다르면 로그를 확인하고 단계별로 디버깅하십시오.
Q3. SystemVerilog의 동적 배열, 연관 배열, 큐를 실제 하드웨어에 사용할 수 있나요?
A3.
In general, dynamic arrays, associative arrays, and queues are not synthesizable (simulation only). Although they provide flexible coding, they cannot be directly mapped to hardware logic. 따라서 이러한 배열은 주로 다음 용도로 사용됩니다:- 테스트벤치에서의 임시 데이터 저장
- 검증 환경에서의 랜덤화 또는 스코어보드 구현
- 복잡한 트랜잭션 기술
- 이러한 배열 타입을 사용하는 설계 코드는 합성 도구에서 무시되거나 오류를 발생합니다.
- 하드웨어 구현이 필요하면
reg또는 고정 길이 1차원 배열로 변환하십시오.
9. 결론
이 기사에서는 키워드 “Verilog 배열”에 초점을 맞추어 기본부터 고급 응용까지 사용법을 설명했습니다. 회로 설계에서 배열을 마스터하면 효율성, 가독성 및 유지보수성에 직접적으로 기여합니다.핵심 요약
- 기본 Verilog 데이터 타입 (reg 및 wire) 을 이해하면 배열 작업 시 오류를 피할 수 있습니다.
- 1차원 배열은 데이터를 그룹화하고 메모리를 모델링하는 데 필수적인 구조입니다.
- 다차원 배열은 Verilog 2001 이후 지원되어 행렬 형태 설계를 가능하게 합니다.
- SystemVerilog는 동적 배열, 연관 배열, 큐와 같은 유연한 구조를 도입합니다(주로 시뮬레이션 및 검증용).
- 배열 처리 베스트 프랙티스(초기화, 명명 규칙, 재사용성, 합성 고려사항) 를 따르면 더 높은 품질의 코드를 작성할 수 있습니다.
실용적인 팁
배열은 강력하지만 모든 경우에 무조건 사용해서는 안 됩니다. 합성 가능한 코드를 작성하거나 팀으로 협업할 때는 항상 제약 조건과 스타일 가이드를 따르세요. SystemVerilog의 고급 배열 기능은 시뮬레이션을 염두에 두고 사용해야 그 이점을 최대화할 수 있습니다. 좋은 설계자는 목적에 맞는 구조를 선택하는 방법을 알고 있습니다.다음으로 추천하는 주제
이제 배열의 기본을 이해했다면, 다음 관련 주제를 탐색해 보시기 바랍니다:- 배열을 활용한 동적 회로 생성을 위해
generate문 사용 - 버스 설계를 위해
interface와 배열 결합 - 배열을 이용한 FIFO, 링 버퍼, ROM 최적화 구현



