Today I did play around with Xilinx Vivado a little, take a look at an example project, look at the synthesis and implementation options (not much new) &cetera.
The last couple of years I have been exclusively working with Xilinx ISE 14.4, mostly avoiding the Project Navigator, but instead using the command line tools like xst, ngdbuild, par, trce and so on directly (from a Makefile). To get some feeling for what awaits me when migrating an existing VHDL project from ISE to Vivado I did create a new Vivado project and imported the code of an existing VHDL project. While doing this I stumbled over a few things that Vivado handles more correctly and a few other things which Vivado, for unknown reasons, does no longer handle as well as ISE (or fails to handle at all).
I am comparing ISE 14.4 against Vivado 2015.3 here!

+1 Vivado correctly complains about a subprogram definition inside a package declaration. ISE did just swallow this piece of code, which isn’t really evil (some people may feel it is comfortable), but not according to standard.

-1 Vivado refuses to synthesize code, which worked fine in ISE, claiming it “does not match the code template” for XYZ. In my case the error popped up for an inferred BRAM.

-1 Vivado refuses to synthesize code which writes to a text file, even if all text IO is masked out by a generic (which turns off all text output). ISE has no problem with this.

+-1 Vivado no longer accepts VHDL expressions in port assignment lists. Despite Vivado handling this according to the standard I do not feel very comfortable with this change. E.g. a lot of existing code uses a simple expression to invert reset polarity in a port assignment list like rstn_i => not rstp.

-1 Vivado will expect files used in read or write operations to actually exist, even if you never actually read from or write to them. In ISE this was not an issue, the file existence was only checked at run time.

Update 2018-01-31 (Vivado 2017.4 was used):

-1 Vivado type inference is not as “flexible” as in ISE. Assume that GTP_ENABLE is a generic of type std_logic_vector, then the following was possible in ISE: GTP_ENABLE => “0”. In Vivado this causes an error (“N visible types match here…“), assuming the standard libraries ieee.std_logic_1164 and ieee.numeric_std are imported (since that’s where those conflicting types come from I assume). Vivado requires explicit type markers: GTP_ENABLE => std_logic_vector'(“0”). This is a difference which can cause a lot of code changes when migrating from ISE to Vivado.

+-1 Vivado is strict when it comes to port association order. When doing sliced/partial port association all associations for a port must appear in contiguous order, otherwise Vivado will complain “Formal port association for ‘rxclk_i’ is non contiguous“.
To clearify this consider the following example:


port map ( …
rxclk_i(0) => fooclk,
rx_i(7 downto 0) => foo,
rxclk_i(1) => barclk,
rx_i(15 downto 8) => bar,
… );

The above is not accepted by Vivado. The port association for rxclk_i and rx_i is not contiguous.
The following port associations are contiguous and won’t trigger an error in Vivado.


port map ( …
rxclk_i(0) => fooclk,
rxclk_i(1) => barclk,w
rx_i(7 downto 0) => foo,
rx_i(15 downto 8) => bar,
… );

Note that this is a VHDL LRM restriction and not specific to Vivado (see stackoverflow). I mention it at this point because ISE is more relaxed about this and does accept non contiguous port association. I see no reason why this should not be allowed, maybe it will become valid in a future VHDL LRM release.