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

Cara menggunakan Fungsi di VHDL

Fungsi adalah subprogram dalam VHDL yang dapat digunakan untuk mengimplementasikan algoritma yang sering digunakan. Sebuah fungsi mengambil nol atau lebih nilai input, dan selalu mengembalikan nilai. Selain nilai kembalian, yang membedakan fungsi dari prosedur adalah tidak dapat berisi pernyataan Tunggu. Ini berarti bahwa fungsi selalu menggunakan waktu simulasi nol.

Jika Anda terbiasa dengan fungsi atau metode dari bahasa pemrograman lain, fungsi VHDL seharusnya mudah dipahami. Dalam VHDL kita tidak bisa menghilangkan nilai kembalian atau mengembalikan batal, suatu fungsi selalu harus mengembalikan sesuatu dan nilai kembalian harus diberikan ke sesuatu.

Pos blog ini adalah bagian dari seri Tutorial VHDL Dasar.

Dalam VHDL, ada dua jenis fungsi, murni dan tidak murni fungsi. Bahwa suatu fungsi adalah murni berarti fungsi tersebut tidak akan diizinkan untuk mengubah atau membaca sinyal eksternal apa pun. Kita dapat yakin bahwa ketika kita memanggil fungsi murni dengan argumen tertentu, itu akan selalu mengembalikan nilai yang sama. Kami mengatakan bahwa fungsi tersebut 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 murni/tidak murni adalah opsional, meskipun default akan murni jika kata kunci dihilangkan. Semua parameter diperlakukan sebagai konstanta di dalam fungsi. Dengan demikian, mereka tidak dapat diubah. Nilai default adalah opsional, dan fungsi harus selalu berakhir pada return pernyataan.

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

Olahraga

Dalam tutorial ini, kita akan fokus pada fungsi murni, fungsi tidak murni akan dibahas dalam tutorial selanjutnya dalam seri ini.

Pada tutorial sebelumnya, kami membuat modul pengontrol lampu lalu lintas menggunakan finite-state machine (FSM). Kami menyalin-menempelkan banyak baris yang berisi penghitungan penghitung waktu dari satu keadaan ke keadaan lain, hanya mengubah satu konstanta sedikit.

Cari tahu bagaimana Anda dapat menyederhanakan kode mesin status dengan menggunakan fungsi:

Kode terakhir untuk fungsi testbench :

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 terakhir untuk modul lampu lalu lintas :

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;

Bentuk gelombang setelah kita memasukkan run 5 min perintah di konsol ModelSim:

Bentuk gelombang dengan kursor ditambahkan pada transisi ke dan dari StartNorth negara:

Analisis

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

Kita dapat melihat dari tangkapan layar bentuk gelombang pertama bahwa fungsi modul tidak berubah. Menggunakan fungsi untuk tugas yang 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 menggunakan fungsi adalah kita dapat mengubah implementasi semua timer sekaligus, daripada melakukannya baris demi baris. Misalnya, jika kita telah menulis return TotalSeconds * ClockFrequencyHz; di CounterVal fungsi, semua timer akan bertahan satu siklus clock terlalu lama. Kami kemudian dapat mengubah ini menjadi return TotalSeconds * ClockFrequencyHz -1; di CounterVal fungsi, dan semua timer akan diperbaiki sekaligus.

Jika kita memeriksa tangkapan layar bentuk gelombang terakhir, kita dapat melihat mengapa kita perlu mengurangi 1 dari nilai timer yang dikembalikan dari CounterVal fungsi. Bentuk gelombang ini memeriksa durasi StartNorth negara, itu harus berlangsung selama tepat lima detik. Ketika State sinyal berubah menjadi StartNorth , Counter nilainya adalah 0, dan hanya berubah setelah siklus clock berikutnya. Jadi, jika kita menghitung hingga 500 siklus clock, StartNorth negara akan benar-benar berlangsung selama 501 siklus. Dengan testbench kami yang berjalan pada 100 Hz, 500 siklus clock adalah tepat lima detik.

Bawa Pulang

Pergi ke tutorial berikutnya »


VHDL

  1. Bagaimana Kami Menggunakan Molibdenum?
  2. Cara membuat daftar string di VHDL
  3. Bagaimana menghentikan simulasi di testbench VHDL
  4. Cara membuat pengontrol PWM di VHDL
  5. Cara menghasilkan angka acak di VHDL
  6. Cara menggunakan Prosedur dalam Proses di VHDL
  7. Cara menggunakan Fungsi Tidak Murni di VHDL
  8. realloc() Fungsi di C Library:Bagaimana cara menggunakannya? Sintaks &Contoh
  9. free() Fungsi di pustaka C:Bagaimana cara menggunakannya? Belajar dengan Contoh
  10. Cara Menggunakan Penggiling Pemotong