Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial programming >> VHDL

Menguasai Fungsi VHDL: Panduan Praktis untuk Desain Efisien

Fungsi adalah subprogram dalam VHDL yang dapat digunakan untuk mengimplementasikan algoritma yang sering digunakan. Fungsi menerima nol atau lebih nilai input, dan selalu mengembalikan nilai. Selain nilai kembali, yang membedakan fungsi dari prosedur adalah bahwa ia tidak dapat berisi pernyataan Wait. Ini berarti fungsi selalu mengonsumsi waktu simulasi nol.

Jika Anda familiar dengan fungsi atau metode dari bahasa pemrograman lain, fungsi VHDL seharusnya mudah dipahami. Dalam VHDL kita tidak dapat menghilangkan nilai kembali atau mengembalikan void, fungsi selalu harus mengembalikan sesuatu dan nilai kembali harus ditetapkan pada sesuatu.

Tulisan blog ini adalah bagian dari seri Tutorial Dasar VHDL.

Dalam VHDL, ada dua jenis fungsi, murni dan tidak murni fungsi. Sebuah fungsi dikatakan murni berarti ia tidak diizinkan untuk mengubah atau membaca sinyal eksternal apa pun. Kami dapat yakin bahwa saat memanggil fungsi murni dengan argumen tertentu, ia akan selalu mengembalikan nilai yang sama. Kami katakan bahwa fungsi tidak memiliki efek samping.

Sintaks untuk mendeklarasikan fungsi dalam VHDL adalah:

[pure|impure] function <function_name> (<parameter1_name> : <parameter1_type> := <default_value>;                                         <parameter2_name> : <parameter2_type> := <default_value>;                                         ... ) return <return_type> is     <constant_or_variable_declaration> begin     <code_performed_by_the_function>     return <value> end function;

Kata kunci pure/impure bersifat opsional, meskipun akan default ke pure jika kata kunci dihilangkan. Semua parameter diperlakukan sebagai konstanta di dalam fungsi. Dengan demikian, mereka tidak dapat diubah. Nilai default bersifat opsional, dan fungsi selalu harus diakhiri pada pernyataan return.

Fungsi memiliki area deklaratifnya sendiri di antara kata kunci in dan begin. Konstanta, sinyal atau variabel yang dideklarasikan di sini valid hanya di dalam fungsi itu sendiri, dan mereka tidak akan mempertahankan nilai mereka melalui panggilan fungsi berikutnya.

Latihan

Dalam tutorial ini, kami akan berfokus pada fungsi murni, fungsi tidak murni akan dibahas dalam tutorial selanjutnya dalam seri ini.

Dalam tutorial sebelumnya, kami telah membuat modul pengontrol lampu lalu lintas menggunakan finite-state machine (FSM). Kami menyalin banyak baris yang berisi perhitungan timer dari satu keadaan ke keadaan lain, hanya mengubah satu konstanta sedikit.

Temukan bagaimana Anda dapat menyederhanakan kode mesin keadaan dengan menggunakan fungsi:

Kode akhir untuk testbench fungsi:

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T21_FunctionTb is end entity; architecture sim of T21_FunctionTb is -- We are using a low clock frequency to speed up the simulation constant ClockFrequencyHz : integer := 100; -- 100 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal NorthRed : std_logic; signal NorthYellow : std_logic; signal NorthGreen : std_logic; signal WestRed : std_logic; signal WestYellow : std_logic; signal WestGreen : std_logic; begin -- The Device Under Test (DUT) i_TrafficLights : entity work.T21_TrafficLights(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, NorthRed => NorthRed, NorthYellow => NorthYellow, NorthGreen => NorthGreen, WestRed => WestRed, WestYellow => WestYellow, WestGreen => WestGreen); -- Process for generating clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); -- Take the DUT out of reset nRst <= '1'; wait; end process; end architecture; 

