Inicializar la variable utilizada en el bloque always_ff

2

Tengo un montón de código de Verilog (del sistema) que usa sentencias de inicialización. Este es el código para un FPGA de Altera. Pruebo el código usando bancos de pruebas automatizados en la versión de modelsim que se envía con quartus, y todo funciona bien. Sin embargo, he estado tratando de mover algunos de nuestros bancos de pruebas al simulador de cadencia, y eso es una queja. Un ejemplo simple de código que falla es el siguiente:

reg [15:0] counter = 0;

always_ff @(posedge clk) begin
    counter = counter + 1'b1;
    display("counter: %4X", counter);
end

Esto da un error en el simulador de cadencia que indica que no está permitido que el contador tenga varios controladores porque se usa en un bloque always_ff.

¿Este error es correcto? Dos herramientas dicen que el código está bien, y una falla. Las reglas que he encontrado para always_ff establecen que "una variable asignada en un always_ff, always_comb, o always_latch no puede ser asignada por ningún otro proceso". Esto tiene sentido, pero parece extraño que el valor inicial se considere un proceso, y en cualquier caso haría que esas características de lenguaje sean incompatibles entre sí.

Entonces, ¿hay una manera correcta de usar inicializadores a lo largo del sistema lateral verilog nuevo estilo siempre procesos * *? ¿Depende este comportamiento de la versión del sistema verilog standard para que pueda decirle a mis herramientas cuál usar? ¿O mis opciones de usar solo líneas de restablecimiento explícito, o atenerse al estilo antiguo siempre bloquean?

    
pregunta Evan

3 respuestas

0

El LRM no es muy claro acerca de los inicializadores como un proceso. Como puede llamar a una función en una inicialización, eso podría considerarse un proceso.

El propósito de la construcción always_ff fue estrictamente para el código de diseño y no para bancos de prueba. Su propósito es declarar la intención de un proceso always_* por adelantado en la simulación para que no haya sorpresas cuando llegue a la síntesis. Sin embargo, las reglas para lo que es sintetizable es un objetivo en movimiento.

Si este código es de hecho para un banco de pruebas, cambiaría los tipos de datos a bit en lugar de reg , entonces el valor predeterminado se convierte en 0 de todos modos. De lo contrario, usaría un bloque simple always .

    
respondido por el dave_59
0

Parece que el código infiere lógica para fpga. En lugar de inicializar el registro durante la declaración, debe usar una señal de reinicio. Eso modela el hardware con mayor precisión.

En fpgas, el POR está implícito, pero aún así debes restablecer la lógica de manera externa o interna. P.ej. Salida bloqueada PLL, etc.

reg [15:0] counter;
reg rst;

always_ff @(posedge clk or posedge rst)        
begin
   if(rst)
     counter <= '0;
   else
     begin
     counter <= counter + 1'b1;
     'ifdef SIM
        display("counter: %4X", counter);
      'endif 
      end
end

Si no desea generar el restablecimiento internamente, los compiladores fpga tienen una configuración predeterminada que establece el estado de encendido de los registros. Puede anular esto a cualquier valor.

    
respondido por el shparekh
0

Veo que Cadence y Synopsys producen un error para este código. También veo que tanto Mentor como Aldec permiten conducir variables inicializadas en bloques always_ff . Esto sugiere que el comportamiento correcto no está correctamente definido en el LRM.

Confiar en los valores de encendido para los diseños de FPGA es perfectamente viable. La guía de codificación recomendada de Altera es usar always @(posedge clock) , por lo que sugeriría que lo haga como una solución. Alternativamente, puedes usar un simulador diferente.

El comportamiento de Cadence podría decirse que tiene sentido para los diseños ASIC, donde no se puede confiar en la inicialización de los registros. Agregar un valor de inicialización para una variable por error podría ocultar errores de reinicio faltantes en la simulación.

    
respondido por el pc3e

Lea otras preguntas en las etiquetas