NewANADOLOGIC Hardware Academy is live: 240 free, AI-graded FPGA & SoC questions.Start learning

FPGA & VHDL KnowHow Series2 min read

FPGA Anadologic

๐๐ฎ๐ž๐ฌ๐ญ๐ข๐จ๐ง: VHDL allows utilization of variable types inside process, function or procedure. They are different than signals in many ways, but most important one is variables are assigned immediately unlike signals. The question is, how many FFs infer for a variable in a clocked process?

๐€๐ง๐ฌ๐ฐ๐ž๐ซ: The most common usage of variables is as follows:

  • First assign values to variables; i.e. initialize them
  • Then write your algorithm utilizing variables by reading or writing them
  • Finally, assign variables to the signals

There is a simple rule for FF inference of variables inside a clocked process: If a variable is read before assigned in the sequence inside a process, then it infers register. So, if you follow the common approach, variables will not infer registers but only signals will.

Letโ€™s see the synthesis result with an example of parity calculation of a bit vector:

library IEEE;
use IEEE.std_logic_1164.all;

entity VARTEST is
port (
clk         : in std_logic;
input1      : in std_logic_vector (7 downto 0);
output1     : out std_logic
);
end VARTEST;

architecture RTL of VARTEST is

begin

process (clk)
    variable TMP : std_logic;
begin
if (rising_edge(clk)) then

    TMP := '0';
    for J in input1'range loop
        TMP := TMP xor input1(J);
    end loop;
    output1 <= TMP;

end if;
end process;

end RTL;

Here is the netlist schematics of the Vivado for the code below:

FPGA & VHDL KnowHow Series - 9 - 1

We can also use a function to utilize variables and evaluate the synthesis result:

library IEEE;
use IEEE.std_logic_1164.all;

entity VARTEST is
port (
clk         : in std_logic;
input1      : in std_logic_vector (7 downto 0);
output1     : out std_logic
);
end VARTEST;

architecture RTL of VARTEST is

function PARITY_FUNC (FP : std_logic_vector)
                        return std_logic is
    variable TMP : std_logic;
begin
    TMP := '0';
    for J in FP'range loop
        TMP := TMP xor FP(J);
    end loop;
    return TMP;
end PARITY_FUNC;

begin

process (clk) begin
if (rising_edge(clk)) then

    output1 <= PARITY_FUNC(input1);

end if;
end process;

end RTL;

The netlist schematics also shows that only 1 FF is inferred.

FPGA & VHDL KnowHow Series - 9 - 2

Letโ€™s see whatโ€™s going to happen if we first read a variable inside a process and then use it. Here is an example code, where 3 variables are read before assignment and 3 variables are assigned first and then read. Finally, a signal is assigned to a function of the all variables.

library IEEE;
use IEEE.std_logic_1164.all;

entity VARTEST is
port (
clk         : in std_logic;
input1      : in std_logic_vector (2 downto 0);
output1     : out std_logic_vector (2 downto 0)
);
end VARTEST;

architecture RTL of VARTEST is

begin

process (clk)
    variable TMP1 : std_logic;
    variable TMP2 : std_logic;
    variable TMP3 : std_logic;
    variable TMP4 : std_logic;
    variable TMP5 : std_logic;
    variable TMP6 : std_logic;
begin
if (rising_edge(clk)) then
    TMP1 := input1(0);
    TMP2 := input1(1);
    TMP3 := input1(2);
    output1(0) <= TMP4 or TMP1;
    output1(1) <= TMP5 or TMP2;
    output1(2) <= TMP6 or TMP3;
    TMP4 := TMP1;
    TMP5 := TMP2;
    TMP6 := TMP3;
end if;
end process;

end RTL;

Here is the netlist schematics result of the Vivado for the code below:

FPGA & VHDL KnowHow Series - 9 - 3

We see 3 FFs are inferred for output1, which is expected. We also see 3 more FFs are inferred for TMP4, TMP5 and TMP6 due to the fact that they are first read before assignment inside the process.

To summarize, do not forget this simple rule while using variables in VHDL, if a variable is read before assigned in the sequence inside a process, then it infers register. If you know what you are doing, then it is OK, but the common usage of variables is first you initialize them and then use them. Finally assign variables to signals.

โ€œ๐‘บ๐’‰๐’‚๐’“๐’Š๐’๐’ˆ ๐’Œ๐’๐’๐’˜๐’๐’†๐’…๐’ˆ๐’† ๐’Š๐’” ๐’•๐’‰๐’† ๐’Ž๐’๐’”๐’• ๐’†๐’‡๐’‡๐’Š๐’„๐’Š๐’†๐’๐’• ๐’๐’†๐’‚๐’“๐’๐’Š๐’๐’ˆ ๐’Ž๐’†๐’•๐’‰๐’๐’…โ€

โ† All posts