Kode akhir untuk modul traffic lights:

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T21_TrafficLights is generic(ClockFrequencyHz : natural); port( Clk : in std_logic; nRst : in std_logic; -- Negative reset NorthRed : out std_logic; NorthYellow : out std_logic; NorthGreen : out std_logic; WestRed : out std_logic; WestYellow : out std_logic; WestGreen : out std_logic); end entity; architecture rtl of T21_TrafficLights is -- Enumerated type declaration and state signal declaration type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest); signal State : t_State; -- Calculate the number of clock cycles in minutes/seconds function CounterVal(Minutes : integer := 0; Seconds : integer := 0) return integer is variable TotalSeconds : integer; begin TotalSeconds := Seconds + Minutes * 60; return TotalSeconds * ClockFrequencyHz -1; end function; -- Counter for counting clock periods, 1 minute max signal Counter : integer range 0 to CounterVal(Minutes => 1) +1; begin process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then -- Reset values NorthRed <= '1'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '1'; WestYellow <= '0'; WestGreen <= '0'; State <= NorthNext; Counter <= 0; else -- Default values NorthRed <= '0'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '0'; WestYellow <= '0'; WestGreen <= '0'; Counter <= Counter + 1; case State is -- Red light in all directions when NorthNext => NorthRed <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= StartNorth; end if; -- Yellow light in north/south directions when StartNorth => NorthRed <= '1'; NorthYellow <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= North; end if; -- Green light in north/south directions when North => NorthGreen <= '1'; WestRed <= '1'; -- If 1 minute has passed if Counter = CounterVal(Minutes => 1) then Counter <= 0; State <= StopNorth; end if; -- Red and yellow light in north/south direction when StopNorth => NorthYellow <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= WestNext; end if; -- Red light in all directions when WestNext => NorthRed <= '1'; WestRed <= '1'; -- If 5 seconds have passedf if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= StartWest; end if; -- Yellow light in west/east direction when StartWest => NorthRed <= '1'; WestRed <= '1'; WestYellow <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= West; end if; -- Green light in west/east direction when West => NorthRed <= '1'; WestGreen <= '1'; -- If 1 minute has passed if Counter = CounterVal(Minutes => 1) then Counter <= 0; State <= StopWest; end if; -- Red and yellow light in west/east direction when StopWest => NorthRed <= '1'; WestYellow <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= NorthNext; end if; end case; end if; end if; end process; end architecture; 

Waveform setelah memasukkan perintah run 5 min di konsol ModelSim:
Menguasai Fungsi VHDL: Panduan Praktis untuk Desain Efisien

Waveform dengan kursor ditambahkan pada transisi ke dan dari keadaan StartNorth:
Menguasai Fungsi VHDL: Panduan Praktis untuk Desain Efisien

Analysis

Kami mengganti perhitungan timer dari tutorial sebelumnya if Counter = ClockFrequencyHz * 5 -1 then dengan pemanggilan ke fungsi CounterVal baru yang kami buat: if Counter = CounterVal(Seconds => 5) then.

Kami dapat melihat dari tangkapan layar waveform pertama bahwa fungsi modul tetap tidak berubah. Menggunakan fungsi untuk tugas berulang adalah praktik desain yang baik. Terutama jika Anda dapat mengganti perhitungan dengan baris yang lebih mudah dibaca yang berisi istilah seperti Minutes dan Seconds.

Keuntungan lain dari menggunakan fungsi adalah kami dapat mengubah implementasi semua timer sekaligus, daripada melakukannya baris demi baris. Misalnya, jika kami telah menulis return TotalSeconds * ClockFrequencyHz; dalam fungsi CounterVal, semua timer akan berlangsung satu siklus clock terlalu lama. Kami kemudian dapat mengubah ini menjadi return TotalSeconds * ClockFrequencyHz -1; dalam fungsi CounterVal, dan semua timer akan diperbaiki sekaligus.

Jika kita memeriksa tangkapan layar waveform terakhir, kita dapat melihat mengapa kita perlu mengurangi 1 dari nilai timer yang dikembalikan dari fungsi CounterVal. Waveform ini memeriksa durasi keadaan StartNorth, seharusnya berlangsung tepat lima detik. Ketika sinyal State berubah menjadi StartNorth, nilai Counter adalah 0, dan hanya berubah setelah siklus clock berikutnya. Jadi, jika kita telah menghitung hingga 500 siklus clock, keadaan StartNorth sebenarnya akan berlangsung selama 501 siklus. Dengan testbench kami berjalan pada 100 Hz, 500 siklus clock tepat lima detik.

Menguasai Fungsi VHDL: Panduan Praktis untuk Desain Efisien

Takeaway

Lanjut ke tutorial selanjutnya »


VHDL

  1. Bagaimana Molibdenum Mengubah Industri Modern: Penggunaan, Manfaat, dan Dinamika Pasokan
  2. Membuat Daftar String dalam VHDL: Praktik Terbaik & Contoh
  3. Mengakhiri Simulasi Testbench VHDL dengan Elegan
  4. Implementasi Pengontrol PWM dalam VHDL: Desain, Simulasi, dan Demo FPGA
  5. Menghasilkan Angka Acak dalam VHDL: Dari Uniform hingga OSVVM
  6. Memanfaatkan Prosedur Dalam Proses untuk Desain FSM VHDL yang Lebih Bersih
  7. Menggunakan Fungsi Tidak Murni di VHDL: Meningkatkan Keterbacaan dan Pemeliharaan FSM
  8. Menggunakan realloc() dalam C: Sintaks, Praktik Terbaik & Contoh
  9. Menguasai Fungsi free() dalam C: Panduan Praktis & Contoh
  10. Menguasai Teknik Mesin Gerinda Cutter: Panduan Praktis