𝐐𝐮𝐞𝐬𝐭𝐢𝐨𝐧: 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:

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.

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:

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.
“𝑺𝒉𝒂𝒓𝒊𝒏𝒈 𝒌𝒏𝒐𝒘𝒍𝒆𝒅𝒈𝒆 𝒊𝒔 𝒕𝒉𝒆 𝒎𝒐𝒔𝒕 𝒆𝒇𝒇𝒊𝒄𝒊𝒆𝒏𝒕 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒎𝒆𝒕𝒉𝒐𝒅”