Esto se debe al funcionamiento de la cadena de herramientas FPGA. Hay varios pasos principales: síntesis, mapeado, colocación y enrutamiento. La síntesis es la única que se parece a la compilación. La síntesis es también el único paso que es más fácil de paralelizar (cada módulo se puede sintetizar independientemente de los otros módulos) y como resultado suele ser sólo una pequeña parte del tiempo total que se tarda en ejecutar las herramientas. En cierto modo, se puede comparar el mapeado, la colocación y el enrutamiento con el enlace, ya que estas tareas funcionan en el diseño completo. Sin embargo, el enlazado es básicamente una operación trivial que consiste principalmente en leer todo el código objeto del compilador, corregir algunas direcciones y escribir el archivo ejecutable. Cada vez que vuelvas a ejecutar tus herramientas de software, puede que sólo haya que recompilar unos pocos archivos, pero habrá que volver a enlazar todo el archivo de salida. Pero esto es rápido porque el enlazador no está haciendo nada especialmente complicado.
Por otro lado, el mapeo, la colocación y el enrutamiento requieren una gran cantidad de recursos informáticos, no se pueden paralelizar fácilmente y no es fácil realizarlos de forma incremental. El mapeado toma una lista de redes de "alto nivel" de la síntesis (compuertas AND, compuertas OR, muxes, flip-flops, sumadores, etc.) y la convierte en primitivos de dispositivo (LUTs, flip-flops, carry-chains, etc.). A continuación, se decide dónde colocar cada primitiva en el dispositivo y se calcula el encaminamiento de todas las conexiones a través de la red de interconexión. Y todo ello en función de la temporización: las herramientas intentan asignar, colocar y encaminar toda la lógica de forma que se cumplan todas las restricciones de temporización. Es un problema mucho más complejo que convertir un montón de C en un montón de ensamblador.
Hacer esto de forma incremental significa realizar un seguimiento de lo que su cambio en el nivel HDL resulta en el diseño final enrutado. Esto no es trivial y es imposible hacerlo bien. Básicamente, las herramientas tienen que comparar el antiguo netlist sintetizado con el nuevo, propagar los cambios hacia abajo y esperar que las cosas funcionen al final y se puedan cumplir las restricciones de temporización.
Tengo alguna experiencia personal con construcciones incrementales que van mal. Recientemente, tuve que borrar y volver a crear un proyecto Intel FPGA cuando se negó a volver a colocar un registro en particular después de cambiar algunas restricciones de temporización, ya que la construcción incremental pensó que, dado que la lógica que generó ese registro no cambió, el registro no tenía que ser movido. Esto fue después de perder varias horas probando varias combinaciones de directivas oscuras para tratar de conseguir que las herramientas cooperaran antes de darme cuenta de cuál era realmente el problema.