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.
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.
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.
initial
los 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 initial
los 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 <= ~clock
ejemplo, 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 x
estado (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 x
el 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.
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 initial
que sea sintetizable: un mecanismo de reinicio explícito. Proporcione a su módulo una reset
entrada 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 X
resultados 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.
tom carpintero
Meenie Leis