vhdlfpga

When should I use a function over a procedure?


I've been trying to understand when to use a Function and when to use a Procedure in VHDL. From my understanding both are Synthesizable. You use a Function when you have 1 return value and a Procedure when you have multiple outputs. My question is why don't I just use a procedure all the time (1 output or many outputs)?

I've googled around trying to find a reason to prefer one over the other, I get examples such as "use a function for a calculation, but use a procedure for a process" but that doesn't make it clear to me why to choose Function when Procedure can do the same thing.


Solution

  • If the intent is really to compute a single result a function can lead to a better readability: c <= mult(a, b) is easier to understand than mult(a, b, c) where you don't immediately see which parameters are inputs and which are outputs. Moreover, the same function can be used to assign a constant, a variable or a signal while a procedure can assign a variable or a signal but not both, and cannot be used to assign a constant.

    Another important difference is that you can use the wait statement in a procedure but not in a function. So, if you want to implement a read sequence of operations of a communication protocol (say AXI), you can encapsulate all this in a procedure but not in a function:

    procedure read(signal axi_in: in axi_if_in; signal axi_out: in axi_if_out) is
    begin
      ...
      wait until rising_edge(axi_in.clk) and axi_in.arvalid = '1';
      ...
      axi_out.arready <= '1';
      axi_out.rvalid <= '1';
      axi_out.rdata <= reg(to_integer(axi_in.araddr);
      axi_out.rresp <= axi_okay;
      ...
      wait until rising_edge(axi_in.clk) and axi_in.arready = '1';
      ...
    end procedure read;
    

    Finally, you can overload the VHDL operators, for instance to design your own package dedicated to complex numbers. And this takes the form of functions because the operators have an equivalent functional form:

    function "+"(a, b: cpx) return cpx is
    begin
      return (a.r + b.r, a.i + b.i);
    end function "+";
    
    ...
    signal a, b, c: cpx;
    ...
    c <= a + b;
    ...