산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> VHDL

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

펄스 폭 변조(PWM)는 디지털 FPGA 핀을 강력한 아날로그 컨트롤러로 바꿉니다. 고속으로 전원 온/오프 전환하여 부하가 보는 시간 평균 전류를 정확하게 공급, 진짜 아날로그 전압 생성 없이 제어 가능.

대표적 PWM 애플리케이션: 스피커 오디오 출력, LED 디밍, 서보 모터·컴퓨터 팬·펌프·전기차용 브러시리스 DC 모터 같은 유도 모터 토크 제어.

참고: FPGA 핀 PWM으로 RC 서보 컨트롤러

PWM 작동 원리

전원을 높은 주파수로 100%와 0% 사이 전환하면 부하가 보는 시간 평균 전류는 전원이 켜진 시간 비율에 정비례. 다음 다이어그램으로 원리 설명:

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

듀티 사이클

듀티 사이클은 각 주기 동안 PWM 출력이 하이 유지되는 시간 정의. 백분율로 표현, 이진 카운터 값으로부터 계산:

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

VHDL 구현에서 듀티 사이클을 부호 없는 정수로 다루어 PWM 카운터의 전체 해상도 활용. 0% 듀티 사이클은 출력을 영구히 끄고, 100%는 계속 켬. 달성 가능한 해상도는 카운터 폭에 의해 결정.

이진 듀티 사이클 값을 백분율로 변환 공식:

\mathit{duty\_cycle\_percentage} = \frac{\mathit{commanded\_duty\_cycle} * 100}{2^\mathit{pwm\_bits} - 1}

PWM 주파수

PWM 주파수는 주기의 역수:

\mathit{pwm\_freq} = \frac{1}{\mathit{pwm\_period}}

적절한 주파수 선택은 대상 디바이스 의존. LED는 가시적 깜빡임 방지 위해 수백 헤르츠면 충분. 브러시리스 DC 모터는 보통 수십 킬로헤르츠 범위 동작; 주파수 너무 낮으면 기계적 진동, 너무 높으면 전력 낭비.

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

MOSFET 스위치가 FPGA 로직보다 느리므로 PWM을 너무 빠르게 동작시키면 트랜지스터가 부분 도통 상태에서 시간 보내 추가 열 발생.

PWM 생성기 모듈

아래는 어떤 카운터 폭과 클럭 분주 인자로도 인스턴스화 가능한 제네릭 VHDL PWM 컨트롤러 구현.

엔티티 선언

 entity pwm is generic ( pwm_bits : integer; clk_cnt_len : positive := 1 ); port ( clk : in std_logic; rst : in std_logic; duty_cycle : in unsigned(pwm_bits - 1 downto 0); pwm_out : out std_logic ); end pwm; 

clk와 rst 포트가 동기 제어 제공. duty_cycle 입력 폭은 pwm_bits로 정의되어 카운터 해상도 직접 구성 가능. pwm_out 신호는 MOSFET 게이트 구동하는 FPGA 핀으로 라우팅.

내부 신호

 signal pwm_cnt : unsigned(pwm_bits - 1 downto 0); signal clk_cnt : integer range 0 to clk_cnt_len - 1; 

pwm_cnt 카운터가 듀티 사이클 폭 미러링. clk_cnt 카운터가 선택적 클럭 분주 구현; clk_cnt_len을 1로 설정하면 분주 비활성화 및 관련 로직 제거.

클럭 분주 프로세스

 CLK_CNT_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then clk_cnt <= 0; else if clk_cnt < clk_cnt_len - 1 then clk_cnt <= clk_cnt + 1; else clk_cnt <= 0; end if; end if; end if; end process; 

기본 clk_cnt_len = 1이면 합성 도구가 이 프로세스 자동 제거.

