VHDL: ¿Se supone que las sentencias if-else y case sintetizan el mismo hardware?

Las sentencias if-else y case son equivalentes. Lo último puede ser más fácil de leer cuando tenemos muchas posibilidades comprobadas.

Se supone que un condicional infiere mux en hardware. Sin embargo, hay una diferencia entre tener una cadena de mux de 2 a 1 y una gran mux de n a 1 que hace lo mismo en términos de retardo de propagación.

¿Se supone que la instrucción if-else y la instrucción case infieren el mismo hardware? ¿O hay alguna diferencia en cómo se sintetizarían?

sí... hay un "error" en la síntesis APA tal que un gran if/elseif/... producirá una red Y en cascada masiva para lograr esto, comiendo LUT y aumentando el retraso de propagación. ¿Por qué no usar una declaración de caso si tiene muchas posibilidades para verificar?
Simplemente mire debajo de la " vista RTL " después de haber sintetizado. Le mostrará cómo el compilador lo armó.
Al contrario de lo que puede leer a continuación, un proveedor de síntesis puede hacer cualquier cosa que se ajuste a la semántica de simulación del lenguaje; su salida será entonces, por definición, correcta, punto. Habiendo dicho eso, cuando enseñé estas cosas les dije a los estudiantes que esperaran un mux en un caso y un codificador/cadena de prioridad en el otro.

Respuestas (2)

No: if-else es secuencial; caso es concurrente. Un simple si seguido de otro equivaldrá a un multiplexor de dos entradas. Un if seguido de un if else es equivalente a una serie de dos multiplexores de entrada como este: muxEsto se debe a que el orden en que verifica las condiciones del if-else es importante, es decir, tiene prioridad.

Una declaración de caso, por otro lado, es concurrente. Todo sucede al mismo tiempo.

Solo agregaría una nota de que los multiplexores en sí mismos no son realmente una cosa en un FPGA, las LUT sí lo son, por lo que un multiplexor de representación esquemática no es particularmente diagnóstico de lo que realmente se hará en términos de utilización del espacio en el tejido FPGA. Los FPGA modernos a menudo tienen 6 LUT de entrada, por lo que lo anterior, de hecho, colapsará a dos LUT con toda probabilidad.
@DanMills Estoy de acuerdo en general. Sin embargo, los FPGA modernos pueden tener tan solo 4 entradas en sus LUT, por ejemplo, MAX 10, Cyclone V. Además, es una buena práctica escribir código escalable. Cada estándar de código que he visto requiere que use casos en los que no se requiere prioridad. Simplemente no hay necesidad de usar if-else en la mayoría de los casos. También debe considerar qué sucede cuando cambia el hardware o opta por una implementación de ASIC.
El caso no es una declaración concurrente... La versión concurrente del caso es una "declaración" with/select. El nombre real es la asignación de señal seleccionada. Es un caso especial que las sentencias if/elsif/else y case se deduzcan como multiplexores. Solo es cierto si se asigna la misma salida en las ramas o en las opciones de una declaración de caso. La diferencia entre if y case es que if puede crear una lógica de prioridad, mientras que las opciones en un caso tienen el mismo peso.

Ninguna declaración necesariamente se asigna a un multiplexor.

El código HDL se compila en una forma intermedia, que se optimiza simplificando declaraciones (por ejemplo, eliminando tautologías) y encontrando una asignación óptima al hardware real que también tiene en cuenta los retrasos de propagación.

Por ejemplo

if(input)
then
    output <= '1';
end if;

probablemente será optimizado output <= '1';por el compilador, porque el estado inicial no está definido y un valor fijo utiliza la menor cantidad de recursos. Place&Route luego lleva esto más allá y configura el controlador de salida para el valor fijo, por lo que no se usa ni un solo registro.

Los retrasos de propagación deben tenerse en cuenta en su diseño donde las interfaces esperan que los datos lleguen en un borde de reloj particular, por lo que ya debería haber sido parte de la especificación de la interfaz.

