VHDL에서 제네릭(generic) 파라미터 오류가 발생하는 경우가 있다. generic map에서 타입 불일치, 범위 초과, 필수 제네릭 누락 등이 원인이 될 수 있다. 제네릭은 엔티티의 재사용성을 높이기 위한 파라미터이므로 올바르게 전달해야 한다.

개요

  • 증상: generic type mismatch, generic value out of range, generic not found
  • 주요 원인: 제네릭 타입 불일치, 범위 초과, 필수 제네릭 누락
  • 해결 방향: 제네릭 선언과 전달 값 일치 확인, 범위 검증

언제 발생하나

대표적인 상황은 다음과 같다.

  • 제네릭 타입 불일치 (예: integer vs natural)
  • 제네릭 값이 선언된 범위를 벗어남
  • 필수 제네릭 파라미터 누락
  • 제네릭 기본값이 없는 경우 값을 전달하지 않음
  • 제네릭 이름 오타

재현 코드(제네릭 타입 불일치)

아래 코드는 제네릭으로 natural을 선언했지만 음수 값을 전달해 오류가 발생한다.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- 제네릭을 사용하는 엔티티
entity shift_register is
  generic (
    WIDTH : natural := 8;  -- natural은 0 이상의 정수
    DEPTH : positive := 4  -- positive는 1 이상의 정수
  );
  port (
    clk   : in  std_logic;
    rst   : in  std_logic;
    din   : in  std_logic_vector(WIDTH-1 downto 0);
    dout  : out std_logic_vector(WIDTH-1 downto 0)
  );
end entity;

architecture rtl of shift_register is
  type reg_array is array (0 to DEPTH-1) of std_logic_vector(WIDTH-1 downto 0);
  signal regs : reg_array;
begin
  process(clk, rst)
  begin
    if rst = '1' then
      regs <= (others => (others => '0'));
    elsif rising_edge(clk) then
      regs(0) <= din;
      for i in 1 to DEPTH-1 loop
        regs(i) <= regs(i-1);
      end loop;
    end if;
  end process;
  dout <= regs(DEPTH-1);
end architecture;
-- 잘못된 인스턴스화 (제네릭 값 오류)
library ieee;
use ieee.std_logic_1164.all;

entity top is
  port (
    clk  : in  std_logic;
    rst  : in  std_logic;
    data : in  std_logic_vector(7 downto 0);
    out  : out std_logic_vector(7 downto 0)
  );
end entity;

architecture rtl of top is
  component shift_register is
    generic (
      WIDTH : natural;
      DEPTH : positive
    );
    port (
      clk  : in  std_logic;
      rst  : in  std_logic;
      din  : in  std_logic_vector(WIDTH-1 downto 0);
      dout : out std_logic_vector(WIDTH-1 downto 0)
    );
  end component;
begin
  inst_shift : shift_register
    generic map (
      WIDTH => -8,  -- 오류: natural은 음수 불가
      DEPTH => 0    -- 오류: positive는 0 불가
    )
    port map (
      clk  => clk,
      rst  => rst,
      din  => data,
      dout => out
    );
end architecture;

해결 원칙

1) 제네릭 타입과 값 일치

제네릭 선언의 타입과 전달하는 값의 타입이 일치해야 한다. natural은 0 이상, positive는 1 이상의 정수만 가능하다.

inst_shift : shift_register
  generic map (
    WIDTH => 8,   -- 올바른 값
    DEPTH => 4    -- 올바른 값
  )
  port map (
    clk  => clk,
    rst  => rst,
    din  => data,
    dout => out
  );

2) 제네릭 기본값 활용

제네릭에 기본값이 있으면 인스턴스화 시 생략할 수 있다. 기본값이 없으면 반드시 값을 전달해야 한다.

-- 기본값이 있는 경우 생략 가능
inst_shift : shift_register
  generic map (
    DEPTH => 8  -- WIDTH는 기본값 8 사용
  )
  port map (
    clk  => clk,
    rst  => rst,
    din  => data,
    dout => out
  );

3) 제네릭 범위 확인

제네릭 값이 실제 사용되는 범위를 벗어나지 않도록 확인한다. 예를 들어, WIDTH-1을 인덱스로 사용한다면 WIDTH >= 1이어야 한다.

4) 제네릭 이름 정확히 일치

제네릭 이름이 엔티티 선언과 정확히 일치해야 한다. 대소문자를 구분하므로 주의해야 한다.

자주 헷갈리는 지점

제네릭은 컴파일 타임 상수이므로, 런타임에 변경할 수 없다. 동적으로 크기를 변경하려면 제네릭이 아닌 다른 방법(예: 최대 크기로 설계 후 사용 시 제한)을 사용해야 한다.

유사 사례

제네릭 파라미터 오류는 타입 불일치와 범위 초과가 주요 원인으로 자주 질문된다.123

References