Perché questo Verilog riduce 30 macrocellule e centinaia di termini di prodotto?


8

Ho un progetto che consuma 34 delle macrocellule di Xilinx Coolrunner II. Ho notato che avevo un errore e l'ho rintracciato fino a questo:

assign rlever = RL[0] ? 3'b000 :
                RL[1] ? 3'b001 :
                RL[2] ? 3'b010 :
                RL[3] ? 3'b011 :
                RL[4] ? 3'b100 :
                RL[5] ? 3'b101 :
                RL[6] ? 3'b110 :
                        3'b111;

assign llever = LL[0] ? 3'b000 :
                LL[1] ? 3'b001 :
                LL[2] ? 3'b010 :
                LL[3] ? 3'b011 :
                LL[4] ? 3'b100 :
                LL[5] ? 3'b101 :
                        3'b110 ;

L'errore è che rlevere lleversono uno po 'largo, e ho bisogno che siano tre bit di larghezza. Sciocco me Ho cambiato il codice per essere:

wire [2:0] rlever ...
wire [2:0] llever ...

quindi c'erano abbastanza pezzi. Tuttavia, quando ho ricostruito il progetto, questa modifica mi è costata più di 30 macrocellule e centinaia di termini di prodotto. Qualcuno può spiegare cosa ho fatto di sbagliato?

(La buona notizia è che ora simula correttamente ... :-P)

MODIFICARE -

Suppongo di essere frustrato perché nel momento in cui penso di iniziare a capire Verilog e il CPLD, succede qualcosa che dimostra chiaramente che non ho comprensione.

assign outp[0] = inp[0] | inp[2] | inp[4] | inp[6];
assign outp[1] = inp[1] | inp[2] | inp[5] | inp[6];
assign outp[2] = inp[3] | inp[4] | inp[5] | inp[6];

La logica per implementare queste tre linee si verifica due volte. Ciò significa che ciascuna delle 6 linee di Verilog consuma circa 6 macrocellule e 32 termini di prodotto ciascuno .

EDIT 2 - Secondo il suggerimento di @ ThePhoton sull'interruttore di ottimizzazione, ecco le informazioni dalle pagine di riepilogo prodotte da ISE:

Synthesizing Unit <mux1>.
    Related source file is "mux1.v".
    Found 3-bit 1-of-9 priority encoder for signal <code>.
Unit <mux1> synthesized.
(snip!)
# Priority Encoders                                    : 2
 3-bit 1-of-9 priority encoder                         : 2

Quindi chiaramente il codice è stato riconosciuto come qualcosa di speciale. Il design sta ancora consumando enormi risorse, tuttavia.

EDIT 3 -

Ho realizzato un nuovo schema che includeva solo il mux raccomandato da @thePhoton. Synthesis ha prodotto un utilizzo insignificante delle risorse. Ho anche sintetizzato il modulo raccomandato da @Michael Karas. Ciò ha anche prodotto un utilizzo insignificante. Quindi un po 'di sanità mentale sta prevalendo.

Chiaramente, il mio uso dei valori della leva sta causando costernazione. E c'è dell'altro.

Modifica finale

Il design non è più folle. Non sono sicuro di cosa sia successo, tuttavia. Ho apportato molte modifiche per implementare nuovi algoritmi. Un fattore che ha contribuito è stata una "ROM" di 111 elementi a 15 bit. Ciò ha consumato un numero modesto di macrocellule ma moltodei termini del prodotto - quasi tutti quelli disponibili su xc2c64a. Lo cerco ma non me ne ero accorto. Credo che il mio errore sia stato nascosto dall'ottimizzazione. Le 'leve' di cui sto parlando vengono utilizzate per selezionare i valori dalla ROM. Ipotizzo che quando ho implementato l'encoder prioritario a 1 bit (danneggiato), ISE ha ottimizzato parte della ROM. Sarebbe un bel trucco, ma è l'unica spiegazione a cui riesco a pensare. Questa ottimizzazione ha ridotto drasticamente l'utilizzo delle risorse e mi ha indotto a prevedere una certa linea di base. Quando ho corretto l'encoder prioritario (come da questo thread), ho visto il sovraccarico dell'encoder prioritario e della ROM che era stato precedentemente ottimizzato e attribuito questo al primo.

