Implementasi Pengontrol PWM dalam VHDL: Desain, Simulasi, dan Demo FPGA
Modulasi lebar pulsa (PWM) mengubah pin digital FPGA menjadi pengontrol analog yang kuat. Dengan menghidupkan dan mematikan suplidan pada kecepatan tinggi, PWM memberikan arus rata-rata yang tepat yang diperlukan perangkat, tanpa pernah menghasilkan tegangan analog sejati.
Aplikasi PWM umum meliputi output audio untuk speaker, redup LED, dan kontrol torsi motor induksi seperti motor servo, kipas komputer, pompa, dan motor DC brushless untuk kendaraan listrik.
Lihat juga: Pengontrol servo RC menggunakan PWM dari pin FPGA
Bagaimana PWM Bekerja
Saat suplidan diaktifkan antara 100 % dan 0 % pada frekuensi tinggi, arus rata-rata yang dilihat beban langsung proporsional dengan fraksi waktu suplidan menyala. Diagram berikut mengilustrasikan prinsip ini:
Siklus Kerja
Siklus kerja mendefinisikan berapa lama output PWM tetap tinggi selama setiap periode. Diekspresikan sebagai persentase, itu dihitung dari nilai counter biner:
Dalam implementasi VHDL, kita memperlakukan siklus kerja sebagai integer tanpa tanda, memberikan resolusi penuh dari counter PWM. Siklus kerja 0 % mematikan output secara permanen, sedangkan siklus kerja 100 % menjaga output terus-menerus menyala. Resolusi yang dapat dicapai ditentukan oleh lebar counter.
Untuk mengonversi nilai siklus kerja biner ke persentase, gunakan:
Memilih frekuensi yang tepat bergantung pada perangkat target. Untuk LED, beberapa ratus hertz sudah cukup untuk menghindari berkedip yang terlihat. Motor DC brushless, di sisi lain, biasanya beroperasi dalam rentang puluhan kilohertz; terlalu rendah dapat menghasilkan getaran mekanis, sementara terlalu tinggi membuang daya.
Karena saklar MOSFET lebih lambat dari logika FPGA, mengoperasikan PWM terlalu cepat dapat menyebabkan transistor menghabiskan waktu dalam keadaan setengah menghantarkan, yang membuang panas ekstra.
Modul Pembangkit PWM
Di bawah ini adalah implementasi VHDL generik dari pengontrol PWM yang dapat dibuat instance dengan lebar counter apa pun dan faktor pembagian clock.
Deklarasi Entitas
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;
Port clk dan rst menyediakan kontrol sinkron. Input duty_cycle memiliki lebar yang ditentukan oleh pwm_bits, sehingga resolusi counter dapat dikonfigurasi langsung. Sinyal pwm_out dirutekan ke pin FPGA yang menggerakkan gate MOSFET.
Sinyal Internal
signal pwm_cnt : unsigned(pwm_bits - 1 downto 0); signal clk_cnt : integer range 0 to clk_cnt_len - 1;
Counter pwm_cnt mencerminkan lebar siklus kerja. Counter clk_cnt mengimplementasikan pembagi clock opsional; menyetel clk_cnt_len ke 1 menonaktifkan pembagi dan menghapus logika yang terkait.
Proses Pembagi Clock
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;
Dengan default clk_cnt_len = 1, alat sintesis akan menghapus proses ini secara otomatis.
Proses Output 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;
Counter hanya bertambah ketika clk_cnt adalah nol, secara efektif menstrottel frekuensi PWM. Kondisional yang mereset pwm_cnt pada nilai tertinggi kedua-nya menjamin bahwa siklus kerja 100 % dapat dicapai.
Untuk mendemonstrasikan pengontrol PWM, desain menggerakkan LED power-on pada papan FPGA Lattice iCEstick. Osilator 12 MHz papan memberi makan counter yang mengontrol intensitas LED dalam pola gigi gergaji.
Deklarasi Entitas
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;
Clock 12 MHz dan generics yang dipilih menghasilkan frekuensi PWM sekitar 1 kHz: \frac{12e6}{(2^8 - 1) * 47} \approx 1 \text{ kHz}
Generic cnt_bits mendorong counter gigi gergaji 25-bit yang mengontrol siklus kerja LED. Periodenya sekitar 2,8 Hz:
Generics memudahkan untuk mempercepat simulasi. Dengan mengurangi cnt_bits dan clk_cnt_len kita dapat mengamati siklus PWM penuh dalam beberapa mikrodetik daripada beberapa detik.
Gelombang di ModelSim menunjukkan counter gigi gergaji yang mengontrol kecerahan LED. Pulsa "on" singkat muncul di ujung setiap siklus ketika siklus kerja mencapai nilai maksimumnya.
Implementasi FPGA
Setelah sintesis dengan iCEcube2, desain hanya mengonsumsi 5 % dari 64 LUT yang tersedia pada bagian ice40hx1ktq144:
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%)
Memprogram FPGA melalui USB dengan programmer standalone Diamond sangatlah mudah. Animasi LED yang dihasilkan menunjukkan ramp kecerahan yang halus diikuti oleh redup singkat sebelum siklus berulang.
LED Bernapas dengan Siklus Kerja Gelombang Sinus
Mengganti counter gigi gergaji dengan tabel lookup gelombang sinus menghasilkan efek "bernapas" yang alami, yang biasa dilihat pada LED notifikasi.
Dalam artikel mendatang, kami akan menunjukkan cara membuat pembangkit gelombang sinus menggunakan block RAM dan mengintegrasikannya ke dalam desain pwm_led.
Baca posting berikutnya: Cara membuat efek LED bernapas menggunakan gelombang sinus yang disimpan di block RAM
Lihat juga: Pengontrol servo RC menggunakan PWM dari pin FPGA