Lo que hace que VHDL y verilog sean algo confusos es que fueron diseñados originalmente para describir hardware para simulación y luego reutilizados para describir hardware para síntesis.
Entiendo que con el siguiente código de Verilog
(Ejemplo de código snip usando asignaciones de bloqueo)
Utiliza declaraciones no bloqueantes, todas en paralelo y entiendo que cuando se sintetiza, es básicamente 3 registros en serie y se necesitan 3 ciclos de reloj para que 1'b1 alcance r_Test_3.
Cuidado.
Recuerde que el estado inicial de los registros no está definido. Como resultado, a menos que haya especificado el estado inicial de los registros *, es muy probable que su sintetizador optimice esto para que todas sus señales tengan un valor constante de 1.
Por ahora, simulamos que estableciste el estado inicial de los registros en cero y simplemente no lo has incluido en tu ejemplo. En ese caso, como usted dice, habrá tres registros establecidos uno tras otro en los tres primeros bordes del reloj.
Pero que hay de esto,
(Ejemplo de código snip usando asignaciones de bloqueo)
Esto usa instrucciones de bloqueo y, por lo tanto, todo este código se debe realizar en serie. ¿Cómo exactamente se sintetizará esto? Quiero decir, ¿será exactamente igual? Estoy confundido.
Como dice el fotón, ese código es equivalente a.
always @(posedge i_clock)
begin
r_Test_1 = 1'b1;
r_Test_2 = 1'b1;
r_Test_3 = 1'b1;
end
Pero nada de eso realmente responde a tu pregunta real que se reduce a.
¿Cómo se sintetizan los bloqueos en los bloques secuenciales siempre sintetizados?
Cómo se comporta una instrucción de bloqueo en un bloque secuencial y, por lo tanto, cómo se sintetiza depende de dónde la lea. Hay tres casos.
- El mismo bloque siempre, leer después de escribir.
- El mismo bloque siempre, leer antes de escribir (o sin escribir en esta invocación del bloque).
- Bloque siempre diferente.
En el primer caso, no hay necesidad de un registro (aunque uno puede generarse inicialmente y luego eliminarse por tener un fanout cero). La señal solo se alimenta de manera combinatoria.
En el segundo caso, el valor debe almacenarse de un ciclo de reloj al siguiente, por lo que es necesario un registro.
Tenga en cuenta que en algunos casos el control de flujo puede significar que una lectura es a veces después de una escritura y otras no, en ese caso la herramienta de síntesis deberá generar un mux para leer desde el registro o directamente desde la lógica, según corresponda. al igual que necesita generar muxes cuando se escribe un valor en varias rutas diferentes.
En el tercer caso, el comportamiento no está bien definido. En la simulación, los resultados dependerán del orden en que se evalúen los bloques siempre. En síntesis, la herramienta probablemente emitirá una advertencia y hará algo, pero lo que haga puede que no sea lo que quería.
Por lo tanto, debe evitar el tercer caso. Si usa las asignaciones de bloqueo en bloques siempre secuenciales, debería solo leer los resultados de esas asignaciones desde el mismo bloque siempre. Las señales que pasan entre diferentes bloques siempre (o que salen al mundo exterior) siempre deben usar asignaciones sin bloqueo.
* Desafortunadamente, la capacidad de especificar el estado inicial de los registros es algo que varía entre las herramientas (y las versiones de las herramientas), algunos permiten el uso de bloques "iniciales" para este propósito, algunos requieren técnicas específicas de las herramientas, otros no Apóyalo en todo.