Uso de “initial” en la descripción del módulo Verilog

1

Estoy escribiendo un código y tengo 2 preguntas tontas:

1- ¿Es una mala práctica usar "inicial" en la descripción del módulo?

Lo pregunto porque tengo un divisor de frecuencia con 2 señales (clk_in y clk_out). Si quiero ver el comportamiento en la simulación, tengo que darle un valor inicial a clk_out, de lo contrario clk_out siempre se mantendrá como X. Luego, usé "inicial" en lugar de usar una señal de reinicio.

2- ¿Por qué el código sin inicializar la salida funciona bien en el FPGA pero no en la simulación?

Mi código básicamente hace esto: Clk_out < = ~ Clk_out;

Gracias de antemano.

    
pregunta Jose de arimatea

4 respuestas

2

Es un error común que los bloques initial nunca puedan sintetizarse.

De hecho, para los FPGA, pueden en la mayoría de los casos ser sintetizados. De hecho, el uso de bloques iniciales es bastante común. Puede usarlos para establecer el valor de encendido de estructuras como RAM, ROM y registros.

Esto no es una mala práctica en absoluto, y ayuda tanto con la simulación como con el código de síntesis.

Sin embargo, en muchos casos con registros, es mejor utilizar una señal de reinicio para controlar el valor del registro. Esto se debe a que le da la opción de poner el registro en un estado conocido en cualquier momento. Si solo restableces un grupo parcial de registros en un circuito, puedes terminar con estados extraños existentes.

En los circuitos de ejecución libre, como su ejemplo clock <= ~clock , probablemente no sea necesario incluir un restablecimiento, y el uso de un valor inicial ayudará a garantizar que la simulación y el comportamiento de síntesis coincidan.

En términos de por qué su código no funciona en simulación, es porque la simulación en realidad tiene cuatro estados, mientras que la síntesis en realidad solo tiene tres.

El estado x (desconocido) es el valor predeterminado para las señales que no se inicializan en la simulación. Desconocido representa una condición en la que el simulador no sabe cuál es el valor, podría ser un 1, o podría ser un 0.

Si toma un valor desconocido y lo invierte, terminará con otro valor desconocido. Como tal, su simulación terminará mostrando siempre x para el valor, porque nunca sabe dónde comenzar.

En el código de síntesis, esto no impedirá que se ejecute (*): será un 1 o un 0, y el FPGA simplemente calculará la salida en función de lo que sea ese valor.

(*) El problema radica en realidad en el hecho de que no sabes cómo empezará. Esto no es un problema si lo ha simulado para averiguarlo, pero si su simulación falla, puede ser difícil predecir comportamientos.

Hay casos en los que no tener un valor inicial no es un problema, por ejemplo, un bus de datos que tiene una señal válida. Siempre que la señal válida se inicie a bajo para indicar que el bus de datos no es válido, entonces no importa en qué valor se inicie el bus de datos. Sin embargo, para registros como la variable "launchMissile", se deja al azar si eso comienza alto o bajo es peligroso.

    
respondido por el Tom Carpenter
1
  

1 / ¿Es una mala práctica?

Está perfectamente bien y, a menudo, se realiza en bancos de pruebas. Pero supongo que no es a lo que te refieres. Preferiría decir que rara vez se hace. La razón es que no se puede sintetizar para todos los FPGA y definitivamente no para los ASIC. Esto hace que ya no se pueda confiar en su diseño, ya que lo que simula puede no coincidir con la lógica real.

Sin embargo, hay algunos casos excepcionales en los que necesita usar una inicial en su módulo para que el código funcione. Para dar un ejemplo: a continuación hay una división por cuatro que no requiere un reinicio. Es un circuito seguro ya que se utilizan todos los estados posibles, por lo que no importa en qué estado comience. Pero sin "inicial" no se puede simular, ya que no saldrá del estado 2'bxx.

reg [1:0] div_4;
always @(posedge clk)
   div_4 <= {div_4[0],~div_4[1]};

Como he comentado en otras publicaciones de Verilog: úsalo solo si realmente sabes lo que estás haciendo.

  

2 / ¿Por qué el código sin inicializar la salida funciona bien en el FPGA pero no en la simulación?

Puede funcionar en tu FPGA, pero eso no significa que funcionará en general.

  • Los FPGA a menudo establecen todo el registro interno en cero. En ese caso, funciona si su estado inicial también es cero.
  • Algunos FPGA pueden preestablecer los registros cuando se cargan. Por lo tanto, puede "establecer" o "borrar" el estado de registro inicial.

