VHDL로 디지털 하드웨어를 기술하는 법
VHDL의 설계 단위, 타입 시스템, 모델링 방식과 합성 시 제약을 중심으로 디지털 하드웨어 설계 언어의 구조를 정리한다.
2026-08-14 · 최초 발행 2026-01-16
회로의 인터페이스와 구현을 나누는 언어
VHDL(VHSIC Hardware Description Language)은 디지털 회로와 시스템의 구조, 동작을 텍스트로 기술하는 하드웨어 기술 언어다. 미국 국방부의 VHSIC(Very High Speed Integrated Circuit) 프로젝트에서 복잡한 집적 회로를 문서화하고 시뮬레이션하기 위해 개발됐으며, 이후 IEEE 1076 표준으로 자리 잡았다.
Ada 기반 문법과 명시적 타입 선언은 대규모 디지털 시스템에서 설계 의도를 분명히 드러낸다. 신호와 변수의 타입을 분명하게 다루고, 하드웨어의 병렬 동작을 언어 구조로 표현하며, 시뮬레이션과 실제 하드웨어 합성을 함께 지원한다. 유럽, 항공우주, 군사 분야와 의료기기에서 널리 쓰이는 배경도 이런 엄격한 표현 방식에 있다.
VHDL은 계층을 가진 모듈 구조로 시스템을 나눌 수 있어, 큰 설계도 단위별로 관리할 수 있다.
표준 개정으로 확장된 VHDL
표준은 계속 개정됐다. VHDL-2008에는 고정 소수점 패키지, 향상된 제네릭, PSL(Property Specification Language) 통합이 포함됐고, VHDL-2019에서는 인터페이스와 API가 개선됐다.
설계를 이루는 단위와 경계
VHDL 설계는 다섯 가지 설계 단위(Design Unit)로 나뉜다.
| 설계 단위 | 역할 | 특징 |
|---|---|---|
| Entity | 모듈의 외부 인터페이스 정의 | 포트, 제네릭 선언 |
| Architecture | 모듈의 내부 구현 | 동작, 구조, 데이터플로우 |
| Configuration | 엔티티와 아키텍처 바인딩 | 다중 아키텍처 선택 |
| Package | 공유 타입, 상수, 함수 정의 | 라이브러리화 지원 |
| Package Body | 패키지에 선언된 함수 본문 | 구현 세부사항 캡슐화 |
이 가운데 Entity와 Architecture의 분리는 VHDL 설계의 중심 구조다. Entity가 블랙박스의 외부 인터페이스를 정의한다면, Architecture는 그 인터페이스 뒤의 동작을 구현한다.
Entity에는 포트와 제네릭을 선언한다.
entity counter is
generic (
WIDTH : integer := 8
);
port (
clk : in std_logic;
rst_n : in std_logic;
enable : in std_logic;
count : out std_logic_vector(WIDTH-1 downto 0)
);
end entity counter;
Architecture는 신호와 프로세스를 사용해 내부 동작을 적는다.
architecture rtl of counter is
signal count_reg : unsigned(WIDTH-1 downto 0);
begin
process(clk, rst_n)
begin
if rst_n = '0' then
count_reg <= (others => '0');
elsif rising_edge(clk) then
if enable = '1' then
count_reg <= count_reg + 1;
end if;
end if;
end process;
count <= std_logic_vector(count_reg);
end architecture rtl;
강타입 시스템이 표현하는 신호 상태
VHDL은 신호와 변수의 타입을 명시하는 강타입 언어다. 기본 스칼라 타입으로는 bit, boolean, integer, real, character, time이 있다. bit은 '0' 또는 '1'만 표현하며, boolean은 TRUE 또는 FALSE를 쓴다. integer의 범위는 -2^31 ~ 2^31-1이고, time은 시뮬레이션에 사용된다.
실제 하드웨어 신호 상태를 다루려면 IEEE 1164의 std_logic과 std_logic_vector가 중요하다. 이들은 9-값 논리 시스템을 제공한다.
| 값 | 의미 | 합성 시 해석 |
|---|---|---|
| 'U' | 초기화되지 않음 | 시뮬레이션용 |
| 'X' | 강한 Unknown | 충돌 상태 |
| '0' | 강한 0 | 논리 0 |
| '1' | 강한 1 | 논리 1 |
| 'Z' | 고임피던스 | 트라이스테이트 |
| 'W' | 약한 Unknown | 시뮬레이션용 |
| 'L' | 약한 0 | 풀다운 |
| 'H' | 약한 1 | 풀업 |
| '-' | Don't Care | 최적화 힌트 |
배열과 레코드는 데이터 구조를 회로 설계에 맞게 묶는 데 사용한다.
type byte_array is array (0 to 255) of std_logic_vector(7 downto 0);
type matrix is array (natural range <>, natural range <>) of integer;
type packet_t is record
valid : std_logic;
addr : std_logic_vector(31 downto 0);
data : std_logic_vector(63 downto 0);
strobe : std_logic_vector(7 downto 0);
end record;
회로를 서술하는 모델링 관점
구조적 모델링은 하위 컴포넌트를 인스턴스화하고 서로 연결하는 방식이다. 계층적 설계에 적합하다.
architecture structural of full_adder is
component half_adder
port (a, b : in std_logic; sum, carry : out std_logic);
end component;
signal s1, c1, c2 : std_logic;
begin
HA1: half_adder port map (a => a, b => b, sum => s1, carry => c1);
HA2: half_adder port map (a => s1, b => cin, sum => sum, carry => c2);
cout <= c1 or c2;
end architecture;
데이터플로우 모델링은 신호 사이의 흐름을 동시 할당문으로 나타낸다. 조합 논리를 직접 표현할 때 쓴다.
architecture dataflow of full_adder is
begin
sum <= a xor b xor cin;
cout <= (a and b) or (cin and (a xor b));
end architecture;
동작적 모델링은 process 문 안에 순차적 알고리즘으로 동작을 기술한다. 순차 논리와 FSM을 다룰 때 사용할 수 있다.
병렬 문장과 프로세스 내부 문장의 차이
Architecture 안의 동시문(Concurrent Statements)은 병렬로 실행되며, 하드웨어의 병렬 동작을 표현한다. 신호 할당문, when-else 조건 신호 할당, with-select 선택 신호 할당, 컴포넌트 인스턴스화, Generate 문, Process 문이 여기에 속한다.
반면 순차문(Sequential Statements)은 Process 안에서 위에서 아래로 실행된다. 변수 할당에는 :=를 사용하고, 신호 할당은 스케줄링을 의미하는 <=를 사용한다. if-then-else, case, for와 while 루프, wait도 프로세스 안에서 사용하는 순차문이다.
process(clk, rst_n)
begin
if rst_n = '0' then
state <= IDLE;
elsif rising_edge(clk) then
case state is
when IDLE =>
if start = '1' then
state <= RUNNING;
end if;
when RUNNING =>
if done = '1' then
state <= COMPLETE;
end if;
when COMPLETE =>
state <= IDLE;
when others =>
state <= IDLE;
end case;
end if;
end process;
Verilog와 다른 언어적 선택
| 항목 | VHDL | Verilog |
|---|---|---|
| 기반 언어 | Ada | C |
| 타입 시스템 | 강타입 | 약타입 |
| 대소문자 구분 | 구분 안함 | 구분함 |
| 배열 인덱싱 | 유연 (to, downto) | 고정 [high:low] |
| 문장 종료 | 세미콜론 | 세미콜론 |
| 코드 양 | 상대적으로 많음 | 간결함 |
| 학습 곡선 | 가파름 | 완만함 |
VHDL은 항공우주, 군사/방산, 유럽 반도체, 의료기기 분야에서 주요하게 사용된다. Verilog는 미국 반도체, 아시아 팹리스, 소비자 가전, 모바일 AP 분야에서 주요하게 사용된다.
합성 가능한 RTL을 작성할 때
VHDL 문법으로 작성한 모든 코드가 하드웨어로 합성되는 것은 아니다. 합성 도구가 인식하는 코딩 패턴을 지켜야 한다.
합성 가능한 구조에는 rising_edge(clk) 또는 falling_edge(clk) 기반 레지스터, 래치를 방지하는 완전한 if-else 또는 case 문, 조합 논리의 모든 입력을 포함한 민감도 리스트, 정의된 비트 폭의 신호 연산이 있다. 반대로 wait for 시간 지연, 파일 I/O, 동적 메모리 할당, 정적으로 펼칠 수 없는 일부 반복문은 합성할 수 없다.
동기 레지스터는 다음과 같이 기술할 수 있다.
process(clk, rst_n)
begin
if rst_n = '0' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
VHDL-2008 이후의 조합 논리에서는 process(all)을 사용할 수 있다.
process(all) -- VHDL-2008 이후
begin
case sel is
when "00" => y <= a;
when "01" => y <= b;
when "10" => y <= c;
when others => y <= d;
end case;
end process;
제네릭과 Generate로 만드는 재사용 구조
제네릭은 재사용 가능한 모듈의 파라미터를 선언하는 수단이다.
entity fifo is
generic (
DATA_WIDTH : integer := 8;
DEPTH : integer := 16
);
port (
clk : in std_logic;
rst_n : in std_logic;
wr_en : in std_logic;
rd_en : in std_logic;
din : in std_logic_vector(DATA_WIDTH-1 downto 0);
dout : out std_logic_vector(DATA_WIDTH-1 downto 0);
full : out std_logic;
empty : out std_logic
);
end entity;
Generate 문은 조건부 또는 반복적인 하드웨어 구조를 생성할 때 사용한다.
gen_registers: for i in 0 to 7 generate
reg_inst: entity work.reg8
port map (
clk => clk,
d => din((i+1)*8-1 downto i*8),
q => dout((i+1)*8-1 downto i*8)
);
end generate;
VHDL-2008은 process all 키워드, 고정 소수점 패키지, 향상된 제네릭, 외부 이름, PSL 통합, 향상된 연산자를 제공한다. 향상된 제네릭은 타입과 서브프로그램 제네릭을 포함하며, process all은 민감도 리스트 작성을 자동화한다.