VHDL generate 문은 코드 블록을 여러 인스턴스로 자동 복제하여 각기 다른 신호에 연결하게 합니다. 컴파일 타임 for 루프로 체인된 프로세스나 모듈 인스턴스를 생성해 보일러플레이트를 획기적으로 줄이고 유지보수성을 높입니다.
전통적 루프가 프로세스나 서브프로그램 내에 국한되는 것과 달리, generate는 아키텍처 영역에 직접 위치합니다. 제네릭과 결합하면 고도로 구성 가능하고 재사용 가능한 VHDL 컴포넌트를 만드는 강력한 메커니즘이 됩니다.
Generate 문 문법
[label :] for in generate [declarations_local_to_each_loop_iteration] [begin] end generate [label];
대괄호 안은 선택 사항. 지역 객체 선언이 없으면 선언부와 begin 키워드 생략 가능. 는 to 또는 downto를 쓰는 표준 정수 문법 따름.
1비트 스위치 디바운서
generate로 들어가기 전에 단일 스위치 입력을 정리하는 간단한 디바운서를 복습합니다. 제네릭 timeout_cycles로 모듈이 어떤 클럭 주파수에도 적응 가능. 기계식 스위치 전환 시 발생하는 일시적 글리치 억제.
entity debouncer is generic ( timeout_cycles : positive ); port ( clk : in std_logic; rst : in std_logic; switch : in std_logic; switch_debounced : out std_logic ); end debouncer;
구현은 제네릭이 폭을 결정하는 정수 카운터에 의존. 내부용 섀도 신호 debounced로 출력 로직을 깔끔하게 유지.
architecture rtl of debouncer is signal debounced : std_logic; signal counter : integer range 0 to timeout_cycles - 1; begin -- Copy internal signal to output switch_debounced <= debounced; DEBOUNCE_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then counter <= 0; debounced <= switch; else if counter < timeout_cycles - 1 then counter <= counter + 1; elsif switch /= debounced then counter <= 0; debounced <= switch; end if; end if; end if; end process; end architecture;
ModelSim 시뮬레이션 확인: switch_debounced가 지정된 타임아웃 후에만 입력을 따르며 바운싱 아티팩트 효과적으로 필터링.
전체 ModelSim 프로젝트(테스트벤치 포함) 다운로드: 아래 이메일 입력. 모든 업데이트는 VHDLwhiz에서 발송, 언제든 구독 취소 가능.
인스턴스화와 함께하는 Generate For 루프
스위치 배열로 디바운서 확장하려면 generate 문으로 여러 인스턴스 자동 생성.
entity debouncer_gen_inst is generic ( switch_count : positive; timeout_cycles : positive ); port ( clk : in std_logic; rst : in std_logic; switches : in std_logic_vector(switch_count - 1 downto 0); switches_debounced : out std_logic_vector(switch_count - 1 downto 0) ); end debouncer_gen_inst;
아키텍처에서 generate 루프로 각 스위치 비트마다 debouncer 인스턴스화. 각 인스턴스는 같은 클럭과 리셋 공유하지만 서로 다른 벡터 요소에 연결.
architecture rtl of debouncer_gen_inst is begin MY_GEN : for i in 0 to switch_count - 1 generate DEBOUNCER : entity work.debouncer(rtl) generic map ( timeout_cycles => timeout_cycles ) port map ( clk => clk, rst => rst, switch => switches(i), switch_debounced => switches_debounced(i) ); end generate; end architecture;
별도 컴포넌트 인스턴스화 없이 디바운서 로직을 generate 블록 안으로 끌어올릴 수도 있습니다. generate 루프가 지역 신호를 가진 동일한 프로세스들도 생성할 수 있음을 보여줍니다.
architecture rtl of debouncer_gen_proc is begin MY_GEN : for i in 0 to switch_count - 1 generate signal debounced : std_logic; signal counter : integer range 0 to timeout_cycles - 1; begin switches_debounced(i) <= debounced; DEBOUNCE_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then counter <= 0; debounced <= switches(i); else if counter < timeout_cycles - 1 then counter <= counter + 1; elsif switches(i) /= debounced then counter <= 0; debounced <= switches(i); end if; end if; end if; end process; end generate; end architecture;
결과 동작은 모듈 인스턴스화 방식과 동일하지만 코드가 아키텍처 내에 자체 포함. 둘 다 유효한 방식이니 설계 스타일에 맞춰 선택.
전체 ModelSim 프로젝트 포함 모든 코드 샘플은 아래 양식으로 다운로드 가능. VHDLwhiz 구독으로 업데이트 받기, 언제든 구독 취소 가능.