Pregunta sobre For loop sintetizable y Generate

Estoy usando el lenguaje Verilog y Zedboard como tablero de destino.

Hasta donde yo sé, el bucle for se puede sintetizar y la herramienta de síntesis traduce el bucle for como una secuencia de instrucciones duplicadas, como el bucle que se desenrolla.

Por ejemplo,

for ( i = 0; i < 4; i=i+1) begin
  mem[i] = i;
end

will be translated to 
mem[0] = 0;
mem[1] = 1;
mem[2] = 2;
mem[3] = 3;

Por lo tanto, hasta donde yo sé, el ciclo for se puede usar si el recurso está disponible para inferir las puertas múltiples pero con el mismo propósito.

Sin embargo, parece que generar en Verilog se puede usar para, no solo implicar las instancias múltiples, sino también las instrucciones múltiples al igual que el ciclo for.

Entiendo que generar solo puede implicar las múltiples instancias del módulo y el ciclo for no se puede usar para ese propósito.

Entonces, ¿cuál es la diferencia entre generar + for loop y solo for loop? Sin embargo, creo que ambos funcionan como el bucle que se desenrolla. ¿Hay alguna diferencia notable? Si no hay diferencia, ¿cuál es el estilo de codificación preferible para inducir el desenrollado del bucle?

Solo para mayor claridad, es: yo insinúo, tú infieres. por ejemplo, implica una RAM en Verilog/VHDL, el software de síntesis infiere esa RAM de su Verilog/VHDL. Error muy común, vale la pena aprender.

Respuestas (1)

Los bucles for de Verilog son perfectamente sintetizables bajo ciertas condiciones:

  • Puede usar cualquier declaración de procedimiento dentro de un bucle (por ejemplo, si no).
  • El número de bucles debe estar predeterminado .
    • La expresión limitante debe ser una comparación entre la variable de bucle y una constante o un parámetro.
    • La asignación de pasos debe incrementar el valor del bucle en una cantidad constante.
  • Puede asignar un valor diferente a la misma variable en cada bucle (por ejemplo, calcular un índice a partir de la variable de bucle).
  • Para fines de síntesis, el bucle se evalúa en tiempo cero, es decir, si intentara hacer un contador, solo vería el valor final.

Esas mismas reglas se aplican ya sea que use un bucle for en un bloque de procedimiento o en un bloque de generación.

Cuando se hace en un bloque de procedimiento, initialy alwayspuede usar un bucle for para cambiar elementos en una matriz (exactamente como su ejemplo), o puede cambiar el mismo valor varias veces, por ejemplo:

for (idx = 0; idx < 4; idx=idx+1) begin
    a = a + b[idx];
    c = c + 2;     //You can change more than one variable in a for loop
end

En ese ejemplo, el hardware resultante será una cadena de sumadores, sumando los valores de cuatro índices de matriz.

La clave es que no puede crear nuevas variables o módulos en un ciclo for de procedimiento. Esta regla se aplica a los bloques de procedimiento en general, no solo a los bucles (es decir, no puede declarar una variable en un bloque de procedimiento).

 

Los bloques de generación, por otro lado, permiten la creación de variables y la creación de instancias de módulos. Eso significa que en un bloque de generación, puede usar un ciclo de generación para inferir módulos. Esa es prácticamente la única diferencia.

Para generar bucles for, debe utilizar a genvarcomo variable de bucle (es decir, el valor que utiliza para contar cada bucle). También debe darle un nombre al bucle for:

for (loopVal = 0; loopVal < 4; loopVal = loopVal + 1) begin : loopName

Este nombre se antepone a cualquier pieza de hardware que cree una instancia en el bucle. Entonces, si crea una instancia llamada bob, el bucle anterior crearía instancias:

loopName[0]|bob
loopName[1]|bob
loopName[2]|bob
loopName[3]|bob

Esto da como resultado múltiples instancias con nombres únicos.

 

Tanto los bucles generados como los de procedimiento realizarán el desenrollado del bucle como usted diga. La diferencia es simplemente cómo puedes usarlos. Procedural se puede utilizar en bloques procedimentales (p. ej., para inicializar una memoria). Generate solo se puede usar en bloques de generación.

Ambos son útiles y preferidos. Uno no puede reemplazar al otro.

otra forma de pensar en generar es como una especie de preprocesador, su compilador verilog 'ejecuta' cosas en bloques de generación en el punto donde está instanciando el bloque que contiene las generaciones; no suceden en tiempo de ejecución (a diferencia de los bucles de procedimiento)
Los bucles de procedimiento de @Taniwha tampoco se ejecutan en tiempo de ejecución. Son desenrollados por el compilador. Todo se reduce al hardware al final. Además, no confunda el preprocesador con declaraciones de generación, no son el mismo concepto: Verilog tiene un preprocesador que incluye declaraciones de tipo if-else.
@TomCarpenter Agradezco una gran respuesta. Podría entender todos sus puntos, excepto generar el ciclo. Parece que comienza: se debe agregar algo justo antes del ciclo for, pero no puedo entender cómo funciona en la creación de instancias de módulos. ¿El loopName es una variable o solo una cadena? Y cómo se pueden indexar por [1] a [4].
@JaeHyukLee loopNamees solo texto, como el nombre de una instancia o el nombre de una señal. Puede ser lo que quieras.
@TomCarpenter: depende del compilador: si está compilando puertas, sí, se desenrollan, si está compilando código para simulación, es más probable que no (descargo de responsabilidad, he escrito un compilador Verilog)