2012-09-20 17 views
11

Estoy tratando de obtener un módulo para pasar la verificación de sintaxis en ISE 12.4, y me da un error que no entiendo. En primer lugar un fragmento de código:Verilog generate/genvar en un bloque siempre

parameter ROWBITS = 4; 

reg [ROWBITS-1:0] temp; 

genvar c; 
generate 
    always @(posedge sysclk) begin 
     for (c = 0; c < ROWBITS; c = c + 1) begin: test 
      temp[c] <= 1'b0; 
     end 
    end 
endgenerate 

Cuando intento una comprobación de sintaxis, me sale el siguiente mensaje de error:

ERROR:HDLCompiler:731 - "test.v" Line 46: Procedural assignment to a non-register <c> is not permitted.

Realmente no entiendo por qué se queja. "c" no es un cable, es un genvar. Este debería ser el equivalente de la sintaxis completamente legal:

reg [3:0] temp; 

always @(posedge sysclk) begin 
    temp[0] <= 1'b0; 
    temp[1] <= 1'b0; 
    temp[2] <= 1'b0; 
    temp[3] <= 1'b0; 
end 

Por favor, no hay comentarios acerca de cómo sería más fácil que escribir esto sin generar. Este es un ejemplo reducido de una pieza de código mucho más compleja que implica múltiples ifs y asignaciones no bloqueantes a "temp". Además, no me digas que hay versiones más nuevas de ISE, ya lo sé. OTOH, si sabe está arreglado en una versión posterior de ISE, por favor dígame qué versión sabe que funciona.

Respuesta

15

de tener que anular el nido en el interior del bloque de generar:

genvar c; 
generate 
    for (c = 0; c < ROWBITS; c = c + 1) begin: test 
     always @(posedge sysclk) begin 
      temp[c] <= 1'b0; 
     end 
    end 
endgenerate 

Técnicamente, esto genera cuatro siempre bloquea:

always @(posedge sysclk) temp[0] <= 1'b0; 
always @(posedge sysclk) temp[1] <= 1'b0; 
always @(posedge sysclk) temp[2] <= 1'b0; 
always @(posedge sysclk) temp[3] <= 1'b0; 

En este sencillo ejemplo, no hay ninguna diferencia de comportamiento entre los cuatro siempre bloquea y un solo bloque siempre contiene cuatro asignaciones, pero en otros casos podría haber.

La operación dependiente del genvar debe resolverse al construir la representación en memoria del diseño (en el caso de un simulador) o al mapear puertas lógicas (en el caso de una herramienta de síntesis). El always @posedge no tiene sentido hasta que el diseño esté en funcionamiento.

Sujeto a ciertas restricciones, puede poner un bucle for dentro del bloque always, incluso para código sintetizable. Para la síntesis, el ciclo se desenrollará. Sin embargo, en ese caso, el bucle for debe funcionar con reg, integer o similar. No puede usar un genvar, porque tener el bucle for dentro del bloque always describe una operación que ocurre en cada extremo del reloj, no una operación que se puede expandir estáticamente durante la elaboración del diseño.

+0

Gracias por la rápida respuesta. Temía que fuera algo como esto. Parte del problema es que quiero generar una secuencia de sentencias if o selectores de casos con el ciclo for, que no se puede hacer en bloques siempre separados. – user1684538

+0

¿Hay alguna manera de generar todo el código en un solo bloque siempre, o genvar simplemente no es capaz de hacer eso? – user2569332

2

Dentro de un módulo, Verilog contiene esencialmente dos construcciones: elementos y declaraciones. Las declaraciones siempre se encuentran en contextos de procedimientos, que incluyen cualquier cosa entre begin..end, funciones, tareas, siempre bloques y bloques iniciales. Los elementos, como generar construcciones, se enumeran directamente en el módulo. Para bucles y la mayoría de las declaraciones variables/constantes pueden existir en ambos contextos.

En su código, parece que desea que el bucle for se evalúe como un elemento de generación pero el bucle es realmente parte del contexto de procedimiento del bloque always. Para que un bucle for sea tratado como un bucle de generación, debe estar en el contexto del módulo. Las palabras clave generate..endgenerate son completamente opcionales (algunas herramientas lo requieren) y no tienen ningún efecto. Consulte this answer para ver un ejemplo de cómo se evalúan los bucles de generación.

//Compiler sees this 
parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
genvar c; 

    always @(posedge sysclk) //Procedural context starts here 
    begin 
     for (c = 0; c < ROWBITS; c = c + 1) begin: test 
      temp[c] <= 1'b0; //Still a genvar 
     end 
    end 
2

Si no le molesta tener que compilar/generar el archivo, puede utilizar una técnica de preprocesamiento. Esto le da el poder de generar pero da como resultado un archivo Verilog limpio que a menudo es más fácil de depurar y lleva a menos problemas con el simulador.

Utilizo RubyIt para generar archivos verilog a partir de plantillas que usan ERB (Ruby incrustado).

parameter ROWBITS = <%= ROWBITS %> ; 
always @(posedge sysclk) begin 
    <% (0...ROWBITS).each do |addr| -%> 
    temp[<%= addr %>] <= 1'b0; 
    <% end -%> 
end 

Generación del archivo module_name.v con:

$ ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv 

El generada module_name.v

parameter ROWBITS = 4 ; 
always @(posedge sysclk) begin 
    temp[0] <= 1'b0; 
    temp[1] <= 1'b0; 
    temp[2] <= 1'b0; 
    temp[3] <= 1'b0; 
end 
4

que no es necesario un bock generar si desea que todos los bits de temp asignado en el mismo bloque siempre.

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
    for (integer c=0; c<ROWBITS; c=c+1) begin: test 
     temp[c] <= 1'b0; 
    end 
end 

Alternativamente, si el simulador compatible con IEEE 1800 (SytemVerilog), entonces

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
     temp <= '0; // fill with 0 
    end 
end 
0

para Verilog acaba de hacer

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
    temp <= {ROWBITS{1'b0}}; // fill with 0 
end 
Cuestiones relacionadas