Por ejemplo, cuando construyo un filtro FIR, también genero una validseñal que se establece cuando se alcanza el estado estable después de un reinicio, y una markerseñal que es simplemente un retraso en los marcadores de entrada. La implementación obvia generavalid norte t a pag s después del reinicio, y el retraso del marcador es norte t a pag s 2 , pero eso no está garantizado en la interfaz. Si puedo obtener un mejor comportamiento de canalización agregando más etapas de registro en el medio, puedo hacerlo sin romper ningún componente conectado, y la lógica casi siempre se optimiza cuando el compilador determina que el retraso total se corrige en el momento de la compilación.

Dado su ejemplo y ninguna asignación adicional outputdará como resultado un bloqueo ... Las descripciones de asignación incompletas darán como resultado elementos de memoria.
@Paebbels Solo es cierto en un contexto combinacional. Es solo un fragmento de código, no tiene sentido ser quisquilloso.
@Paebbels, sí, si no ejecuta el optimizador sobre el diseño. El optimizador verá que hay un pestillo con un estado que es '1'o 'U', lo simplifica a '1', propaga el valor fijo a través del búfer de salida y elimina el pestillo, la tabla que tiene delante y la interconexión al búfer de salida.
Esto no es correcto. Al principio no hay ningún Uvalor en sintetizar. Sólo 0, y . 1_ En segundo lugar, supongamos que su código incompleto es parte de un proceso combinacional, luego la salida se infiere a un pestillo. Supongamos además que la salida no se inicializó ( ) o se inicializó a , luego su pestillo solo cambia un estado cuando la entrada sube. El único caso en el que synthese puede optimizar la salida a una constante es si la salida se inicializó en . Eso es muy poco probable.... . Z-U01
¡Incluso cuando coloca su código en un proceso cronometrado, los sintetizadores inferirán el mismo comportamiento pero usarán un flip flop en lugar de un pestillo! Si no me cree, escriba un código de ejemplo para cualquier herramienta de síntesis y envíelo a mi dirección de correo electrónico. Presentaré este comportamiento como un error para ti :).
@jalalipop Sucede en procesos cronometrados. La diferencia es que obtienes un flip flop pero nunca un multiplexor.
@Paebbels, estoy de acuerdo en que se generaría un pestillo, pero el optimizador lo eliminará nuevamente porque el único valor definido que puede tomar la salida es '1'. Mi punto es que el optimizador hará cambios más grandes que la diferencia entre ify casepodría ser.
No, no se puede eliminar/optimizar en FPGA (estamos discutiendo una pregunta de FPGA basada en el etiquetado de esta pregunta). Este es un pestillo con valor inicial 0que necesita un evento activo alto en input. Si el evento nunca se proporciona, outputpuede bajarse del escenario para siempre. Por lo general, dicho pestillo (o más probablemente flip flop) se usa para registrar las condiciones de inicio.
@Paebbels, las señales no tienen valores predeterminados en síntesis. Es por eso que necesita una señal de reinicio explícita.
No, eso de nuevo no es correcto. Lea la Norma IEEE. 1076.6-2004 (comúnmente conocido como estándar de síntesis VHDL). Describe cómo los valores predeterminados de las señales se traducen en valores iniciales de registros o latches. El estándar fue retirado por IEEE, pero Altera/Intel, Synopsys y Xilinx se adhieren a esa parte del estándar. Divulgación completa: soy uno de los vicepresidentes del P1076 VSAG :).
@Paebbels Cierto, supongo que su punto general fue que la forma en que se escribe el código no se optimizaría como dijo Simon, lo que tiene sentido para mí.
@Paebbels, probado en Quartus Prime 16.1, compilando para EP4CE22E22C8 con este código de prueba: el visor RTL muestra 'output'estar conectado a 1h. Esto sigue siendo cierto incluso si extiendo esto con una señal local que se inicializa en '0'.
@Paebbels, logré crear un pestillo al hacer que el proceso fuera sensible a input: en este caso, iftodavía está optimizado y la entrada D del flip flop está conectada 1, pero ahora la entrada está conectada a la entrada de reloj del FF.
No puedo reproducir sus resultados en Quartus Prime 17.0. RTL Viewer y Technology Map Viewer muestran el comportamiento descrito por mí. Probé flip flops y pestillos, así como no init value, init to 0e init to 1. Si outputse inicializa en 1entonces, la optimización elimina el elemento de memoria como se esperaba. Estoy muy seguro de que utilicé esta función años atrás en Quartus II 13.0.