57 / 63 · Konzept
Zeiger und Grenzregeln einer FIFO mit einem Takt
Zeiger und Belegung einer FIFO mit vier Plätzen sowie simultane Annahme bei empty/full definieren.
Lektionen sind frei lesbar. Schreibe dich ein, um deinen Fortschritt zu speichern.
Reihenfolge erhalten, ohne alle Daten zu verschieben
FIFOFIFO Warteschlange, die zuerst eingefügte Daten zuerst ausgibt. Voll-/Leerzustände und Regeln gleichzeitigen Lesens/Schreibens gehören zum Vertrag. gibt zuerst eingefügte Daten zuerst aus. Hier werden Lesen und Schreiben im selben Takt entschieden: DEPTH=4, acht Datenbits. rptr zeigt den nächsten Lese-, wptr den nächsten Schreibplatz. Beide sind zwei Bit und laufen von 3 nach 0 um. occupancy zählt 0–4 und braucht drei Bit.
rptr=wptr gilt sowohl bei leer als auch voll. Adressgleichheit allein als empty zu verwenden würde volle Daten verlieren. Wir führen count mit und . Für gelten:
Grenzregeln trennen Anforderung und Annahme
push und pop sind Anforderungen; p und q ihre tatsächlichen Annahmen. Ohne Reset werden sie aus dem Zustand vor der Flanke berechnet:
Bei empty und beiden Anforderungen wird nur push angenommen, da kein alter Wert zum Lesen existiert. Neue Daten erscheinen nicht sofort am Ausgang. Bei full werden beide angenommen: Der alte Head wird entnommen und schafft so Platz. full bedeutet hier „vier Werte gespeichert“, kein bedingungsloses Push-Verbot.
| Zustand vor Flanke | Nur push | Nur pop | Beide |
|---|---|---|---|
| C=0 | Einen speichern | Ablehnen | Nur push, C=1 |
| 0<C<4 | C+1 | C−1 | Beide, C bleibt |
| C=4 | Ablehnen | C=3 | Beide, C=4 |
Grenzen mit Taktschritten prüfen
Fordern Sie anfangs push und pop gemeinsam an: Nur push darf angenommen werden. Füllen Sie dann ohne pop vier Plätze und aktivieren Sie beide mit neuen Daten. occupancy bleibt 4, ausgegeben wird der alte Head und hinten steht der neue Wert.
FIFO mit vier Einträgen. Anfangs leer, Lese- und Schreibzeiger stehen auf 0. pop wird angenommen, wenn sie nicht leer ist. push wird angenommen, wenn Platz frei ist oder an derselben Flanke ein pop angenommen wird.
Das Modell zeigt Zustand nach jeder steigenden FlankeSteigende Flanke Übergang des Takts von 0 auf 1. Nicht zu verwechseln mit dem gesamten hohen Pegelintervall CLK=1. Mehr erfahren. Angenommenes pop setzt output valid=1; ohne pop an der nächsten Flanke hält das AusgangsregisterRegister Speichert einen Zustand aus mehreren Bits. Die synchronen Register dieses Kurses übernehmen festgelegte Eingaben an Taktflanken. Mehr erfahren seinen Wert, aber valid wird 0. Alte Bits leerer Plätze werden verborgen. „Von vorn“ initialisiert die gesamte Übung und bildet keinen RTL-SpeicherresetReset Steuerung zur Rückkehr in einen festgelegten Anfangszustand. Synchron/asynchron und Priorität gegenüber anderen Steuerungen müssen definiert werden. Mehr erfahren ab.
RTL einschließlich registriertem Ausgang
module fifo4 (
input logic clk, rst, push, pop,
input logic [7:0] din,
output logic [7:0] dout,
output logic dout_valid, full, empty,
output logic [2:0] occupancy
);
timeunit 1ns;
timeprecision 1ps;
logic [7:0] mem [0:3];
logic [1:0] rptr, wptr;
logic take_push, take_pop;
assign empty = (occupancy == 3'd0);
assign full = (occupancy == 3'd4);
assign take_pop = !rst && pop && !empty;
assign take_push = !rst && push && (!full || take_pop);
always_ff @(posedge clk) begin
if (rst) begin
rptr <= 2'd0;
wptr <= 2'd0;
occupancy <= 3'd0;
dout_valid <= 1'b0;
end else begin
dout_valid <= take_pop;
if (take_push) begin
mem[wptr] <= din;
wptr <= wptr + 2'd1;
end
if (take_pop) begin
dout <= mem[rptr];
rptr <= rptr + 2'd1;
end
case ({take_push, take_pop})
2'b10: occupancy <= occupancy + 3'd1;
2'b01: occupancy <= occupancy - 3'd1;
default: occupancy <= occupancy;
endcase
end
end
endmoduleoccupancy wird nicht durch zwei unabhängige ifs erhöht und verringert. Zwei nonblocking-ZuweisungenNonblocking Sequenzielle RTL-Zuweisung mit <=. Nach Auswertung der rechten Seite wird die Aktualisierung geplant, sodass Register derselben Flanke den alten Zustand verwenden. Mehr erfahren an dasselbe Register würden bei Gleichzeitigkeit nur die letzte wirksam lassen. Beide Zeiger bewegen sich jeweils bei Annahme; count wird einmal aus vier Fällen bestimmt. Annahmebedingungen verhindern Unterlauf bei 0 und Überlauf bei 4.
Gleiche Adresse bei voller FIFO lesen und schreiben
Nach A, B, C, D gilt rptr=wptr=0, occupancy=4. Mit pop=push=1, din=E folgt dout=A, dout_valid=1, Inhalt [B, C, D, E]. Beide Zeiger werden 1, count bleibt 4. mem[0] wird E, doch die rechte Seite der nonblocking-Lesezuweisung sieht das alte A. Dieses read-first-Verhalten ist für den Austausch bei full notwendig.
Danach liefert nur pop B und count=3. Bei empty mit din=Z und beiden Anforderungen wird hingegen nur count=1, dout_valid=0. Erst ein weiteres pop liefert Z. Direkte Weitergabe bei empty und Austausch bei full sind getrennte Entscheidungen.
Synchroner active-high-Reset initialisiert Zeiger, count, dout_valid, nicht Speicher oder dout. Nach Reset blockiert empty das Lesen alter Bits; später werden nur neu beschriebene Plätze gelesen. Ein vollständiger Arrayreset ist funktional unnötig. Daten mit dout_valid=0 werden ignoriert. Gültige Daten antworten auf angenommenes pop; ohne separates Ausgangs-ready muss der Verbraucher sie annehmen.
Bei einer Tiefe, die keine Zweierpotenz ist, ist natürlicher Zweibitüberlauf ungeeignet: Tiefe drei muss explizit nach Adresse 2 auf 0 springen. Falls Synthese RAM nutzt, prüfen Sie dessen Old-data-Verhalten bei Kollision. Dieses RTL gilt nur für einen Takt und übernimmt keine Zeigersynchronisation einer asynchronen FIFO.
Selbst ausprobieren
Nach Reset je eine Flanke: (1) push A+pop, (2) push B, (3) push C, (4) push D, (5) push E+pop, (6) pop. Geben Sie Inhalt, occupancy, valid und gültige Ausgabe an. Warum braucht (5) read-first?
Erklärung lesen
(1) [A],1, valid=0. (2) [A, B],2,0. (3) [A, B, C],3,0. (4) [A, B, C, D],4,0. (5) [B, C, D, E],4, valid=1, dout=A. (6) [C, D, E],3, valid=1, dout=B. In (1) fehlt ein alter Head, daher kein pop. In (5) sind rptr=wptr=0: Lesen und Schreiben treffen denselben Platz und müssen das alte A ausgeben. Write-first mit E verletzt FIFO-Reihenfolge und Inhalt. Ausgaben bei valid=0 werden nicht bewertet.