2012-09-20 14 views
11

Sto cercando di ottenere un modulo per passare il controllo della sintassi in ISE 12.4 e mi dà un errore che non capisco. Prima un frammento di codice:Verilog generate/genvar in un blocco sempre

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 

Quando provo un controllo della sintassi, ricevo il seguente messaggio di errore:

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

Io davvero non capisco il motivo per cui si lamenta. "c" non è un filo, è un genvar. Questo dovrebbe essere l'equivalente della sintassi completamente legale:

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 

Per favore, niente commenti su come sarebbe più facile scrivere questo senza l'generare. Questo è un esempio ridotto di una parte di codice molto più complessa che coinvolge più incarichi if e non bloccanti in "temp". Inoltre, non dirmi solo che ci sono versioni più recenti di ISE, lo so già. OTOH, se tu sai è stato corretto in una versione successiva di ISE, per favore fammi sapere quale versione sai funzionare.

risposta

15

è necessario invertire la nidificazione all'interno del blocco generare:

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

Tecnicamente, questo genera quattro sempre blocchi:

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; 

In questo semplice esempio, non c'è alcuna differenza di comportamento tra i quattro blocca sempre e un solo blocco sempre contenente quattro assegnazioni, ma in altri casi potrebbe esserci.

L'operazione dipendente da genvar deve essere risolta quando si costruisce la rappresentazione in memoria del progetto (nel caso di un simulatore) o quando si esegue il mapping su porte logiche (nel caso di uno strumento di sintesi). Lo always @posedge non ha alcun significato fino a quando il progetto non sta funzionando.

Soggetto a determinate restrizioni, è possibile inserire un ciclo for all'interno del blocco sempre, anche per codice sintetizzabile. Per sintesi, il ciclo verrà srotolato. Tuttavia, in questo caso, il ciclo for deve funzionare con uno , integer o simile. Non può usare un genvar, perché avere il ciclo for all'interno del blocco sempre descrive un'operazione che si verifica su ciascun lato del clock, non un'operazione che può essere espansa staticamente durante l'elaborazione del progetto.

+0

Grazie per la rapida risposta. Avevo paura che sarebbe stato qualcosa del genere. Parte del problema era che volevo generare una sequenza di istruzioni if ​​o selettori di casi con il ciclo for, che non può essere eseguito in blocchi separati separati. – user1684538

+0

Esiste un modo per generare tutto il codice in un singolo blocco, oppure genvar non è in grado di farlo? – user2569332

2

All'interno di un modulo, Verilog contiene essenzialmente due costrutti: elementi e istruzioni. Le dichiarazioni si trovano sempre in contesti procedurali, che includono qualsiasi cosa tra init..end, funzioni, attività, sempre blocchi e blocchi iniziali. Gli elementi, come i costrutti di generazione, sono elencati direttamente nel modulo. Per i loop e la maggior parte delle dichiarazioni variabili/costanti possono esistere in entrambi i contesti.

Nel codice, sembra che si desideri che il ciclo for venga valutato come elemento di generazione, ma il ciclo fa effettivamente parte del contesto procedurale del blocco sempre. Perché un ciclo for sia trattato come un loop di generazione, deve essere nel contesto del modulo. Le parole chiave generate..endgenerate sono del tutto facoltative (alcuni strumenti li richiedono) e non hanno alcun effetto. Vedere this answer per un esempio di come vengono valutati i loop di generazione.

//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

Se non ti dispiace dover compilare/generare il file allora si potrebbe utilizzare una tecnica di lavorazione pre. Questo ti dà la potenza del generare ma si traduce in un file Verilog pulito che è spesso più facile da eseguire il debug e porta a meno problemi di simulazione.

Io uso RubyIt per generare file verilog da modelli utilizzando ERB (Embedded Ruby).

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

Generazione del file module_name.v con:

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

Il generato 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

non hai bisogno di una generare bock se si desidera che tutti i bit di temp assegnato nello stesso blocco sempre.

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 

In alternativa, se il vostro simulatore supporta IEEE 1800 (SytemVerilog), quindi

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

per Verilog solo fare

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