This is related to how the RAMB18 and RAMB36 is counted.
The BRAM utilization is given by the number of RAMB36s.
When Vivado counts the BRAM, it treats 2 RAMB18 as 1 RAMB36.
If the RAMB18 number is an odd value, it counts the last 1 RAMB18 as 1 RAMB36.
2 RAMB18 + 1 RAMB36 = 2 RAMB36
1 RAMB18 + 1 RAMB36 = 2 RAMB36
3 RAMB18 + 1 RAMB36 = 3 RAMB36
In the above example, BRAMs in the sub-modules are like this:
ram18_36_inst: 1 RAMB18 + 1 RAMB36 = 2 RAMB36
ram36_instx2: 2 RAMB36 = 2 RAMB36
ram18_instx1: 1 RAMB18 = 1 RAMB36
ram18_instx2: 2 RAMB18 = 1 RAMB36
ram36_instx1: 1 RAMB36 = 1 RAMB36
So in the top: 4 RAMB18 + 4 RAMB36 = 6 RAMB36
The BRAM utilization in a parent module does not always match the sum of its sub-modules.
This is an expected behavior.