Dopo tutto questo, ero bravo con le macrocellule ma avevo esaurito i termini del mio prodotto. La metà della ROM era un lusso, in realtà, dato che era solo la seconda parte della prima metà. Ho rimosso i valori negativi, sostituendoli altrove con un semplice calcolo. Questo mi ha permesso di scambiare macrocellule con termini di prodotto.

Per ora, questa cosa si adatta a xc2c64a; Ho usato rispettivamente l'81% e l'84% delle mie macrocellule e termini di prodotto. Certo, ora devo provarlo per assicurarmi che faccia quello che voglio ...

Grazie a ThePhoton e Michael Karas per l'assistenza. Oltre al supporto morale che mi hanno prestato per aiutarmi a risolvere questo problema, ho imparato dal documento Xilinx pubblicato da ThePhoton e ho implementato l'encoder prioritario suggerito da Michael.


non tutti i punti interrogativi implicano effettivamente un multiplexer e strutturalmente li hai anche messi in cascata? Quante macro-celle ti aspettavi che prendesse?
Vicatcu,

Non so quante macrocellule dovrebbe consumare il costrutto. Tuttavia, considerando che il mio progetto sta attualmente consumando 34 macrocelle tra cui quei due multiplexor da 1 bit e che questi sono una piccola parte del progetto, sono sorpreso da questo risultato.
Tony Ennis,

Quale strumento stai usando?
The Photon,

Xilinx's ISE ...
Tony Ennis,

Nel codice nella tua modifica, penso che tu voglia |invece di ||.
The Photon,

Risposte:


7

Il codice che mostri è essenzialmente un codificatore prioritario. Cioè, ha un ingresso di molti segnali e la sua uscita indica quale di questi segnali è impostato, dando la priorità al segnale più a sinistra se è impostato più di uno.

Tuttavia, vedo definizioni contrastanti del comportamento standard per questo circuito nei due punti che ho controllato.

Secondo Wikipedia , il codificatore a priorità standard numera i suoi ingressi da 1. Cioè, se è impostato il bit di ingresso meno significativo, produce 1, non 0. Il codificatore a priorità Wikipedia emette 0 quando nessuno dei bit di ingresso è impostato.

La Guida dell'utente XST di Xilinx (p. 80), tuttavia, definisce un codificatore di priorità più vicino a ciò che è stato codificato. Gli ingressi sono numerati da 0, quindi quando viene impostato l'ingresso lsb, esso dà uno 0. Tuttavia, la definizione di Xilinx non fornisce specifiche per l'output quando tutti i bit di input sono chiari (il tuo codice genererà 3'd7).

La guida per l'utente di Xilinx, ovviamente, determinerà cosa si aspetta il software di sintesi Xilinx. Il punto principale è che (*priority_extract ="force"*)per XST è necessaria una direttiva speciale per riconoscere questa struttura e generare risultati di sintesi ottimali.

Ecco il modulo consigliato da Xilinx per un codificatore prioritario da 8 a 3:

(* priority_extract="force" *)
module v_priority_encoder_1 (sel, code);
input [7:0] sel;
output [2:0] code;
reg [2:0] code;
always @(sel)
begin
    if (sel[0]) code = 3b000;
    else if (sel[1]) code = 3b001;
    else if (sel[2]) code = 3b010;
    else if (sel[3]) code = 3b011;
    else if (sel[4]) code = 3b100;
    else if (sel[5]) code = 3b101;
    else if (sel[6]) code = 3b110;
    else if (sel[7]) code = 3b111;
    else code = 3bxxx;
end
endmodule

Se riesci a riorganizzare la logica circostante per consentirti di utilizzare lo stile di codifica raccomandato da Xilinx, è probabilmente il modo migliore per ottenere un risultato migliore.

Penso che puoi ottenerlo istanziando il modulo encoder Xilinx con

v_priority_encoder_1 pe_inst (.sel({~|{RL[6:0]}, RL[6:0]}), .code(rlever));

Non ho combinato tutti i bit RL[6:0]per ottenere un ottavo bit di input che attiverà l'uscita 3'b111 quando tutti i bit RL sono bassi.

Per la lleverlogica, puoi probabilmente ridurre l'utilizzo delle risorse creando un modulo codificatore modificato, seguendo il modello Xilinx, ma richiedendo solo 7 bit di input (i tuoi 6 bit di LLpiù un bit aggiuntivo che aumenta quando gli altri 6 sono tutti bassi).