PWM 출력 프로세스

 PWM_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then pwm_cnt <= (others => '0'); pwm_out <= '0'; else if clk_cnt_len = 1 or clk_cnt = 0 then pwm_cnt <= pwm_cnt + 1; pwm_out <= '0'; if pwm_cnt = unsigned(to_signed(-2, pwm_cnt'length)) then pwm_cnt <= (others => '0'); end if; if pwm_cnt < duty_cycle then pwm_out <= '1'; end if; end if; end if; end if; end process; 

카운터는 clk_cnt가 0일 때만 증가하여 PWM 주파수 효과적으로 스로틀링. pwm_cnt를 두 번째로 높은 값에서 리셋하는 조건문이 100% 듀티 사이클 달성 보장.

\mathit{pwm\_hz} = \frac{\mathit{clk\_hz}}{(2^\mathit{pwm\_bits} - 1) * \mathit{clk\_cnt\_len}}

최상위 설계

PWM 컨트롤러 시연 위해 설계가 Lattice iCEstick FPGA의 파워온 LED 구동. 보드 12MHz 발진기가 카운터 공급해 LED 강도를 톱니 패턴으로 제어.

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

엔티티 선언

 entity pwm_led is generic ( pwm_bits : integer := 8; cnt_bits : integer := 25; clk_cnt_len : positive := 47 ); port ( clk : in std_logic; rst_n : in std_logic; led_1 : out std_logic; led_2 : out std_logic; led_3 : out std_logic; led_4 : out std_logic; led_5 : out std_logic ); end pwm_led; 

12MHz 클럭과 선택한 제네릭으로 약 1kHz PWM 주파수 생성:
\frac{12e6}{(2^8 - 1) * 47} \approx 1 \text{ kHz}

cnt_bits 제네릭이 25비트 톱니 카운터 구동해 LED 듀티 사이클 제어. 주기 약 2.8Hz:

\frac{2^{\mathit{cnt\_bits}}}{\mathit{clk\_hz}} = \frac{2^{25}}{12e6} \approx 2.8 \text{ Hz}

LED 5만 사용, 나머지 LED는 로우로 묶어 불필요한 점등 방지.

내부 신호와 배선

 architecture str of pwm_led is signal rst : std_logic; signal cnt : unsigned(cnt_bits - 1 downto 0); signal pwm_out : std_logic; alias duty_cycle is cnt(cnt'high downto cnt'length - pwm_bits); begin led_1 <= '0'; led_2 <= '0'; led_3 <= '0'; led_4 <= '0'; led_5 <= pwm_out; 

rst 신호는 외부 리셋의 동기화된 비반전 버전. 별칭 duty_cycle이 cnt의 최상위 비트들을 PWM 컨트롤러에 매핑.

모듈 인스턴스화

 RESET : entity work.reset(rtl) port map ( clk => clk, rst_n => rst_n, rst => rst ); PWM : entity work.pwm(rtl) generic map ( pwm_bits => pwm_bits, clk_cnt_len => clk_cnt_len ) port map ( clk => clk, rst => rst, duty_cycle => duty_cycle, pwm_out => pwm_out ); COUNTER : entity work.counter(rtl) generic map ( counter_bits => cnt'length ) port map ( clk => clk, rst => rst, count_enable => '1', counter => cnt ); 

시뮬레이션

제네릭 덕분에 시뮬레이션 가속 쉬움. cnt_bits와 clk_cnt_len 줄여 몇 초 대신 몇 마이크로초 만에 전체 PWM 사이클 관찰.

테스트벤치 인스턴스화:

 DUT : entity work.pwm_led(str) generic map ( pwm_bits => 8, cnt_bits => 16, clk_cnt_len => 1 ); 

ModelSim 파형은 톱니 카운터가 LED 밝기 구동. 듀티 사이클 최대값 도달 시 각 사이클 팁에 짧은 '온' 펄스 나타남.

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

FPGA 구현

iCEcube2로 합성 후 설계가 ice40hx1ktq144 파트에서 사용 가능한 64 LUT 중 5%만 소비:

 Resource Usage Report for pwm_led Mapping to part: ice40hx1ktq144 Cell usage: GND 3 uses SB_CARRY 31 uses SB_DFF 5 uses SB_DFFSR 39 uses SB_GB 1 use VCC 3 uses SB_LUT4 64 uses I/O ports: 7 I/O primitives: 7 SB_GB_IO 1 use SB_IO 6 uses I/O Register bits: 0 Register bits not including I/Os: 44 (3%) Total load per clock: pwm_led|clk: 1 @S |Mapping Summary: Total LUTs: 64 (5%) 

Diamond 스탠드얼론 프로그래머로 USB 통한 FPGA 프로그래밍 간단. 결과 LED 애니메이션: 부드러운 밝기 램프 후 사이클 반복 전 잠깐 어두워짐.

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

사인파 듀티 사이클로 호흡 LED

톱니 카운터를 사인파 룩업 테이블로 교체하면 알림 LED에서 흔히 보이는 자연스러운 '호흡' 효과 생성.

VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모

차기 기사에서 블록 RAM 사용 사인파 생성기 구축해 pwm_led 설계에 통합하는 법 다룰 예정.

다음 포스트 읽기: 블록 RAM에 저장된 사인파로 호흡 LED 효과 만들기

참고: FPGA 핀 PWM으로 RC 서보 컨트롤러

VHDL

  1. PWM 전력 컨트롤러: 펄스 폭 변조 램프 드라이버 제작
  2. VHDL 문자열 리스트 구현: 모범 사례와 예제
  3. Tcl 기반 VHDL 코드락 모듈 테스트벤치 만들기
  4. VHDL 테스트벤치 시뮬레이션 우아하게 종료하기
  5. VHDL 난수 생성: 균일 분포부터 OSVVM까지
  6. 블록 RAM에서 견고한 VHDL 링 버퍼 FIFO 설계하기
  7. VHDL 자가 검증 테스트벤치 구축 실전 가이드
  8. VHDL에서 보호 타입과 액세스 포인터로 동적 링크드 리스트 구현하기
  9. 프로세스 내 프로시저로 VHDL FSM 설계 깔끔하게 만들기
  10. 커패시터 충전(Charging Capacitors) 단계별 안전 가이드: 차량 오디오 적용 포함