𝐐𝐮𝐞𝐬𝐭𝐢𝐨𝐧: Does it differ to add parenthesis and group two operands to get more efficient adder structure in Vivado?

𝐀𝐧𝐬𝐰𝐞𝐫: Some synthesis tools require you to write “clever” RTL code to help synthesis tool to generate netlist that is easier to achieve timing closure for arithmetic operations. What about Vivado, let’s see this with an example.

I will write 2 different codes for adding 4 numbers one with grouping 2 numbers with parenthesis and the other is just has no parenthesis.

The first code is:

entity test_code is
port (
num1_i      : in std_logic_vector (31 downto 0);
num2_i      : in std_logic_vector (31 downto 0);
num3_i      : in std_logic_vector (31 downto 0);
num4_i      : in std_logic_vector (31 downto 0);
result_o    : out std_logic_vector (31 downto 0)
);
end test_code;

architecture Behavioral of test_code is 

begin

result_o <= std_logic_vector(signed(num1_i) + signed(num2_i) + signed(num3_i) + signed(num4_i));

end Behavioral;

Here is the elaboration result of the Vivado for the code below:

FPGA-VHDL-KnowHow-Series-7-1
FPGA-VHDL-KnowHow-Series-7-1

Critical path has 3 adder circuits starting from num1_i or num2_i.

In some RTL trainings or web posts you see that for efficiency in arithmetic logic you need to use parenthesis to get a tree form adder structure, which has less logic levels. If we write our code in a different way, then the elaboration is different:

entity test_code is
port (
num1_i      : in std_logic_vector (31 downto 0);
num2_i      : in std_logic_vector (31 downto 0);
num3_i      : in std_logic_vector (31 downto 0);
num4_i      : in std_logic_vector (31 downto 0);
result_o    : out std_logic_vector (31 downto 0)
);
end test_code;

architecture Behavioral of test_code is 

begin

result_o <= std_logic_vector(
    (signed(num1_i) + signed(num2_i)) 
    + 
    (signed(num3_i) + signed(num4_i))
    );

end Behavioral;
FPGA-VHDL-KnowHow-Series-7-2
FPGA-VHDL-KnowHow-Series-7-2

This time the critical path is 2 adder circuits instead of 3.

So, if we evaluate the 2 code methods by just looking the elaboration results, it seems the second code is better with respect to timing closure. But, let’s synthesize the codes and see the netlists.

Here is the critical path after synthesis of the first code:

FPGA-VHDL-KnowHow-Series-7-3
FPGA-VHDL-KnowHow-Series-7-3

It has 10 levels of combinational paths excluding IO buffers. The total delay is 8.137 ns of which 5.611 is logical delay and 2.526 is net delay.

Let’s synthesize the second code. But after synthesis we see that the netlist and the timing delay for the critical path is same with the first one, surprise mfs:

FPGA-VHDL-KnowHow-Series-7-4
FPGA-VHDL-KnowHow-Series-7-4

To summarize, always need to check the synth results. Some synthesis tools in ASIC maybe pay critical attention to using parenthesis but not Vivado. It automatically optimizes the adder circuit.

“𝑺𝒉𝒂𝒓𝒊𝒏𝒈 𝒌𝒏𝒐𝒘𝒍𝒆𝒅𝒈𝒆 𝒊𝒔 𝒕𝒉𝒆 𝒎𝒐𝒔𝒕 𝒆𝒇𝒇𝒊𝒄𝒊𝒆𝒏𝒕 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒎𝒆𝒕𝒉𝒐𝒅”