Verilog: Comparación después de la asignación sin bloqueo

3

He visto el código de Verilog que se parece a lo siguiente:

...

reg [9:0] count;

always @ (posedge clk)

   count <= count + 1
   if (count == 10'b1000) begin
      ...
   end

   ...

end

Me pregunto cómo se comporta esto realmente; ¿la comparación usará el valor nuevo o el valor antiguo de count ?

Me han dicho que todas las asignaciones no bloqueantes ocurren en paralelo, por lo que si hubiera una línea x <= count más abajo en el mismo bloque always , esto usaría el antiguo valor de conteo, que es Por eso me parece ambiguo qué valor utilizará la comparación.

    
pregunta p0llard

3 respuestas

3

Si usted es principalmente un ingeniero de software, puede pensar que Verilog utiliza copias internas de las variables asignadas dentro del bloque siempre. En términos de implementación, las "variables internas" no están realmente ahí , pero nunca es la mejor manera de visualizar cómo funciona.

Considere el siguiente código:

wire a, b;
always @ (posedge clk) begin
    a = a + 1;
    if (a) ...
end
always @ (posedge clk) begin
    b <= b + 1;
    if (b) ...
end

Esto se realiza efectivamente como:

wire a, b;
always @ (posedge clk) begin
    var a_int = a;
    a_int = a_int + 1;
    if (a_int) ...
    a = a_int;
end
always @ (posedge clk) begin
    var b_int = b;
    b_int = b + 1;
    if (b) ...
    b = b_int;
end

Observe cómo las instrucciones de no bloqueo provocan que se realicen cálculos en la variable externa (global si lo desea). Sin embargo, las instrucciones de bloqueo hacen que los cálculos se realicen utilizando la variable interna (local).

Al final del bloque siempre, el valor resultante de la variable interna se asigna de nuevo a la externa.

En su caso, está utilizando asignaciones no bloqueadas para el recuento, por lo que sus cálculos utilizarán la variable externa, que contendrá el valor "antiguo", y no el valor incrementado "nuevo".

A medida que te familiarizas, comienzas a pensar en términos de hardware como describe @Oldfart.

Nota al margen: esta es la razón por la que es una mala idea combinar el bloqueo y el no bloqueo. Terminas calculando una combinación impredecible de valores internos y externos, lo que puede dar como resultado resultados de simulación frente a síntesis muy diferentes.

    
respondido por el Tom Carpenter
3

Utilizará el valor actual del recuento.

En cuanto a 'encontrarlo ambiguo' es solo una cuestión de percepción. Los programadores de HDL tienen una visión diferente del mundo.

Intenta pensarlo de esta manera:

Tenemos un conteo de señales. El conteo es un conjunto de cables.

  • Tienes una pieza de hardware (Llamémosla HwA) usando la cuenta.
  • Tiene una segunda cuenta de cambio de hardware (HwB).

El hardware que cambia el 'conteo' funciona en paralelo con lo que esté usando el conteo.

No importa donde coloque HwA, antes, después o junto a HwB, siempre usa los cables de conteo, lo que sea que esté en esos cables en este momento .

    
respondido por el Oldfart
0

El valor de "conteo" no se actualizará hasta que se haya evaluado cada instrucción en el bloque ... por lo tanto, evaluará el valor anterior. Imagine el contador real ... la salida no se actualiza inmediatamente en el borde del reloj, sino un tiempo finito más tarde, preservando la causalidad. Con la instrucción if dentro del bloque siempre, implica que la salida de la comparación también se registra, por lo que la simulación refleja con precisión esta configuración. Si pretende que la comparación se realice de forma asíncrona, sáquelo de ese bloque.

    
respondido por el Cristobol Polychronopolis

Lea otras preguntas en las etiquetas