How to use a function in VHDL - VHDLwhiz (2024)

Table of Contents
Exercise Analysis Takeaway References

Functions are subprograms in VHDL which can be used for implementing frequently used algorithms. A function takes zero or more input values, and it always returns a value. In addition to the return value, what sets a function apart from a procedure, is that it cannot contain Wait-statements. This means that functions always consume zero simulation time.

If you are familiar with functions or methods from other programming languages, VHDL functions should be easy to grasp. In VHDL we cannot omit the return value or return void, a function always has to return something and the return value has to be assigned to something.

This blog post is part of the Basic VHDL Tutorials series.

In VHDL, there are two types of functions, pure and impure functions. That a function is pure means that it will not be allowed to modify or read any external signal. We can be certain that when we call a pure function with certain arguments, it will always return the same value. We say that the function doesn’t have any side effects.

The syntax for declaring a function in VHDL is:

[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;

The pure/impure keyword is optional, although it will default to pure if the keyword is omitted. All parameters are treated as constants inside of the function. Thus, they cannot be changed. The default values are optional, and the function must always terminate at a return statement.

Functions have their own declarative region between the is and begin keywords. Constants, signals, or variables declared here are valid only within the function itself, and they will not retain their values through subsequent calls to the function.

Exercise

In this tutorial, we are going to focus on the pure function. Impure functions will be covered in a later tutorial in this series.

In the previous tutorial, we created a traffic lights controller module using a finite-state machine (FSM). We copy-pasted many of the lines containing timer calculations from one state to another, only changing one constant slightly.

Find out how you can simplify the state machine code by using a function:

The final code for the function testbench:

library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all; entity T21_FunctionTb isend 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;

The final code for the traffic lights module:

library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all; entity T21_TrafficLights isgeneric(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;

The waveform after we entered the run 5 min command in the ModelSim console:

How to use a function in VHDL - VHDLwhiz (1)

The waveform with cursors added at the transitions to and from the StartNorth state:

How to use a function in VHDL - VHDLwhiz (2)

Need the Questa/ModelSim project files?

Let me send you a Zip with everything you need to get started in 30 seconds

How does it work?

Tested on Windows and Linux Loading Gif.. How to use a function in VHDL - VHDLwhiz (3)

By submitting, you consent to receive marketing emails from VHDLwhiz (unsubscribe anytime).

Analysis

We replaced the timer calculations from the previous tutorial if Counter = ClockFrequencyHz * 5 -1 then with a call to the new CounterVal function we created: if Counter = CounterVal(Seconds => 5) then.

We can see from the first waveform screenshot that the module’s function is unchanged. Using functions for repetitive tasks is good design practice. Especially if you can replace calculations with more readable lines containing terms like Minutes and Seconds.

Another advantage of using functions is that we can change the implementation of all the timers at once, instead of doing it line by line. For example, if we had written return TotalSeconds * ClockFrequencyHz; in the CounterVal function, all the timers would have lasted one clock cycle too long. We could then change this to return TotalSeconds * ClockFrequencyHz -1; in the CounterVal function, and all the timers would be fixed at once.

If we examine the last waveform screenshot, we can see why we need to subtract 1 from the timer value that is returned from the CounterVal function. This waveform examines the duration of the StartNorth state, it should last for exactly five seconds. When the State signal changes to StartNorth, the Counter value is 0, and it only changes after the next clock cycle. So, if we had counted up to 500 clock cycles, the StartNorth state would have actually lasted for 501 cycles. With our testbench running at 100 Hz, 500 clock cycles is exactly five seconds.

Get free access to the Basic VHDL Course

Download the course material and get started.

You will receive a Zip with exercises for the 23 video lessons as VHDL files where you fill in the blanks, code answers, and a link to the course.

By submitting, you consent to receive marketing emails from VHDLwhiz (unsubscribe anytime).

Takeaway

  • Functions can take zero or more parameters, but they always return a value
  • Functions cannot contain wait statements
  • Pure functions cannot have side effects, while impure functions can.

Go to the next tutorial »

How to use a function in VHDL - VHDLwhiz (2024)

References

Top Articles
23 April 2013 - [PDF Document]
[PDF] The Hunt for Zero Point - Free Download PDF
Red Carpet Oil Change Blackstone
Jazmen00 Mega
Brett Cooper Wikifeet
799: The Lives of Others - This American Life
5 Anterior Pelvic Tilt Exercises
Lvc Final Exam Schedule
United Center: Home of the Chicago Bulls & Chicago Blackhawks - The Stadiums Guide
Magic Seaweed Pleasure Point
6023445010
Making a Docker Container Use a VPN – Natural Born Coder
The Center Breakfast, Lunch & Snack Menus September 2024
Does Publix Pharmacy Accept Sunshine Health
Bigbug Rotten Tomatoes
Last minute moving service van local mover junk hauling pack loading - labor / hauling / moving - craigslist
Fk Jones Obituary
Xxc Renegade 1000 Xxc Price In India Price
Meridamoonbeams
Used Travel Trailers Under $5000 Craigslist
Unmhealth My Mysecurebill
Money Rose Stencil
Katmoie
Fto Kewanee
Aflac Dulles Synergy
Left Periprosthetic Femur Fracture Icd 10
Showcameips
Xdm16Bt Manual
Subway And Gas Station Near Me
Circuit Court Evanston Wy
1084 Sadie Ridge Road, Clermont, FL 34715 - MLS# O6240905 - Coldwell Banker
Preventice Learnworlds
6030 Topsail Rd, Lady Lake, FL 32159 - MLS G5087027 - Coldwell Banker
Emily Dealy Obituary
Magma Lozenge Location
Cavender's Boot City Lafayette Photos
The Little Mermaid 2023 Showtimes Near Marcus South Pointe Cinema
Sam's Club Near Me Gas Price
Ma Scratch Tickets Codes
Brooklyn Park City Hall
Farmers Branch Isd Calendar
Best Pizza In Ft Myers
Jason Brewer Leaving Fox 25
Diabetes Care - Horizon Blue Cross Blue Shield of New Jersey
Goldthroat Goldie
Thoren Bradley Lpsg
Sona Systems Tcu
8569 Marshall St, Merrillville, IN 46410 - MLS 809825 - Coldwell Banker
Magnifeye Alcon
Crustless Pizza Bowl Pizza Hut
Guy Ritchie's The Covenant Showtimes Near Century 16 Eastport Plaza
Sam Smith Lpsg
Latest Posts
Article information

Author: Terrell Hackett

Last Updated:

Views: 5772

Rating: 4.1 / 5 (72 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Terrell Hackett

Birthday: 1992-03-17

Address: Suite 453 459 Gibson Squares, East Adriane, AK 71925-5692

Phone: +21811810803470

Job: Chief Representative

Hobby: Board games, Rock climbing, Ghost hunting, Origami, Kabaddi, Mushroom hunting, Gaming

Introduction: My name is Terrell Hackett, I am a gleaming, brainy, courageous, helpful, healthy, cooperative, graceful person who loves writing and wants to share my knowledge and understanding with you.