61 / 63 · Concetto
Pipeline arrestabile e backpressure
Calcolare ready per stadio evitando perdite, duplicazioni e ricalcoli durante stop e avanzamenti simultanei.
Le lezioni sono gratuite. Iscriviti per salvare i progressi.
Se il destinatario non può ricevere ogni ciclo
Prerequisiti: buffer ready/validHandshake Contratto che conferma il trasferimento quando valid del mittente e ready del destinatario valgono 1 allo stesso fronte. Include il mantenimento dei dati in attesa. Approfondisci da un posto e allineamento di pipelinePipeline Divide i calcoli in stadi separati da registri elaborando più ingressi sovrapposti. Dati, valid e controlli devono essere allineati per stadio. Approfondisci.
Aggiungere solo out_ready a una pipeline fissa non basta. Quando l'ultimo stadio pieno si ferma, quelli anteriori non devono sovrascrivere dati. La backpressureBackpressure Il destinatario segnala temporanea impossibilità di ricevere, fermando il flusso. I dati non consegnati devono restare conservati. Approfondisci deve propagare lo stop verso l'ingresso.
Ogni stadio conserva un dato e un valid. Il secondo accetta se è vuoto o può consegnare; il primo segue la stessa regola.
in_ready è r1. Anche con r2=0, il primo stadio vuoto può ricevere un dato. Usa meglio lo spazio che rifiutare sempre ogni ingresso quando l'uscita è ferma.
Aggiornare ogni stadio solo quando autorizzato
L'esempio calcola y=2(x+1) per x unsignedUnsigned Interpretazione dei bit come intero non negativo. Il campo a n bit è 0–2^n−1 e può differire dalla lettura signed degli stessi bit. Approfondisci a otto bit. Lo stadio 1 conserva x+1 su nove bit, il secondo sposta di uno su dieci. Anche x=255 produce esattamente 512.
module stallable_pipeline (
input logic clk, rst,
input logic in_valid,
output logic in_ready,
input logic [7:0] in_data,
output logic out_valid,
input logic out_ready,
output logic [9:0] out_data
);
logic v1, v2, r1, r2;
logic [8:0] d1;
logic [9:0] d2;
assign r2 = !v2 || out_ready;
assign r1 = !v1 || r2;
assign in_ready = r1;
assign out_valid = v2;
assign out_data = d2;
always_ff @(posedge clk) begin
if (rst) begin
v1 <= 1'b0;
v2 <= 1'b0;
end else begin
if (r2) begin
v2 <= v1;
if (v1) d2 <= {d1, 1'b0};
end
if (r1) begin
v1 <= in_valid;
if (in_valid) d1 <= {1'b0, in_data} + 9'd1;
end
end
end
endmoduleCon nonblockingNonblocking Assegnazione RTL sequenziale con <=. Valuta il membro destro e pianifica l’aggiornamento, permettendo ai registri dello stesso fronte di usare lo stato precedente. Approfondisci, il secondo stadio riceve il vecchio d1, non quello appena calcolato. r1=0 mantiene v1, d1; r2=0 mantiene v2, d2. Fermare solo valid continuando ad aggiornare i dati è errato.
Seguire due stadi pieni
All'inizio v2 contiene il risultato A, v1 l'intermedio B e C attende all'ingresso.
| out_ready | in_ready | Azione al fronte |
|---|---|---|
| 0 | 0 | Mantiene A, B; C non accettato |
| 0 | 0 | Mantiene A, B; C non accettato |
| 1 | 1 | Consegna A, sposta B al secondo, accetta C |
Il mittente mantiene C e in_valid fino all'accettazione. Passare al dato seguente credendo C inviato al primo fronte fermo perde C.
Le colonne sono valori prima del fronte di salitaFronte di salita Passaggio del clock da 0 a 1, distinto dall’intero intervallo di livello CLK=1. Approfondisci. A è in fondo, B davanti, C attende. E2 consegna A e accetta C; prima di E3 l'uscita è B.
Mostra i dati della forma d’onda
| Segnale | Forma d’onda | Valori del bus |
|---|---|---|
| edge | 2345 | E0 → E1 → E2 → E3 |
| out_ready | 0.1. | |
| out_valid | 1... | |
| out_data | 2..3 | A → B |
| in_valid | 1... | |
| in_ready | 0.1. | |
| in_data | 2..3 | C → D |
Verificare la conservazione
Con Nin ingressi accettati e Nout uscite trasferite dopo reset, l'occupazione è la seguente. Non si contano trasferimenti sul fronte reset.
Il conteggio corretto può nascondere A duplicato e B perso: verificate valori e ordine con una queue. Variate valid e ready indipendentemente includendo stop lunghi, flusso continuo e svuotamento tramite reset.
Anche ready è un cammino temporale
Molti stadi allungano il percorso combinatorio inverso r2→r1. Registrare ready può richiedere spazio aggiuntivo per ingressi già promessi durante il ritardo. Inserire soltanto un flip-flop senza considerare memoria e protocollo non è un'ottimizzazione temporale sicura.
Prova tu
v1=0, v2=1, out_ready=0, in_valid=1: si può accettare? Con out_ready ancora 0 si possono ricevere altri dati?
Leggi la spiegazione
All’inizio r2=0 ma r1=1: un dato riempie il primo stadio. Poi v1=v2=1 e r1=r2=0: niente ulteriori accettazioni. Così si utilizzano entrambi i posti.