haskell - Varias asignaciones al mismo registro en un bloque de RTL con Kansas Lava
vhdl (1)
El problema es que está utilizando múltiples instrucciones sin bloqueo para asignar la señal.
sig_2_o0 <= ''0'';
sig_2_o0 <= ''1'';
Esto se traduce a:
at next event assign ''0'' to sig_2_o0.
at next event assign ''1'' to sig_2_o0.
Esto es diferente a usar asignaciones de bloqueo :
sig_2_o0 := ''0'';
sig_2_o0 := ''1'';
Lo que se traduciría en:
assign ''0'' to sig_2_o0.
assign ''1'' to sig_2_o0.
Bloquear asignaciones
Cuando usa asignaciones de bloqueo, el valor está claramente definido. Primero se configurará a ''0'', luego lo anulará con ''1''. En este ejemplo, no debería haber ningún efecto desde la primera asignación de bloqueo para simulación o hardware sintetizado. Puedes pensarlo ya que hay un retraso de 0 entre la primera asignación y la segunda. Esto significa que tiene un pulso de 0 de ancho, que en realidad no es nada. Es equivalente a tener solo la última asignación, y la primera se omite por completo. Una advertencia es que si pones un retraso en las asignaciones, por ejemplo, "después de 1 ns", entonces notarás la primera asignación seguida de la segunda en simulación. En el hardware, las demoras se ignoran y, por lo tanto, no se producirán cambios por la adición de demoras. De hecho, la inserción de retrasos en RTL que se pretende sintetizar se desaconseja por esta razón. Es muy deseable que el hardware coincida con la simulación, y agregar demoras puede presentar desajustes.
Asignaciones sin bloqueo
Pero cuando utiliza asignaciones sin bloqueo, el simulador tiene dos asignaciones programadas para el evento de la próxima vez. Establezca la señal a ''1'' y, al mismo tiempo, ajústelo a ''0''. Entonces, ¿qué asignación programada tomará la señal? No hay manera de saber. Puede ser cualquier valor ya que está asignado incorrectamente. Todos los verificadores de pelusas y la herramienta de síntesis en el planeta deberían arrojar un error al encontrar múltiples asignaciones sin bloqueo como esta. Es posible simularlo, pero claramente hay un problema con el RTL.
Tengo problemas para entender el comportamiento de Kansas Lava cuando un bloque RTL
contiene múltiples asignaciones en el mismo registro. Aquí está la versión número 1:
foo :: (Clock c) => Signal clk Bool
foo = runRTL $ do
r <- newReg True
r := low
return $ var r
Esto se comporta como lo esperaba:
*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .
El VHDL
generado es:
architecture str of assignments is
signal sig_2_o0 : std_logic;
begin
sig_2_o0 <= ''0'';
OUTPUT <= sig_2_o0;
end architecture str;
Sin embargo, esperaba que esta otra versión también funcionara:
foo = runRTL $ do
r <- newReg True
r := low
r := high
return $ var r
Pero no es así, y la segunda asignación no se tiene en cuenta:
*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .
La razón por la que estoy confundido es porque reg
y var
se definen en términos de un ciclo de reloj completo, por lo que no es posible hacer cosas imposibles de sintetizar como la rama en función de r
y luego reasignarle un nuevo valor. Entonces, ¿por qué esta segunda forma no funciona?
Tampoco es solo un problema de simulación: el VHDL
generado para la segunda versión muestra claramente que la segunda tarea se descarta en el momento de la generación:
architecture str of assignments2 is
signal sig_2_o0 : std_logic;
begin
sig_2_o0 <= ''0'';
OUTPUT <= sig_2_o0;
end architecture str;
Así que, básicamente, esperaba que la salida fuera más parecida
architecture str of assignments2 is
signal sig_2_o0 : std_logic;
begin
sig_2_o0 <= ''0'';
sig_2_o0 <= ''1'';
OUTPUT <= sig_2_o0;
end architecture str;
pero no estoy seguro de lo que eso / debería significar en VHDL.