Uso de "inicial" en la descripción del módulo Verilog

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?

Pregunto esto 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 dar 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 la FPGA pero no en la simulación?

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

Gracias de antemano.

He etiquetado la pregunta con FPGA ya que parece estar hablando de FPGA. Siéntase libre de retroceder si está preguntando sobre Verilog en general (por ejemplo, incluidos los ASIC)
no preguntas tontas en absoluto

Respuestas (4)

1/ ¿Es una mala práctica?

Está perfectamente bien y, a menudo, se realiza en bancos de prueba. Pero supongo que no es eso a lo que te referías. 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 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 se inicie. 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: úselo solo si realmente sabe lo que está haciendo.

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

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

  • Los FPGA a menudo establecen todos los registros internos en cero. En ese caso, funciona si su estado inicial también es cero.
  • Algunas 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 al inicio. Si, por ejemplo, restablece su lógica, es posible que ya no esté en el estado que usó cuando inició su simulación por primera vez. Por lo tanto, su código podría o no funcionar.

Si "inicial" no se puede sintetizar, ¿por qué Xilinx ISE no me da errores? Sintetiza perfectamente el código.
Es un error común pensar que initiallos bloques no se pueden sintetizar. De hecho, al menos para los FPGA, pueden : es bastante común usar bloques iniciales para establecer el valor de encendido de estructuras como RAM, ROM y registros.
reg [1:0] div_4 = 2'b00;es una construcción idénticareg [1:0] div_4; initial begin div_4 = 2'b00; end a la de establecer el valor de encendido inicial de un registro.

Es un error común pensar que initiallos bloques nunca se pueden sintetizar.

De hecho, para los FPGA, en la mayoría de los casos se pueden sintetizar. 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.

Esta 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 usar una señal de reinicio para controlar el valor del registro. Esto se debe a que le brinda la opción de poner el registro en un estado conocido en cualquier momento. Si solo reinicia un grupo parcial de registros en un circuito, puede terminar con estados extraños existentes.

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


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

El xestado (desconocido) es el 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, termina con otro valor desconocido. Como tal, su simulación terminará mostrando siempre xel valor, porque nunca sabe por dónde empezar.

En el código de síntesis, esto no detendrá su ejecución (*): será un 1 o un 0, y la FPGA simplemente calculará la salida según el valor que sea.


(*) El problema radica en realidad en el hecho de que no sabes cómo comenzará. 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 inicialice en un nivel bajo para indicar que el bus de datos no es válido, entonces no importa en qué valor comience el bus de datos. bajo es peligroso.

Es un error común pensar que los bloques iniciales no se pueden sintetizar. No estoy de acuerdo con eso. Solo se puede usar en FPGA, no en CPLD, no en ASIC. (He corregido mi respuesta anterior.)
@oldfart Estoy de acuerdo en que no en todos los casos, pero no pretendo eso. Decir que no se pueden sintetizar es un error, porque en algunos casos se puede. Consulte Si y solo si .
Capenter: Lo descarto como diferencia en el uso del idioma. Especialmente con muchas personas que no hablan inglés, trato de usar frases simples, pero siempre hago que mi idioma sea 'seguro'. Así que estoy de acuerdo con su comentario de que mi uso de 'incorrecto' fue incorrecto y lo corregí. Al mismo tiempo, encuentro que una frase como la que usa para comenzar la respuesta anterior es extremadamente peligrosa, ya que la mayoría de los lectores no la leerán como "si y solo si", sino más bien como "Él está bien", mientras que fácilmente puede conducir a desajustes de simulación . También puede deberse a que muchos años en el diseño de ASIC me vuelven paranoico por los desajustes de simulación.

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 según el dispositivo de destino. Sintetícelo para un FPGA basado en RAM (típ. Altera, Xilinx) y su diseño funcionará porque se reconocerán los valores iniciales.

Sintetícelo para un FPGA basado en Flash (típ. Microsemi), un CPLD (típ. 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...

Utilice un reinicio. Los FPGA basados ​​en RAM proporcionan restablecimientos asíncronos (o, con menos frecuencia, 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.

Cada dispositivo de destino ahora necesita proporcionar un reinicio para sí mismo.

Esto podría generarse externamente, luego pasar a través de una etapa de entrada simple para hacer un restablecimiento asincrónicamente afirmado, sincrónicamente negado, que evita la metaestabilidad en los DFF en la 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 a '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 reinicio para todos los DFF como lo haría un reinicio externo y (b) esta es la única parte que cambia si se usa un dispositivo diferente. apuntado Todos los demás Verilog/VHDL permanecen completamente sin cambios en un redireccionamiento de dispositivo.

La conclusión...

Los valores iniciales tienen trampas 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 es así. Porque, a menos que trabajen completamente solos, no pagan el desarrollo ni cargan con los costos de las consecuencias.

Si está diseñando profesionalmente, entonces debería entregar los diseños sin 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 años o diez años, en diferentes dispositivos. Los propietarios del diseño (su empleador o cliente) esperarán que otros ingenieros puedan reutilizar sus diseños por los que pagaron, en diferentes productos con diferentes dispositivos de destino.

Me temo que el hecho de que su diseño se haya sintetizado y funcionado aquí no es prueba de nada. En ingeniería, es muy fácil hacer diseños que funcionen. (Piense en ese tipo cuyos estantes apenas cuelgan con un clavo pero siguen ahí). Nuestro objetivo es hacer diseños que nunca dejen de funcionar. En el diseño de circuitos digitales, esta es una forma de hacerlo 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 las direcciones IP que encontrará, especialmente las direcciones IP de los proveedores de PLD, utilizan restablecimientos por las mismas razones.

En resumen: no use valores iniciales. Mantenga sus diseños portátiles. Manténgase móvil a través de los trabajos y la industria. Disminuya la búsqueda de fallas de todos.

Hay una manera fácil de evitar initialque sea sintetizable: un mecanismo de reinicio explícito. Proporcione a su módulo una resetentrada y un requisito para que se afirme durante y durante algunos ciclos después del inicio para que el módulo entre en un estado sensato.

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