Para ambos funciona solo una vez en el inicio. Si, por ejemplo, restablece su lógica, es posible que ya no se encuentre en el estado que usó cuando inició la simulación por primera vez. Por lo tanto, su código podría o no funcionar.

    
respondido por el Oldfart
0

De hecho, puede usar valores iniciales en Verilog o VHDL, pero reducen la portabilidad de su diseño. Por lo tanto, deben evitarse y no se recomiendan.

Las razones ...

Su diseño se comportará de manera diferente dependiendo del dispositivo de destino. Sintetízalo para un FPGA basado en RAM (typ. Altera, Xilinx) y tu diseño funcionará porque los valores iniciales serán reconocidos.

Sintetícelo para un FPGA basado en Flash (typ. Microsemi), un CPLD (typ. Altera, Lattice) o un ASIC y su diseño no funcionará porque los valores iniciales no tienen sentido. La causa no será evidente de inmediato, especialmente si no es su propio diseño, por lo que hay tiempo y costo de ingeniería para descubrirlo y volver a trabajarlo.

La alternativa ...

Usa un reinicio. Los FPGA basados en RAM proporcionan restablecimientos asíncronos (o, menos comúnmente, síncronos) en sus DFF, por lo que le cuesta enrutamiento pero no recursos. El diseño ahora es portátil en todos los CPLD, FPGA y ASIC.

Ahora, cada dispositivo de destino debe proporcionar un restablecimiento por sí mismo.

Esto podría generarse externamente y luego pasar a través de una etapa de entrada simple para hacer un restablecimiento asíncrono, negado sincrónicamente, que evita la metastabilidad en DFFs en negación.

O puede generarse internamente en un dispositivo basado en RAM, usando un registro de desplazamiento simple de n bits (yo uso 4 bits) con un valor inicial de '0' y cambiando en un '1'. Se puede usar un valor inicial aquí en este registro de desplazamiento, y solo aquí, porque (a) da como resultado la misma señal de restablecimiento a todos los DFF que haría un restablecimiento externo y (b) esta es la única parte que debe cambiar si un dispositivo diferente es apuntado Todos los demás Verilog / VHDL permanecen completamente sin cambios en un nuevo destino del dispositivo.

La conclusión ...

Los valores iniciales tienen dificultades y pueden causar problemas invisibles. Un reinicio no lo hace y no lo hará.

Podría decir que depende del diseñador profesional su elección ... pero no lo es. Porque, a menos que trabajen completamente solos, no pagan por el desarrollo ni soportan los costos de las consecuencias.

Si está diseñando profesionalmente, debería entregar los diseños más libres de problemas a su empleador o cliente, y eso incluye la portabilidad. También está haciendo más difícil reutilizar sus propios diseños si trabaja en otro lugar en un año, cinco o diez años, en diferentes dispositivos. Los propietarios del diseño (su empleador o cliente) esperarán que otros ingenieros puedan reutilizar los diseños que pagaron, en diferentes productos con diferentes dispositivos de destino.

El hecho de que su diseño sintetizado y trabajado aquí no prueba nada, me temo. En ingeniería, es muy fácil hacer diseños que funcionen. (Piense en ese tipo cuyos estantes apenas cuelgan con un solo clavo pero todavía están allí). Nuestro objetivo es hacer diseños que nunca funcionen. En el diseño de circuitos digitales, esta es una forma de hacer eso mucho más probable.

Muchos clientes para los que he trabajado simplemente prohíben los valores iniciales en sus estándares de codificación por todas estas razones. La mayoría de IP que encontrará, especialmente la IP del proveedor PLD, usa restablecimientos por las mismas razones.

En resumen: no utilice valores iniciales. Mantenga sus diseños portátiles. Manténgase móvil a través de empleos y la industria. Reducir la búsqueda de fallos de todos.

    
respondido por el TonyM
0

Hay una manera fácil de evitar initial que se puede sintetizar: un mecanismo de reinicio explícito. Proporcione a su módulo una entrada reset y un requisito para que se confirme durante y durante unos pocos ciclos después del inicio para que el módulo se encuentre en un estado sano.

Este requisito se puede cumplir fácilmente desde un banco de pruebas, también puede verificar que no hay X de salidas generadas por el diseño completo (no nos importa mucho internamente), y obtiene un diseño que puede usarse con un proceso de síntesis que no permite valores iniciales, o en un contexto que requiere un mecanismo de apagado para su módulo.

    
respondido por el Simon Richter

Lea otras preguntas en las etiquetas