L'uso di questo modello presuppone che la versione di ISE in uso stia utilizzando il motore di sintesi XST. Sembra che cambino gli strumenti di sintesi su ogni grande giro di ISE, quindi controlla che il documento che ho collegato corrisponda effettivamente alla tua versione di ISE. In caso contrario, controlla lo stile consigliato nella documentazione per vedere cosa si aspetta il tuo strumento.


Grazie, ci vorrà del tempo per digerire. Il mio ISE sta usando XST anche se non so quale versione.
Tony Ennis,

La chiave sta avendo (* priority_extract="force" *)e probabilmente includendo esplicitamente anche l'output non importa, anche se si copre ogni possibile input. (Senza di essa, XST sta probabilmente provando a generare una tabella di ricerca completa, motivo per cui così tanti termini di prodotto) Prova prima ad aggiungere l'opzione non importa. Se non funziona, prova a utilizzare esattamente la piastra di cottura Xilinx.
The Photon,

Ho implementato un rip completo del codice sopra e non ho ottenuto un risultato migliore. Le pagine di riepilogo ISE indicano che è stato riconosciuto un MUX, sebbene il riconoscimento non sia stato forte come per altri costrutti. Invierò le informazioni pertinenti tra qualche minuto.
Tony Ennis,

modifica - ignora il commento sopra su "riconoscimento forte" - è lì, l'ho perso ieri sera; Ho rifatto il lavoro e la realtà funziona correttamente.
Tony Ennis,

6

La risposta di ThePhoton è eccellente. Vorrei aggiungere alcune informazioni aggiuntive qui per la vostra considerazione. Ciò deriva dal fatto che anche se disponiamo di dispositivi FPGA e CPLD all'avanguardia che utilizzano HDL e strumenti di sistesi, può essere informativo guardare da vicino le cose progettate anni fa. Resta con me mentre cammino attraverso questo alla mia raccomandazione alla fine.

Esistono parti logiche discrete che eseguono la funzione di codifica prioritaria. La logica implementata da queste parti esiste da molto tempo quando era essenziale ridurre al minimo il numero di transistor. È possibile cercare sul web parti logiche con numeri di parte generici come 74HC148 o MC14532B per trovare schede tecniche che includono diagrammi logici equivalenti per queste parti. Lo schema seguente è un esempio tratto dalla scheda tecnica TI per la parte 74HC148 .

inserisci qui la descrizione dell'immagine

Questa logica implementa la seguente tabella di verità (presa dalla stessa scheda tecnica):

inserisci qui la descrizione dell'immagine

Si noti che la famiglia di parti sopra utilizza segnali di ingresso attivi bassi. Un'altra scheda tecnica per la parte MC14532B di ON Semiconductor mostra una tabella di verità per la funzione encoder che utilizza segnali di ingresso alti attivi simili all'esempio di Verilog.

inserisci qui la descrizione dell'immagine

La stessa scheda tecnica mostra le equazioni logiche per l'MC14532B come segue:

inserisci qui la descrizione dell'immagine

Potresti considerare di codificare equazioni simili direttamente nel tuo codice Verilog per vedere come si confronta con il tuo esempio attuale. È molto probabile che si traduca in un risultato molto più favorevole.


Grazie, lo farò. Questo problema mi sta uccidendo. Credo che si stesse sintetizzando in modo più efficiente in precedenza. E poi ho cambiato qualcosa. / selfbonk
Tony Ennis,

Grazie, l'ho implementato. Sfortunatamente non ha fatto differenza materiale.
Tony Ennis,

Bella risposta. Vediamo Tony quanti termini di prodotto dovrebbe essere necessario per implementare questa logica. Tony, se usi la piastra di caldaia di Xilinx o le equazioni di Michael e stai ancora generando centinaia di termini di prodotto, allora devi cercare un sottile cambiamento da qualche altra parte nel tuo codice che potrebbe aver causato il problema; oppure osserva attentamente il file di registro di sintesi per vedere se sta accadendo qualcosa che non ti aspetti.
The Photon,

Sono completamente d'accordo con @ThePhoton. Ho nascosto qualcosa. Sono sicuro che questo funzionava: non avevo nemmeno notato che il consumo era così ridotto. Vabbè, è una buona scusa per iniziare a comprendere meglio le informazioni di riepilogo.
Tony Ennis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.