vorgegebene Simulationsmodell

vorgegebene Simulationsmodell
348
4 Vom Transistor zur Schaltung
mit dem direkten und dem verzögerten negierten Takt als Eingabesignale. Bei
einer steigenden Taktflanke sind beide Eingänge des UND-Gatters für eine
kurze Zeit td1 gleichzeitig »1«, so dass das nachfolgende UND-Gatter den
gewünschten Impuls erzeugt. Für T = 1, T = 0 und auch nach der fallenden
Taktflanke bleibt das Freigabesignal inaktiv.
thL , tdL
n
td1
T
z
a)
ts
tn
thr
tdr
n
x
x
&
E
E
y
td2
Vorhaltezeit
Nachhaltezeit
Registerhaltezeit
Registerverzögerung
Wert ungültig
Abtastfenster
wi Datenwert
b)
T
1
0
z
1
0
E
1
0
td1
td2
td2
ts = 0
tn = td1
w1
x
tdR = tdL
Bezugszeit der ⇒
thR = thL
Übernahme
y
w0
w1
Abb. 4.48. Gepulstes Latch a) Schaltung b) Zeitverhalten
Eine korrekte Datenübernahme ohne Glitches am Latch-Ausgang setzt
voraus, dass das Eingabesignal während der gesamten Dauer, die das Freigabesignal aktiv ist, d.h. im Zeitfenster td2 bis td1 + td2 , stabil und gültig
ist. Zur Beschreibung der Gesamtschaltung mit dem Registermodell aus Abschnitt 1.4.1 ist es notwendig, den Bezugszeitpunkt für die Datenübernahme
auf die um td2 verzögerte steigende Flanke des Übernahmeimpulses zu verschieben. Das äquivalente Registermodell hat dann eine Vorhaltezeit ts = 0
und eine Nachhaltezeit tn = td1 . Die Registerverzögerung ist gleich der LatchVerzögerung und die Registerhaltezeit gleich der Latch-Haltezeit.
Die Registernachbildung mit einem gepulsten Latch hat schaltungsbedingt
eine Nachhaltezeit größer null. Das hat für die Register-Transfer-Funktionen
zwischen den Registern den Nachteil, dass eine Mindesthaltezeit in der Größenordnung der Nachhaltezeit zu fordern ist (Abb. 4.49). Die Synthese unterstützt die Zusicherung von Mindesthaltezeiten normalerweise nicht, so dass
TP
tn
x
a) E
c)
x
E
thr , tdr
x’
thf , tdf
y = f (x)
thr + thf > tn
E
ts = 0, tn > 0 thr , tdr
y
x
E
tdr + tdf < TP
TP
1
0
tdr
thr
x’ w0
y’
w1
thf
b)
y f (w0 )
w2
tdf
tn
f (w1 )
Abb. 4.49. Register-Transfer-Funktion mit gepulsten Latches a) Schaltung b)
Signalverläufe c) zuzusichernde Zeitbedingungen
4.3 Speicherzellen, Latches und Register
349
manuelle Nacharbeit bei der Festlegung der Schaltungsstruktur und der Leitungsführung erforderlich werden kann.
4.3.5 Register aus Master-Slave-Flipflops
Ein Master-Slave-Flipflop ist eine taktflankengesteuerte Speicherzelle, die aus
zwei taktzustandsgesteuerten D-Flipflops zusammengesetzt ist. Das erste DFlipflop – der Master – übernimmt die Daten vor der Übernahmeflanke und
speichert sie in der Takthälfte nach der Übernahmeflanke. Das zweite DFlipflop – der Slave – übernimmt den zwischengespeicherten und damit stabilen Wert aus dem Master in der zweiten Takthälfte (Abb. 4.50). Das Eingabesignal des gesamten Master-Slave-Flipflops, das über den Master und den
Slave zum Ausgang weitergeleitet wird, muss nur während eines kleinen Zeitfensters vor der Übernahmeflanke einen gültigen und stabilen Wert haben. Die
Nachhaltezeit ist null. Die Gesamtschaltung ist zwar deutlich aufwändiger als
ein funktionsgleiches gepulstes D-Flipflop. Dafür sind Master-Slave-Flipflops
laufzeitunkritisch und Schaltungen mit ihnen einfacher zu entwerfen.
x
T
T
1
0
x
1
0
z
1
0
y
1
0
Master
Slave
z
x
x
E
E
Symbol
y
x
y
T
Übernahmeflanke
Abtastfenster
Master speichert
Slave speichert
Abb. 4.50. Master-Slave-Flipflop
Ein Register fasst mehrere Master-Slave-Flipflops mit einem gemeinsamen
Takteingang zusammen. Die einzelnen Speicherzellen sind räumlich voneinander getrennt, so dass die aktiven Taktflanken sie mit einem geringen Taktversatz erreichen (vgl. Abschnitt 1.4.5). Die Eingabedaten müssen um die Vorhaltezeit vor dem frühestmöglichen Zeitpunkt, zu dem die aktive Taktflanke
eine Registerzelle erreichen kann, bis zur Nachhaltezeit nach dem spätestmöglichen Zeitpunkt, zu dem die aktive Taktflanke eine Registerzelle erreichen
kann, stabil anliegen. Die Registerausgabe ändert sich frühstens nach der Zellenhaltezeit nach dem frühestmöglichen Zeitpunkt der Taktflanke. Der neue
Wert ist spätestens nach der Zellenverzögerungszeit nach dem spätestmöglichen Zeitpunkt der Taktflanke am Registerausgang verfügbar (Abb. 4.51).
Bei einem Taktversatz ist irgendein Zeitpunkt innerhalb des Intervalls, in
dem die aktive Taktflanke die Zellen erreichen kann, als Bezugszeitpunkt zu
definieren. Mit dem frühestmöglichen Zeitpunkt als Bezugszeitpunkt sind die
Vorhaltezeit und die Haltezeit des Registers gleich der Vorhaltezeit und der
350
4 Vom Transistor zur Schaltung
tsZ
thZ , tdZ
x0
y0
x1
y1
t∆T
xn−1
t∆T
T
tsZ
tsR
yn−1
y
T
thR , tdR
n
n
x
a)
y
T
wi
(tnZ = 0)
x
···
tsR , tnR
1
0
wi−1
thZ
b)
Abtastfenster
modellierter Abtastzeitpunkt
thR
tnR
wi
tdR
tdZ
t..R Zeitparameter Register
t..Z Zeitparameter Zelle
t∆T maximaler Taktversatz
Abb. 4.51. Register mit Taktversatz a) Schaltung b) Zeitverläufe
Haltezeit der einzelnen Speicherzellen. Die Nachhaltezeit ist gleich dem maximalen Taktversatz10 und die maximale Verzögerungszeit gleich der Summe
aus dem Taktversatz und der Verzögerungszeit einer Speicherzelle:
tsR = tsZ
tnR = t∆T
thR = thZ
tdR = t∆T + tdZ
(4.34)
(tsR – Vorhaltezeit des Registers; tsZ – Vorhaltezeit einer Speicherzelle; thR –
Haltezeit des Registers; thZ – Haltezeit einer Speicherzelle; tnR – Nachhaltezeit des Registers; t∆T – maximaler Taktversatz; tdR – Verzögerungszeit des
Registers; tdZ – Verzögerungszeit einer Speicherzelle).
Eine Nachhaltezeit ungleich null lässt sich schlecht simulieren (vgl. Abb.
1.47 in Abschnitt 1.4.2). Mit einem Taktversatz kleiner der Haltezeit lässt
sich der Bezugszeitpunkt um den Taktversatz nach hinten verschieben, ohne
dass die Haltezeit einen nicht simulierbaren negativen Wert annimmt. Die
Vorhaltezeit vergrößert sich, die Halte- und die Verzögerungszeit verringern
sich gegenüber Gleichung 4.34 um den maximalen Taktversatz:
tsR = tsZ + t∆T
tnR = 0
thR = thZ − t∆T
tdR = tdZ
(4.35)
Die Nachhaltezeit ist null. Das ist das bevorzugte Verhaltensmodell für ein
Register.
Freigabe- und Initialisierungseingang
Abbildung 4.52 zeigt die Synthesebeschreibung für ein Register mit einem
Initialisierungs- und einem Freigabeeingang (vgl. Abschnitt 2.1.3). Beide Zu10
plus der Zellennachhaltezeit, die für Master-Slave-Flipflops null ist
4.3 Speicherzellen, Latches und Register
351
satzfunktionen werden oft benötigt. Das rechtfertigt eine genauere schaltungstechnische Betrachtung. Die zustandsgesteuerte Übernahme des Anfangswertes wird bei einem Register aus Master-Slave-Flipflops mit initialisierbaren
Slaves nachgebildet. Die Setz- und Rücksetzeingänge der Slave-Flipflops haben
Vorrang vor der Übernahme vom Dateneingang (vgl. Abschnitt 4.3.3, Abb.
4.46), so dass die Initialisierung sofort und unabhängig vom Takt, d.h. asynchron, erfolgt. Die zusätzliche Freigabesteuerung kann unterschiedlich realisiert werden. In Abb. 4.52 b wird die bedingte Übernahme mit einem Multiplexer nachgebildet, der wahlweise den Ist-Zustand oder das abzutastende
Signal an den Registereingang weiterleitet. In Abb. 4.52 c blockiert das inaktive Freigabesignal des Registers die Datenweitergabe vom Master zum Slave.
Das Freigabesignal E ∗ muss während der gesamten Slave-Übernahmephase
stabil und gültig sein. Dazu wird es in Abb. 4.52 c in dieser Taktphase in einem zusätzlichen D-Flipflop gespeichert. Das zusätzliche D-Flipflop wird für
das gesamte Register nur einmal benötigt, während in Abb. 4.52 b jedes Bit
seinen eigenen Multiplexer haben muss.
signal x, y: std_logic_vector(n-1 downto 0);
signal E, I, T: std_logic;
...
process(I, T):
begin
if I=’1’ then
y <= aw;
elsif E=’1’ and rising_edge(T) then
y <= x;
end if;
a) end process;
x
E
T
b) I
Slave
x
E
I
Master
x
E
x
T
E
c)
Master
x
E
0
1
I
x
E
&
Slave
x
E
I
y
y
E∗
Abb. 4.52. Register mit Freigabe- und Initialisierungseingang a) SyntheseBeschreibung b) Schaltung mit Eingabemultiplexer c) Schaltung mit Übernahmeblockierung für den Slave
4.3.6 Taktversorgung
Taktsignale legen die Zeitpunkte und Zeitfenster für die Datenübernahme in
die Register und Latches fest. Sie müssen zeitgenau und Glitch-frei sein. In
einer synchronen Schaltung werden alle Taktsignale von einem Haupttakt abgeleitet, der mit einem frequenzstabilen Oszillator erzeugt wird.
Oszillator
Ein Oszillator ist eine Schaltung, die ein periodisches Signal bereitstellt. Prinzipiell ist diese Funktion mit dem Ringinverter aus Abschnitt 4.2.3 realisierbar. Aber die Periodendauer des von einem Ringinverter erzeugten Signals ist
352
4 Vom Transistor zur Schaltung
meist zu ungenau. Zeitgenaue Oszillatoren verwenden einen Quarz oder einen
anderen mechanischen Schwinger als frequenzbestimmendes Element. Abbildung 4.53 a zeigt eine gebräuchliche Oszillatorschaltung mit einem Quarz. Der
Quarz verhält sich elektrisch wie ein Schwingkreis. Er bildet die Rückkopplung
des ersten Inverters, der hier als Verstärker arbeitet. Die beiden Kapazitäten
dienen zur Phasenverschiebung. Der zweite Inverter verbessert die Signalform.
Die relative Abweichung zwischen der Ist- und der Soll-Frequenz eines solchen
Oszillators liegt in der Größenordnung von 10−5 bis 10−4 . Das ist für den Takt
einer digitalen Schaltung ausreichend genau.
T
Quarz
C1
a)
Oszillatorschaltkreis
UV
Quarz
digitaler Schaltkreis
xtl in
C1
C2
C1 = C2 ≈ 20 pF
b)
C2
xtl out
Abb. 4.53. Quarzstabilisierter Taktgenerator a) Schaltung b) Schaltkreis mit
Quarz- oder Oszillatoranschlüssen
Quarze und andere mechanische Schwinger gibt es als Einzelbauteile oder
komplett mit Beschaltung als Oszillatorschaltkreise. Hochintegrierte Schaltkreise, die einen frequenzstabilen Takt benötigen, haben meist die Inverter für
den Oszillator mit auf dem Chip, so dass extern nur noch der mechanische
Schwinger angeschlossen werden muss. Alternativ kann an dem Schaltkreisanschluss, der auf den Eingang des ersten Inverters führt, auch ein externes
Taktsignal von einem Oszillatorschaltkreis oder einer anderen Taktquelle eingespeist werden (Abb. 4.53 b).
Taktnetze
Taktsignale müssen die Takteingänge von Hunderten oder Tausenden von angeschlossenen Speicherzellen treiben. Die große Anzahl von Lasten und der
geringe zulässige Taktversatz erfordern spezielle Treiber und spezielle Leitungsführungen (Abb. 4.54). In programmierbaren Logikschaltkreisen gibt es
spezielle Taktverteilernetze. In der Spartan- und Virtex-Familie erfolgt die
Einspeisung von Taktsignalen in diese Netze mit BUFG-Treibern. Der Entwurf der Taktnetze erfordert einen weit tieferen Einblick in das elektrische
Verhalten der Gatter und Leitungen als alle anderen Entwurfsaufgaben in der
Digitaltechnik zusammen.
Taktteiler
Takte mit einer geringeren Frequenz werden mit Taktteilern erzeugt. Ein Taktteiler ist ein autonomer Automat mit dem Ausgabetakt als Zustandssignal
4.3 Speicherzellen, Latches und Register
353
Treiber, Ausgleich von
Laufzeitunterschieden
Oszillator
(Basistakt)
···
Ableitung zeitlich
ausgerichteter Takte
···
Abb. 4.54. Schaltung zur Taktversorgung
und einem Zähler. In jedem Zustand wird nach einer bestimmten Anzahl von
Zählschritten der Zustand gewechselt und der Zähler zurückgesetzt. Bei einem Tastverhältnis von eins zu eins genügt eine Übergangsfunktion, die das
Zustandssignal immer nach der entsprechenden Taktanzahl invertiert. Abbildung 4.55 zeigt die VHDL-Beschreibung, den Operationsablaufgraph und die
Signalverläufe für einen Taktteiler mit dem Teilerverhältnis eins zu sechs. Die
Abtastung, die eine Definition des Taktes als Zustandssignal einschließt, ist
notwendig, um Glitches auf dem Ausgabetakt auszuschließen, und minimiert
gleichzeitig den Taktversatz zum Basistakt.
signal ct: tUnsigned(1 downto 0);
signal I, T, Q: std_logic;
...
process(T, I)
begin
if I=’1’ then
Q <= ’0’;
ct <= "00";
elsif rising_edge(T) then
if ct="10" then
ct <= "00";
Q <= not Q;
else
ct <= ct + "1";
end if;
end if;
a) end process;
sonst
ct <= ct + 1
Q=0
ct = 10
ct <= 00
b)
sonst
ct <= ct + 1
ct = 10
ct <= 00
Q=1
1
T0
ct
Q 10
c)
00 01 10 00 01 10 00 01 10 00
⇒Web-Projekt: P4.3/Taktteiler.vhdl
Abb. 4.55. Taktteiler a) VHDL-Beschreibung b) Operationsablaufgraph c) Signalverläufe
354
4 Vom Transistor zur Schaltung
Phasenregelkreise (PLL)
Komplexe Taktversorgungsschaltungen benutzen Phasenregelkreise (PLL –
phase locked loop). Ein Phasenregelkreis besteht aus einer Quelle für den Referenztakt, einem spannungsgesteuerten Oszillator (VCO – voltage controlled
oscillator), einem Phasenvergleicher, einem Integrator und optional zwei Frequenzteilern (Abb. 4.56). Der Referenztakt TRef muss eine konstante Frequenz
haben. Bei einem spannungsgesteuerten Oszillator lässt sich die Frequenz über
das Steuerpotenzial ϕCtl einstellen. Der Phasenkomparator vergleicht die aktiven Flanken der beiden Takte und steuert einen Integrator an. Gemeinsam
mit dem Integrator erhöht bzw. verringert der Phasenkomparator das Steuerpotenzial ϕCtl so, dass sich nach einer gewissen Zeit die Flanken der heruntergeteilten Takte T1 und T2 zeitlich angleichen. Man spricht dann vom Einrasten des Regelkreises, der von dem Phasenkomparator mit einem Ready-Signal
quittiert wird. Im eingerasteten Zustand erzeugt der spannungsgesteuerte Oszillator einen Takt TVCO mit einer Frequenz von exakt
fVCO =
Q
· fRef
P
(4.36)
(P – Teilerwert für den Referenztakt; Q – Teilerwert für den VCO-Takt; fRef
– Frequenz des Referenztaktes). Schaltungen mit Phasenregelkreisen in der
Taktversorgung sind erst betriebsbereit, wenn der Regelkreis eingerastet ist.
Nach dem Zuschalten der Versorgungsspannung dauert das einige Hundert
Takte. Erst dann kann der Rest der Schaltung initialisiert werden und seinen
normalen Betrieb aufnehmen. Wenn diese Reihenfolge verletzt wird, kann es
zu Fehlfunktionen kommen.
TVCO
VCO
TRef
Taktteiler T1
1:Q
Taktteiler T2
1:P
t∆T12
↑
Phasenvergleicher
↓
Rdy
Integrator
ϕCtl
Ready
Abb. 4.56. Takterzeugung mit einem Phasenregelkreis
Phasenregelkreise werden zur Frequenzvervielfachung und zur Korrektur
von Taktversätzen eingesetzt. Zur Erzeugung von Takten mit einem ganzzahligen Vielfachen der Frequenz des Basistaktes wird der P-Teiler nicht benötigt
(P = 1). Mit dem Q-Teiler wird der gewünschte Vervielfachungsfaktor eingestellt. Mit P > 1 und Q > 1 lassen sich nicht ganzzahlige Vielfache der Basistaktfrequenz einstellen. Eine andere Anwendung von Phasenregelkreisen ist
die Korrektur oder Erzeugung von Taktversätzen. Abbildung 4.57 a zeigt einen
Phasenregelkreis mit einem Johnson-Zähler als Taktteiler. Der Schaltungstakt
4.3 Speicherzellen, Latches und Register
355
T0 , der am Eingang des Johnson-Zählers abgegriffen wird, regelt sich so ein,
dass er in Frequenz und Phase mit dem Referenztakt übereinstimmt. An den
übrigen Ausgängen des Johnson-Zählers können frequenzgleiche, je um eine
Achtelperiode phasenversetzte Takte abgegriffen werden (Abb. 4.57 b). Einer
dieser phasenversetzten Takte dient in der Beispielschaltung als Ausgabetakt
Tout . Zu ihm soll das Ausgabesignal yout eine vorgegebene Vorhaltezeit ≥ ts
haben (Abb. 4.57 c). Die Vorhaltezeit ist in der Beispielschaltung die Differenz zahlreicher unterschiedlicher Verzögerungszeiten. Eine Synthese kann
normalerweise ein Vorhaltezeit-Constraint dieser Art schwer einhalten. In der
Beispielschaltung ist das aber kein Problem. Denn es ist hier vorgesehen, nach
der fertigen Platzierung und Verdrahtung die Vorhaltezeit durch eine geringfügige lokale Verdrahtungsänderung, nach der der Ausgabetakt vom richtigen
Zählerausgang abgegriffen wird, zu korrigieren.
Johnson-Zähler
T0
Power-on-Reset
TRef
TIst
a)
TVCO
T0
T1
T2
b)
T3
Phasenvergleicher,
Integrator
und VCO
x
I
T2
x
I
T3
x
I
TVCO
eigentliche Schaltung
x
I
Rdy
Taktrückführung
1
0
1
0
1
0
1
0
1
0
x
I
T1
x
I
yout
Tout
Treiber(1)
TIst = TRef
yout
1
0
≥ ts
c)
Tout
1
0
Abb. 4.57. PLL-basierte Erzeugung phasenverschobener und phasenkorrigierter
Taktsignale a) Schaltung b) phasenverschobene Ausgabesignale des JohnsonZählers c) Datenausgabe mit einer vorgegebenen Vorhaltezeit zum Ausgabetakt
((1) – Treiber für eine große Anzahl von Lasten)
4.3.7 Zusammenfassung und Übungsaufgaben
Daten werden in einer digitalen Schaltung bitweise gespeichert, entweder in
einer kleinen Kapazität oder in einer bistabilen Schaltung. Die Signalwerte in
Kapazitäten müssen nach der garantierten Haltezeit aufgefrischt werden. Eine
bistabile Schaltung – ein Ring aus zwei invertierenden Gattern – behält den
gespeicherten Wert bis zum nächsten Schreibvorgang oder bis zum Abschalten
der Versorgungsspannung. Für das Schreiben der Daten gibt es unterschiedliche Ansteuerschemata. Das klassische RS-Flipflop ist laufzeitkritisch und nicht
356
4 Vom Transistor zur Schaltung
für zu synthetisierende Entwürfe geeignet. Auch D-Flipflops und Latches, die
ihre Daten zustandsgesteuert übernehmen, sind für die Synthese problematisch. Das ideale taktflankengesteuerte Speicherelement ist das Master-SlaveFlipflop, das aus zwei D-Flipflops besteht. Der Master übernimmt die Daten
vor der aktiven Taktflanke und speichert sie nach der aktiven Taktflanke. Der
Slave übernimmt die im Master gespeicherten Daten und speichert, während
der Master die nächsten Daten übernimmt. Bei einem Master-Slave-Flipflop
mit initialisierbarem Slave hat die Initialisierung Vorrang vor der Datenübernahme und das Initialisierungssignal muss zum Takt ausgerichtet sein.
Der Takt einer digitalen Schaltung wird in der Regel mit einem Quarz oder
einem anderen mechanischen Schwinger stabilisiert, der eine hohe Zeitgenauigkeit sichert. Auch Taktteiler, Taktvervielfachungsschaltungen und Schaltungen zur Phasenkorrektur sind Spezialschaltungen zur Bereitstellung zeitgenauer Signale. Bei einer Taktversorgung mit Phasenregelkreisen ist auf die
Initialisierungsreihenfolge zu achten. Weiterführende und ergänzende Literatur siehe [20, 21, 30, 36, 47, 52].
Aufgabe 4.8
Gegeben sind die Transistorschaltung und der Eingabesignalverlauf in Abb.
4.58.
a) Welche Funktion haben die Gatter G1 bis G4?
b) Beschreiben Sie die Funktionsweise der Schaltung und skizzieren Sie die
Signalverläufe der Zwischensignale und des Ausgabesignals für den gegebenen Eingabesignalverlauf. Die Verzögerungszeiten seien in der Skizze
vernachlässigbar klein und die Haltezeit, wenn der Gatterausgang hochohmig ist, sei viel größer als die Taktperiode.
c) Um welchen Typ von Speicherzelle handelt es sich?
G1
G2
x
T
G3
z1
T̄
G4
z2
UV
y
ungültig
T
x
T̄
z1
z2
y
1
0
1
0
1
0
1
0
1
0
1
0
Abb. 4.58. Schaltung und Eingabesignalverlauf zu Aufgabe 4.8
Aufgabe 4.9
Wie müssen die Teilerverhältnisse P und Q für den Phasenregelkreis in Abb.
4.56 gewählt werden, um mit einem quarzstabilisierten 50MHz-Referenztakt
einen 300MHz-Takt zu erzeugen?
4.4 Schreib-Lese-Speicher
357
4.4 Schreib-Lese-Speicher
Für die Speicherung größerer Informationsmengen in digitalen Schaltungen
werden Blockspeicher eingesetzt. Blockspeicher sind bottom-up entworfene,
hochgradig optimierte Schaltungen mit einer wesentlich höheren Transistordichte, als der, die mit einer freistrukturierten Schaltung mit Latches und
Registern erzielbar ist. Blockspeicher bestehen aus einer zweidimensionalen
Speichermatrix, die den Hauptteil der Fläche einnimmt, umgeben von einer
Ansteuerschaltung (Abb. 4.59).
Schreib-Lese-Steuerung und Spaltenauswahl
.
..
bj+1 ..
bj
.
wi
Zelle
Zelle
Schnitt···
···
Zeilen(i, j)
(i, j + 1)
stellenauswahl
signale
wi+1
Zelle
Zelle
···
···
(i + 1, j)
(i + 1, j + 1)
wi Wortleitungen
..
..
.
.
b
Bitleitungen
j
Abb. 4.59. Blockspeicher
Die Funktion eines Blockspeichers wird in erster Linie von der Funktion der Zellen bestimmt. Abbildung 4.60 zeigt eine Übersicht über die wichtigsten Speicherarten. Es wird zwischen Festwertspeichern und Schreib-LeseSpeichern unterschieden. Festwertspeicher können nur einmal oder nur mit
großem Zeitaufwand beschrieben werden, behalten ihre Daten auch ohne Versorgungsspannung über Jahre und werden in einem separaten Abschnitt behandelt. Schreib-Lese-Speicher haben eine Schreibzeit in der Größenordnung
der Lesezeit. Statische Speicher behalten die gespeicherten Daten, bis die Versorgungsspannung abgeschaltet wird. Dynamische Speicher verwenden Kapazitäten als Speichermedium. Sie haben eine sehr hohe Speicherdichte, verlieren
ihre Daten aber ohne Auffrischen nach wenigen Millisekunden. Die meisten
Blockspeicher sind so aufgebaut, dass in jedem Zeitschritt nur der Zugriff auf
einen Speicherplatz möglich ist. Mehrportspeicher, bei denen mehrere Speicherzellen zeitgleich wahlfrei adressiert werden können, benötigen spezielle
Speicherart
Festwertspeicher
vom Hersteller
programmiert
mehrmals programmierbar
(ROM)
(EEPROM)
Schreib-Lese-Speicher
statisch
Einport (SRAM) Mehrport
Abb. 4.60. Einteilung der Blockspeicher
dynamisch
assoziativ
358
4 Vom Transistor zur Schaltung
Speicherzellen. Das gilt auch für Assoziativspeicher, die in einem Zugriffsschritt für ein Eingabedatenwort die Adresse, unter der es gespeichert ist,
suchen und ausgeben können.
4.4.1 SRAM
Die Abkürzung RAM ist ein Akronym für random access memory (Speicher mit wahlfreiem Zugriff) und wird als Bezeichnung für Schreib-LeseSpeicher mit wahlfreiem Zugriff verwendet11 . Das vorangestellte »S« steht
für »statisch« und bedeutet, dass die Speichermatrix aus statischen Speicherzellen besteht.
Ein SRAM besteht aus einer Matrix bistabiler Speicherzellen umgeben von
einer Ansteuerschaltung für die Spalten- und Zeilenauswahl und die SchreibLese-Steuerung. Die kleinste bistabile les- und beschreibbare Speicherzelle
benötigt sechs Transistoren. Vier Transistoren bilden den Inverterring (vgl.
Abschnitt 4.3.2). Die übrigen beiden Transistoren T5 und T6 dienen zur Zellenauswahl. Wenn die Wortleitung wi einer Speicherzelle i, j aktiv ist, schalten beide Auswahltransistoren ein. Das Steuersignalpaar r̄j , s̄j wählt dann
zwischen vier möglichen Aktionen: setzen (»1« schreiben), rücksetzen (»0«
schreiben), lesen und keine Operation (Abb. 4.61).
Spaltenauswahl
Zeilenauswahl
x
W
a)
bj
Schreibschaltung
r̄j
&
LeseSchaltung
T5
T6
x
1
0
-
W
1
1
0
-
-
bj
1
1
1
r̄i
1
0
Z∗
s̄i
0
1
Z∗
0 Z∗ Z∗
b)
s̄j
Zelle i, j
wi
y
setzen
rücksetzen
lesen
keine
Operation
x
W
wi
Z∗
Dateneingang bj Bitleitung
Schreibsignal
y Datenausgang
- beliebig (don’t care)
Wortleitung
Spaltentreiber deaktiviert
Abb. 4.61. SRAM a) Schaltung b) Ansteuerung der Speicherzellen
In Abb. 4.61 erfolgt die Zeilenauswahl über die Wortleitungen wi und die
Spaltenauswahl über die Bitleitungen bj . Bei jedem Zugriff sind genau eine
Wortleitung und eine Bitleitung aktiv. In allen anderen Zeilen sind die Auswahltransistoren ausgeschaltet und in allen anderen Spalten sind die Treiber
der Schreibschaltung für die Steuersignale r̄j , s̄j hochohmig und die Leseschaltungen deaktiviert, so dass keine Operation ausgeführt wird.
Für die ausgewählte Zelle schaltet die Wortleitung wi die Auswahltransistoren ein. Die Bitleitung aktiviert, wenn das Schreibsignal aktiv ist, die Treiber der Steuersignale r̄j , s̄j . Diese übernehmen den direkten und invertierten
11
Auch die meisten Nur-Lese-Speicher sind wahlfrei adressierbar.
4.4 Schreib-Lese-Speicher
359
Eingabewert. Bei einer zu schreibenden »1« wird der Zellenzustand über das
low-aktive Setzsignal s̄j auf »1« und bei einer zu schreibenden »0« wird er
über das low-aktive Rücksetzsignal r̄j auf »0« gesetzt. Wenn das Schreibsignal
W inaktiv ist, bleiben die Spaltentreiber inaktiv. Die Signale r̄j , s̄j übernehmen die schwachen Werte der ausgewählten Speicherzelle und leiten sie an die
Leseschaltung weiter, die den Datenwert übernimmt und zum Ausgang des
Schaltkreises durchstellt.
Abbildung 4.62 zeigt die komplette Transistorschaltung der 6-TransistorZelle und ein Beispiel für eine mögliche geometrische Anordnung. Die Transistoren haben Minimalabmessungen und werden auf minimaler Fläche angeordnet. Die zeilen- und spaltenweise Verdrahtung erfolgt in mehreren Ebenen
von Metallleiterbahnen. Zur Erzeugung einer Zellenmatrix aus vielen Zeilen
und Spalten wird die Zelle einfach Tausende oder Millionen Male kopiert.
r̄j
r̄j
s̄j
UV
s̄j
UV
xij
n+ -Gebiet
Polysilizium
T6
n-Wanne
p+ -Gebiet
T3
b)
x̄ij
T1
T5
wi
a)
T4
T4 T6
x̄ij
T3
T2
T2
T5 xij
T1
wi
Metall 1
Durchk. 1
Metall 2
Durchk. 2
Abb. 4.62. SRAM-Zelle a) Transistorschaltung b) geometrische Anordnung
Eine wichtige Kenngröße eines Schreib-Lese-Speichers ist die Zugriffszeit.
Das ist die Dauer eines Speicherzugriffs. Sie liegt bei großen Schreib-LeseSpeichern mit mehreren Megabit Speicherkapazität in der Größenordnung von
10 ns bis 100 ns und ist um Zehnerpotenzen größer als die Verzögerungszeit
eines einzelnen Gatters. Benötigt wird diese lange Zeit für die Adressdecodierung und das Treiben der Zeilen- und Spaltenleitungen, die eine linear mit der
Spalten- bzw. Zeilenanzahl zunehmende Lastkapazität haben. Aus Letzterem
folgt, dass die Zugriffszeit eines Speichers mit der Anzahl der Speicherzellen
zunimmt. Kleine Blockspeicher sind deutlich schneller als große.
Für die Simulation wurde das RAM-Modell in Abschnitt 3.4.3 in eine Kernfunktion und eine Schnittstellenfunktion unterteilt. Die Kern-Lesefunktion ähnelt der einer kombinatorischen Schaltung. Wenn das Schreibsignal inaktiv ist,
wird das Ausgabesignal nach einer Adressänderung nach der Haltezeit thy ungültig. Wenn die neue gültige Adresse anliegt, wird nach der Verzögerungszeit
tdy der gespeicherte Inhalt ausgegeben. Ein korrekter Schreibvorgang setzt
voraus, dass die Adresse hinreichend lange vor und nach der Aktivierung des
Schreibsignals stabil und gültig ist. Der Schreibimpuls muss eine Mindestlän-
360
4 Vom Transistor zur Schaltung
ge haben und die zu schreibenden Daten müssen hinreichend lange vor der
Deaktivierung des Schreibsignals stabil und gültig sein (Abb. 4.63). Bei einer
Verletzung der Zeitbedingungen werden ungültige Werte gespeichert.
a
Lesen
LA1
Lesen
LA2
Schreiben Schreiben
SA1
SA2
tsa
tna
twr
W
tsx
tdy
y
tnx
X1
x
X2
thy
Y1
LAi Leseadresse
SAi Schreibadresse
Y2
Yi gelesener Wert
Xi zu schreibender Wert
a
x
W
y
thy
tdy
tsa
tna
tsx
tnx
twr
Adresssignal
Eingangsdaten
Schreibsignal
Ausgabedaten
Lesehaltezeit
Leseverzögerungszeit
Adressvorhaltezeit
Adressnachhaltezeit
Datenvorhaltezeit
Datennachhaltezeit
Schreibzeit
Abb. 4.63. Signalverläufe zum Lesen und Schreiben für die SRAM-Kernfunktion
Simulationsmodell für einen Speicherschaltkreis
Große Blockspeicher sind oft eigenständige Schaltkreise. In diesem Abschnitt
wird ein vereinfachtes Simulationsmodell für einen asynchronen SRAM-Schaltkreis entwickelt. Ziel ist die Vermittlung eines skizzenhaften Einblicks in diese
Art der Modellbildung und die Entwicklung eines Beispielmodells für den darauf folgenden Unterabschnitt.
Der Beispielschaltkreis ist ein IS61LV25616AL [8]. Er hat achtzehn Adresseingänge, sechzehn bidirektionale Datenanschlüsse, eine Speicherkapazität von
vier Megabit und eine Zugriffszeit von 10 ns. Die Operationsauswahl soll ausschließlich über die drei Steuersignale
• Ausgabeaktivierung: oe (output enable, low-aktiv),
• Schreibaktivierung: wr (write, low-aktiv) und
• Schaltkreisauswahl: cs (chip select, low-aktiv)
erfolgen. Die hier nicht berücksichtigten Byte-Auswahlsignale seien ständig
aktiv. Die bidirektionalen Datenanschlüsse bilden einen Bus, über den bei
einem Schreibzugriff die zu schreibenden Daten zum Schaltkreis geschickt und
bei einem Lesezugriff die gelesenen Daten abgeholt werden.
Intern hat der Speicherschaltkreis, ohne dass das explizit im Datenblatt
steht, eine Matrixstruktur wie in Abb. 4.61, die in eine Schnittstellenschaltung eingebettet ist. Letztere erzeugt aus den im Datenblatt beschriebenen
Anschlusssignalverläufen die Signalverläufe für die Kernfunktion. Mit diesem
Hintergrundwissen kann das Simulationsmodell aus dem bereits behandelten
Simulationsmodell für die Kernfunktion und einem noch zu entwickelnden
4.4 Schreib-Lese-Speicher
361
Simulationsmodell für die Schnittstellenschaltung zusammengesetzt werden.
Für die Schnittstellenschaltung lässt sich aus dem Datenblatt Folgendes rekonstruieren. Das Ausgabesignal y der Kernfunktion ist über einen deaktivierbaren Treiber mit den bidirektionalen Datenanschlüssen dat des Schaltkreises
verbunden. Das Freigabesignal E des Treibers wird nur aktiviert, wenn das
Schaltkreisauswahlsignal cs und das Ausgabefreigabesignal oe aktiv und das
Schreibsignal wr inaktiv ist:
E = cs ∧ oe ∧ wr
Das Schreibsignal W der Kernfunktion wird nur aktiviert, wenn das Schaltkreisauswahlsignal cs und das Schreibsignal wr des Schaltkreises aktiv ist
(Abb. 4.64):
W = cs ∧ wr
Im nächsten Schritt ist das Zeitverhalten nachzubilden. Aus den im Datenblatt für den Lesezyklus dargestellten Signalverläufen ist ablesbar, dass
die Leseverzögerung tdy ≤ 10 ns und die Lesehaltezeit thy ≥ 2 ns beträgt.
tZO , tOZ
oe
cs
wr
dat
adr
a)
&
&
E
y
W
x
a
Kernfunktion
Leseschaltung
Schreibtreiber
(deaktivierbar)
Spaltenauswahl
Zeilenauswahl
Schaltkreisanschlüsse:
oe Ausgabefreigabesignal
cs Schaltkreisauswahlsignal
wr Schreibsignal
adr Adresssignal
dat bidirektionales Datensignal
Verzögerung des Ausgabetreibers:
tOZ Deaktivierungsverzögerung
tZO Aktivierungsverzögerung
(im Beispiel unten 2 × 4 ns)
signal adr: tUnsigned(17 downto 0);
signal dat, y: std_logic_vector(15 downto 0);
signal n_oe, n_cs, n_wr, W, E: std_logic;
...
W <= not n_cs and not n_wr;
E <= ’X’, not n_oe and not n_cs and n_wr after 4
ram(W=>W, a=>adr, x=>dat, y=>y, thy=>2 ns,
tdy=>10 ns, tsa=>0 ns, tna=>0 ns, twr=>8 ns,
process(oe, y)
begin
if E=’1’ then dat <= y;
elsif E=’0’ then dat <= (others=>’Z’);
else dat <= (others=>’X’);
end if;
b) end process;
–- 1. Gatter
ns; –- 2. Gatter
–- Kernfunktion
tsx=>6 ns);
–- Ausgabetreiber
⇒Web-Projekt: P4.4/IS61.vhdl
Abb. 4.64. Verhaltensmodell eines asynchronen SRAM-Schaltkreises a) Ersatzschaltung aus Kernfunktion und Schnittstellenschaltung b) VHDL-Beschreibung
362
4 Vom Transistor zur Schaltung
Die Aktivierung und Deaktivierung des Ausgabetreibers dauert zwischen null
und 4 ns. Die Adresse benötigt keine Vor- und keine Nachhaltezeit. Für die
Eingabedaten sind eine Vorhaltezeit von tdx ≥ 6 ns und eine Nachhaltezeit
tnx ≥ 0 gefordert. Das Schreibsignal wr muss mindestens für 8 ns aktiv sein
und die Adresse für mindestens 10 ns stabil anliegen. Die Aktivierungs- und
Deaktivierungsverzögerung des Treibers sind in Abb. 4.64 b als Halte- und
Verzögerungszeit des Gatters, das das Freigabesignal E erzeugt, modelliert.
Die übrigen Zeitparameter werden der nebenläufigen Prozedur »ram(...)« aus
Abschnitt 3.4.3, Abb. 3.25 übergeben, die das Verhalten der Kernfunktion
nachbildet. Zum Aufdecken möglicher Modellschwächen sind Testbeispiele aus
dem Datenblatt abzuleiten.
Das entwickelte Schaltkreissimulationsmodell ist noch nicht ganz exakt.
Für die Adresse kontrolliert die Prozedur »ram(...)« nur, dass sie bei einem
Schreibzugriff für die Summe aus der Mindestschreibimpulsbreite, der Adressvorhaltezeit und der Adressnachhaltezeit
twr + tsa + tna = 8 ns + 0 + 0
stabil anliegt. Laut Datenblatt soll sie aber mindestens für 10 ns stabil anliegen. Das erfordert eine kleine Änderung in der Prozedur »ram(...)«. Laut
Simulationsmodell hat das Signal cs dieselbe zeitliche Wirkung auf den deaktivierbaren Ausgabetreiber wie das Signal oe, was auch nicht genau den
Datenblattangaben entspricht. Für unsere Zwecke soll das Simulationsmodell
in Abb. 4.64 b jedoch so genügen, wie es ist.
Speichercontroller
Der Schaltkreis aus dem vergangenen Abschnitt soll in eine synthesefähige
Beschreibung eingebettet werden. Dazu muss er in Register eingerahmt werden, die die Eingabe- und Ausgabesignale abtasten und dabei zeitlich am Takt
ausrichten. Das abgetastete Eingabedatensignal ist über einen deaktivierbaren
Treiber an die bidirektionalen Datenanschlüsse des Schaltkreises anzuschließen. Für die Einstellung der geforderten Zeitversätze und Zeittoleranzfenster
der Steuersignale in Bezug auf die abgetasteten Adress- und Datensignale gibt
es zwei Lösungsansätze:
• Einstellung mit abgestimmten Verzögerungszeiten und
• Erzeugung mit einer sequenziellen Schaltung.
In Abb. 4.65 werden die Steuersignalverläufe mit abgestimmten Verzögerungszeiten eingestellt. Aus den Abtastwerten der externen Steuersignale W (write,
schreiben) und R (read, lesen) werden mit einer kombinatorischen Schaltung
die drei Schaltkreisansteuersignale cs, wr und oe sowie ein Steuersignal EW
für die Aktivierung des Schreibtreibers und ein Freigabesignal ER für das Leseregister erzeugt. Die kombinatorischen Funktionen für die Erzeugung der
fünf Steuersignale sind einfach, aber ihre Gatternachbildungen müssen genau
4.4 Schreib-Lese-Speicher
363
aufeinander abgestimmte Einschalt- und Ausschaltverzögerungen haben. Die
Ausschaltverzögerung der Schaltung für die Bereitstellung des Schreibsignals
wr muss z.B. mindestens so groß wie die Adressverzögerung und seine Einschaltverzögerung darf maximal so groß wie die Adressverzögerung sein. In
dieser Rechnung sind alle Verzögerungen, auch die auf der Baugruppe, zu berücksichtigen. Während eines Adresswechsels zwischen zwei Schreibvorgängen
ist normalerweise das Schreibsignal zu deaktivieren. Der Beispielschaltkreis
hat jedoch eine Adressvorhalte- und eine Adressnachhaltezeit null. Wenn sich
alle Adressbits am Schaltkreis fast gleichzeitig ändern, kann auf die Deaktivierung verzichtet werden. Wie groß »fast gleichzeitig« ist, steht leider nicht im
Datenblatt. Das Zeitfenster dafür ist offenbar sehr klein. Enge Zeittoleranzen
erfordern, auch wenn die Schaltung nur aus wenigen Gattern besteht, einen
professionellen Handentwurf. Für die Synthese der umgebenden Schaltung
sind die manuell gefundene Schaltung sowie ihre Platzierung und Verdrahtung mit Constraints festzuschreiben (vgl. Abschnitt 2.1.5). Der Entwurf ist
viel schwieriger, als es die Schaltung in Abb. 4.65 vermuten lässt.
x
a
W
R
x’
a’
EW
W’
R’
≥1
&
adr RAM- dat
wr Schaltcs kreis
oe
x
ER
y
E
T
a
x
y
W
R
Adresssignal
Eingabedaten
Ausgabedaten
Schreibsignal
Lesesignal
T Takt
EW Freigabesignal für Schreibdaten
ER Übernahmesignal für gelesene Daten
individuell abzugleichende Verzögerung
laufzeitkritische Teilschaltung
Abb. 4.65. Speichercontroller für einen asynchronen Schreib-Lese-Speicher mit individuell angepassten Verzögerungszeiten
Die Alternative zu einem Handentwurf der laufzeitkritischen Schaltungsteile ist die Erzeugung der Steuersignale mit einer sequenziellen Schaltung.
Abbildung 4.66 a zeigt die Prinzipschaltung. Die Adresse und die Daten werden genauso wie in der ersten Lösung abgetastet und die abgetasteten Eingabedaten werden genauso über einen deaktivierbaren Treiber an die bidirektionalen Datenanschlüsse des Schaltkreises angeschlossen. Neu ist der MooreAutomat, der die Steuer- und Freigabesignale erzeugt.
Für den Automatenentwurf sind als erstes die Zeitverläufe der zu erzeugenden Steuersignale zu spezifizieren. In Abb. 4.66 b ist jeder Speicherzugriff
in vier Taktphasen unterteilt. Die abgetastete Adresse a’ soll jeweils in allen vier Phasen stabil anliegen und das Schaltkreisauswahlsignal cs soll in
allen vier Phasen aktiv sein. Um bei einem Schreibzugriff eine ausreichende
364
4 Vom Transistor zur Schaltung
x’
a’
x
a
EE
W
R
a)
T
E
fs
fy
EW
adr RAM- dat
wr Schaltcs kreis
oe
E
ER
Moore-Automat
T
Phase
1
0
Stop W1 W2 W3 W4 L1 L2 L3 L4 Stop
cs
wr
oe
LA1
SA1
a’
bw
Stopp
111 100
tsa
twr
tna
tdy
sonst
br
W1
011 000
R1
011 000
W2
001 010
R2
010 000
W3
001 010
R3
010 000
br
W4
011 100
bw
sonst
1
0
1
0
1
0
EE 10
EW 10
ER 10
b)
x
y
R4
010 101
br
sonst
bw
Übergangsbedingungen:
bw = (W = 1)
br = (W = 0) ∧ (R = 1)
Zusammensetzung des Ausgabevektors:
c)
cs & wr & oe EE & EW & ER
Abb. 4.66. Speichercontroller für einen asynchronen Schreib-Lese-Speicher mit einem Automaten zur Erzeugung der Steuersignale a) Gesamtschaltung b) zu erzeugende Steuersignalverläufe c) Zustandsgraph der Steuerung
Adressvorhalte- und Adressnachhaltezeit zu garantieren, wird das Schreibsignal wr erst einen Takt nach der Adressabtastung aktiviert und einen Takt
vor der nächsten Adressabtastung deaktiviert. Das Freigabesignal EW für den
Schreibtreiber soll erst ab der zweiten Taktphase aktiviert werden, damit der
Ausgabetreiber im RAM-Schaltkreis nach einem Lesezyklus genügend Zeit
hat, sich zu deaktivieren. Das Ausgabefreigabesignal des Speicherschaltkreises oe und das Freigabesignal ER für das Leseregister bleiben während des
gesamten Schreibzugriffs inaktiv. Bei einem Lesezugriff bleiben das Speicherschreibsignal wr und das Freigabesignal EW für den Schreibtreiber durchgängig inaktiv. Das Ausgabefreigabesignal des Schaltkreises oe soll, damit der
Treiber für die zu schreibenden Daten genügend Zeit zur Deaktivierung hat,
erst im zweiten Takt aktiviert werden. Das Freigabesignal ER für das Leseregister ist nur im letzten Takt vor Abschluss der Leseoperation zu aktivieren.
Im nächsten Entwurfsschritt wird aus den Steuersignalverläufen in Abb.
4.66 b der Zustandsgraph in Abb. 4.66 c konstruiert. Nach der Initialisierung
und wenn kein Speicherzugriff erfolgt, soll sich der Automat im Zustand
»Stopp« befinden, in dem alle Steuersignale außer dem Freigabesignal EE
für das Eingaberegister inaktiv sind. Wenn das externe Schreibsignal W im
Stopp-Zustand oder am Ende eines Schreib- oder Lesezylusses aktiv ist, wird
anschließend die Zustandsfolge »W1« bis »W4« durchlaufen, die die Steuersignale für den Schreibvorgang erzeugt. In Analogie dazu wird in diesen
Zuständen, wenn das Schreibsignal W inaktiv und das Lesesignal R aktiv ist,
4.4 Schreib-Lese-Speicher
365
die Zyklusfolge »R1« bis »R4« für die Erzeugung der Steuersignalfolge für
den Lesevorgang durchlaufen. Im letzten Schreib- und im letzten Lesezustand
wird jeweils wie im Stopp-Zustand das Steuersignal EE für die Abtastung der
Eingabeadresse und der Eingabedaten aktiviert, damit sich sofort der nächste
Schreib- oder Lesezyklus anschließen kann.
Der nächste Entwurfsschritt ist die Abschätzung der minimalen Taktperiode. Die kritischste Zeitbedingung für den Beispielschaltkreis ist, dass der
zwei Takte lange Schreibimpuls eine Mindestbreite von twr ≥ 8 ns haben muss.
Daraus folgt für die Taktperiode eine Mindestlänge von TP ≥ 4 ns. Relativ kritisch ist auch die Einhaltung der Datenvorhaltezeit von tsx ≥ 6 ns für die in
Summe mit der Aktivierungsverzögerung des Eingabetreibers auch nur zwei
Taktperioden eingeplant sind. Wenn der Eingabetreiber des zu entwerfenden
Controllers eine längere Aktivierungsverzögerung als 2 ns hat, muss die Taktperiode entsprechend länger als 4 ns gewählt werden.
Der weitere Entwurf vom Zustandsgraphen bis zur fertigen Simulationsund Synthesebeschreibung erfolgt in der bereits mehrfach vorgeführten Weise
und hat Rezeptcharakter (siehe Abschnitt 1.6). Auch wenn die Schaltung in
Abb. 4.66 wesentlich komplizierter aussieht als die in Abb. 4.65, ist die zweite
Schaltung einfacher zu entwerfen. Denn sie ist nicht laufzeitkritisch und damit
synthesefähig. Allerdings ist die zweite Schaltung mit dem Automaten deutlich
aufwändiger und langsamer als die erste.
4.4.2 Mehrportspeicher
Ein zeitgleicher Zugriff auf mehrere Speicherplätze eines Blockspeichers verlangt Zellen, die über mehrere Sätze von Steuerleitungen unabhängig voneinander gelesen und beschrieben werden können. In Abb. 4.67 a ist die 6Transistor-Zelle aus Abb. 4.62 um einen zweiten Port erweitert. Der zweite
Port besteht auf der Zellenebene aus dem zusätzlichen Auswahltransistorpaar
T7 und T8. Jeder Port besitzt eigene Zeilen- und Spaltenauswahlsignale, die
von einer Port-eigenen Ansteuerschaltung erzeugt werden (Abb. 4.67 b). Nach
außen hin verhalten sich die einzelnen Ports eines Mehrportspeichers wie separate Speicher, nur dass der Zugriff auf dieselbe Speichermatrix erfolgt. Ein
s̄1.j s̄2.j
Port1
z2.i
T5
x
T1
T4 T8
x̄
T6
T3
S-Decoder
z1.i
a)
S-Decoder
Z-Decoder
T7 T2
Z-Decoder
r̄2.j r̄1.j
UV
b)
Port2
Abb. 4.67. 2-Port-Speicher a) Speicherzelle b) Gesamtstruktur (S-Decoder –
Schreib-Lese-Steuerung und Spaltenauswahl; Z-Decoder – Zeilenauswahl)
366
4 Vom Transistor zur Schaltung
gleichzeitiges Beschreiben derselben Zelle mit unterschiedlichen Werten invalidiert den gespeicherten Inhalt und ist nach Möglichkeit durch eine geeignete Ansteuerschaltung auszuschließen. Eine typische Anwendung für Mehrportspeicher ist die Kopplung von Rechnern.
Synthesebeschreibungen mit 1-Port- und Mehrportspeichern
Abbildung 4.68 a zeigt noch einmal die synthesefähige Beschreibung für den
1-Port-Speicher aus Abb. 3.26 in Abschnitt 3.4.3. Wenn das Schreibsignal
aktiv ist, wird das adressierte Feldelement beschrieben. Sonst, wenn das Lesesignal aktiv ist, wird der Wert des adressierten Feldelements gelesen. Für
beide Operationen steht maximal die Dauer einer Taktperiode zur Verfügung.
ts
signal RAM is tRAM(0 to 2**a’length - 1);
signal T, W, E: std_logic;
x
signal x, y: tDaten;
a
W
signal a: tAdresse;
E
...
process (T)
T
begin
b)
if rising_edge(T) then
T
if W=’1’ and E=’1’ then
x
RAM(Int(a)) <= x;
a
elsif E=’1’ then
W
y <= RAM(Int(a));
E
end if;
y
end if;
a) end process;
c)
th , td
&
x RAM y
a
w
x
E
y
&
Schreiben Lesen Pause
1
0
1
0
1
0
ts
th
td
Abb. 4.68. Synthesebeschreibung eines 1-Port-Speichers a) VHDL-Beschreibung b) erforderliche Beschaltung der Kernfunktion c) Ansteuerung
Abbildung 4.68 b zeigt die zugehörige Beschaltung der Kernfunktion. Die
Adress-, Steuer- und Eingabedatensignale müssen, damit der gesamte Blockspeicher nach außen laufzeitrobust ist, abgetastet auf die Kernfunktion geführt werden. Ein nachgeschaltetes Ausgabe-Latch lässt die Lesewerte bei
einem Lesezugriff passieren und hält die Ausgabe während der Schreibzugriffe
konstant. Die internen Verzögerungszeiten sind so laufzeitkritisch, dass der
Speicher gemeinsam mit seiner Schnittstelle von der Synthese nur als fertig
vorentworfener und verdrahteter Block verwendet werden kann. Die Vorhalteund die Nachhaltezeiten zur aktiven Taktflanke für die Adresse, die Eingabedaten und die Steuersignale sind die des eingangsseitigen Abtastregisters und
damit sehr klein. Die Haltezeit th und die Verzögerungszeit td eines Lesezugriffs sind etwas größer als die der Speicherkernfunktion und damit sehr groß
(Abb. 4.68 c).
4.4 Schreib-Lese-Speicher
367
Die Synthesebeschreibung eines Mehrportspeichers ist sehr ähnlich zu der
eines 1-Port-Speichers. Die Speichermatrix und die einzelnen Schreib- und
Lesezugriffe werden genauso beschrieben. Der einzige Unterschied ist, dass
in der Beschreibung eines Mehrportspeichers die Möglichkeit existiert, dass
auf mehrere Speicherelemente zeitgleich zugegriffen wird. Schaltungstechnisch
ist bei einem synchronen Mehrportspeicher jeder Port wie der des 1-PortSpeichers in Abb. 4.68 b zu beschalten.
Im nachfolgenden Beschreibungsbeispiel wird in jedem Takt auf den Speicherplatz mit der Adresse a geschrieben und gleichzeitig der Inhalt der Vorgängeradresse gelesen:
process (T)
begin
if rising_edge(T) then
RAM(Int(a)) <= x;
y <= RAM(Int(a) - 1);
end if;
end process;
Das erfordert einen 2-Port-Speicher. Eine weitere Leseoperation würde die erforderliche Port-Anzahl auf drei erhöhen. Auch wenn zwei zeitlich nicht zueinander ausgerichtete Prozesse auf dasselbe Bitvektorfeld schreibend oder lesend
zugreifen, muss der Speicher mindestens zwei getrennte Ports haben. Umgekehrt ist es eine wichtige Optimierungsrichtlinie, in der Synthesebeschreibung
die maximal mögliche Anzahl der zeitgleichen Speicherzugriffe, die die Portanzahl festlegt, so gering wie möglich zu halten.
FIFO mit 1- und 2-Port-Speicher
Abbildung 4.69 zeigt eine Schaltung zur Rechnerkopplung mit einem FIFOSpeicher12 . Das Initialisierungssignal I stellt den Anfangszustand »FIFO leer«
her. Rechner 1 schreibt Daten in den FIFO und Rechner 2 holt die Daten in
derselben Reihenfolge aus dem FIFO ab.
In Abschnitt 3.4.4 wurde ein FIFO als ein Datenobjekt aus einem Blockspeicher, einem Lesezeiger, einem Schreibzeiger, einem Flag für »voll«, einem
Flag für »leer« und je einer Bearbeitungsmethode zum Initialisieren, zum
Schreiben eines Datenobjekts und zum Lesen eines Datenobjekts modelliert.
Die Methode »init« setzt die beiden Zeiger auf null, das Flag »leer« auf true
und das Flag »voll« auf false. Die Schreibmethode wird nur ausgeführt, wenn
der FIFO nicht voll ist. Sie löscht das Flag »leer«, schreibt die Daten auf den
nächsten freien Platz und stellt den Schreibzeiger weiter. Die Lesemethode
entnimmt, wenn der FIFO nicht leer ist, den ältesten Wert und stellt den
Lesezeiger weiter:
12
Ein FIFO-Speicher bildet eine Warteschlange nach, in die nacheinander Daten geschrieben und aus der die Daten in derselben Reihenfolge wieder abgeholt werden
können (vgl. Abschnitt 3.4.4).
368
4 Vom Transistor zur Schaltung
Rechner
1
a)
x
y
W
R
I
leer
voll
I
T
x FIFO y
W
leer
voll
R
I
Eingabedaten
Ausgabedaten
Schreibsignal
Lesesignal
Initialisierungssignal
Flags für leer und voll
Rechner
2
T
I
W
R
x
1
0
1
0
1
0
1
0
w1 w2 w3
(voll) 4
3
Füllstand 2
1
(leer) 0
b)
w4 w5 w6
w1 w2
y
w3
w3
w3 w4 w4
w1
w1 w2 w2
w3 w4 w5 w5
w1 w2 w3 w3 w3 w4 w5 w6 w6
Abb. 4.69. FIFO-Speicher a) Einsatz zur Kopplung von zwei Rechnern b) Funktionsweise an einem Beispielablauf
–- Package-Vereinbarungen für ein FIFO-Modell
constant N_Adr: positiv := ...; –- Anzahl der Adressbits
subtype tAdrIdx is range 0 to 2**N_Adr - 1;
subtype tDaten is ...;
type tSpeicher is array (tAdrIdx) of tDaten;
type tFIFO is record
Speicher: tSpeicher;
–- Speichermatrix
sz, lz : tAdrIdx;
–- Schreib- und Lesezeiger
leer, voll : boolean;
–- Statussignale
end record;
procedure init(signal fifo: inout tFIFO);
procedure write(x: tDaten; signal fifo: inout tFIFO);
procedure read(signal y: out tDaten; fifo: inout tFIFO);
⇒WEB-Projekt: P3.4/FIFO_pack.vhdl
Im folgenden Verhaltensmodell wird der FIFO in jedem Taktschritt genau
wie in Abb. 4.69 nur entweder beschrieben oder gelesen:
signal x, y: tDaten;
signal fifo: tFIFO;
...
if init=’1’ then init(fifo);
elsif rising_edge(T) then
if
W=’1’ and not voll then write(x, fifo);
elsif R=’1’ and not leer then read(y, fifo);
end if;
end if;
Da in keinem Takt auf mehrere Speicherplätze zugegriffen wird, würde die
Synthese für den Blockspeicher des FIFO-Objekts einen 1-Port-Speicher wählen. Bei einer geringfügigen Modifikation, die ein zeitgleiches Lesen und Schreiben nicht mehr ausschließt,
4.4 Schreib-Lese-Speicher
369
...
elsif rising_edge(T) then
if W=’1’ and not voll then write(x, fifo); end if;
if R=’1’ and not leer then read(y, fifo); end if;
end if;
muss die Synthese einen synchronen 2-Port-Speicher einsetzen.
4.4.3 Assoziativspeicher
Ein Assoziativspeicher ist ein normal beschreibbarer und lesbarer Speicher
mit einer Zusatzfunktion für den parallelen Vergleich. Bei der Vergleichsoperation werden die Eingabedaten in einem Schritt mit den gespeicherten Bitmustern aller Speicherzeilen verglichen. Abbildung 4.70 zeigt die Schaltung
einer Zelle. Die Transistoren T1 bis T6 bilden eine normale RAM-Zelle und
die Transistoren T7 bis T10 bilden die Schaltung für den bitweisen Vergleich.
Bei der Vergleichsoperation werden die Spaltenleitungen wie beim Schreiben
angesteuert:
(4.37)
r̄j = dj ; s̄j = d¯j
(dj – Bitwert für Spalte j). Die Zeilenauswahlsignale bleiben jedoch alle inaktiv, so dass der Zelleninhalt nicht verändert wird. Das Netzwerk aus den
Transistoren T7 bis T10 hat die Funktion
fij = (r̄j ∧ x̄ij ) ∨ (s̄j ∧ xij )
"
= (dj ∧ x̄ij ) ∨ d¯j ∧ xij
(4.38)
Die Parallelschaltung der beiden Transistorpaare sperrt genau dann, wenn der
Zellenwert mit dem Eingabewert übereinstimmt. Die Vergleichsschaltungen aller Spalten j einer Zeile i sind parallel geschaltet und damit ODER-verknüpft:
d¯j
dj
UV
vi
d¯j+1
dj+1
r̄j
s̄j
r̄j+1
s̄j+1
H
T8
T5 T7
xij
T2
T4
T10
xi,j+1
T6
x̄ij
T1
T3
x̄i,j+1
T9
zi = 0
H
vi+1
xi+1,j
x̄i+1,j
xi+1,j+1
x̄i+1,j+1
Abb. 4.70. Aufbau der Speichermatrix eines Assoziativspeichers
370
4 Vom Transistor zur Schaltung
fi =
NS
_
fij
(4.39)
j=1
(NS – Spaltenanzahl). Das Gesamtnetzwerk einer Zeile i ist genau dann gesperrt (fi = 0), wenn die Eingabebits aller Spalten übereinstimmen. Ein PullUp-Element erzeugt in diesem Fall den Vergleichswert vi = 1. Die Gesamtausgabe besteht in der Regel aus zwei Informationseinheiten. Das ist zum einen
ein binäres Signal »hit«, das aktiviert wird, wenn das Suchmuster im Speicher
steht, und zum anderen die Adresse der ersten Zeile, in der das Suchmuster
gefunden wird.
Für die Modellierung eines synchronen Assoziativspeichers bietet sich genau wie für den FIFO im Vorabschnitt eine objektorientierte Modellierung
an. Das Modell der Speichermatrix und die Schreib- und die Lesemethode
unterscheiden sich nicht von der eines einfachen Schreib-Lese-Speichers und
seien wie die in Abschnitt 3.4.3 definiert:
subtype tDaten is std_logic_vector(... downto 0);
type tMem is array (natural range <>) of tDaten;
subtype tAdr is tUnsigned(... downto 0);
function read(Mem: tMem; adr: tAdr) return tDaten;
procedure write(x: tDaten, adr: tAdr,
signal Mem: inout tMem);
Zusätzlich benötigt das Modell eines Assoziativspeichers eine Suchmethode
zur Bestimmung der Adresse der ersten Speicherzeile, in der der Eingabewert
steht:
procedure search(x: tDaten; signal adr: out tAdr;
signal hit: out std_logic; signal Mem: inout tMem) is
begin
for idx in Mem’range loop
if Mem(idx)=x then
hit <= ’1’;
adr <= to_tUnsigned(idx, adr’length);
return;
end if;
end loop;
hit <= ’0’;
adr <= (others=>’0’);
⇒WEB-Projekt: P4.4/AsRAM_pack.vhdl
end procedure;
Auch wenn der Vergleich in der Hardware parallel erfolgt, muss er im Simulationsmodell sequenziell nachgebildet werden.
4.4 Schreib-Lese-Speicher
371
4.4.4 Dynamische Speicher (DRAM)
Dynamische Speicher (DRAM – dynamic random access memory) besitzen
die kleinsten Speicherzellen und die höchste Speicherdichte. Jede Speicherzelle
besteht aus einer winzigen Kapazität CS , die über einen NMOS-Transistor mit
einer Bitleitung verbunden ist (Abb. 4.71 a). Der Preis des einfachen Aufbaus
und des geringen Flächenbedarfs der Zellen ist eine deutlich kompliziertere
Funktionsweise und Ansteuerung.
Auswahlleitung x
Bitleitung
a)
uCS
CS
ux
D∗
b)
UV
CS
S∗
uGS
uCS
c)
D∗
S∗
UV
uCS
∗
Der Source ist bei einem NMOS-Transistor immer der Kanalanschluss mit
dem niedrigeren und der Drain der mit dem höheren Potenzial.
Abb. 4.71. a) DRAM-Zelle b) Schreiben einer »0« c) Schreiben einer »1«
Beschreiben einer Speicherzelle
Zum Beschreiben der Speicherzelle wird auf der Bitleitung die Spannung zur
Darstellung des Logikwertes angelegt
(
0
für x = 0
ux =
(4.40)
UV für x = 1
und der Transistor eingeschaltet. Beim Schreiben einer »0« arbeitet der Transistor ganz normal als Low-Side-Schalter (Abb. 4.71 b). Der Source, d.h. der
Kanalanschluss mit dem niedrigeren Potenzial, ist der Leseleitungsanschluss
und hat das Potenzial 0 V. Die Lesegeschwindigkeit errechnet sich nach demselben Modell wie die Ausschaltzeit taus eines Inverters (Gleichung 4.20). Beim
Aufladen der Lastkapazität hat die Kapazitätsseite des Kanals das niedrigere
Potenzial und bildet den Source. Die Gate-Drain-Spannung ist null, so dass
der Transistor während des gesamten Aufladevorgangs im Abschnürbereich
arbeitet (Abb. 4.71 c). Die Spannung über der Speicherkapazität strebt nicht
gegen die Versorgungsspannung, sondern nur gegen
uCS ≤ UV − UTN
(4.41)
(UTN – Einschaltspannung des Auswahltransistors). Der Aufladestrom ist
deutlich kleiner als beim Aufladen über einen PMOS-Transistor mit vergleichbaren Parametern, so dass das Schreiben einer »1« vergleichsweise lange dauert [30].
372
4 Vom Transistor zur Schaltung
Lesen
Der Lesevorgang ist noch komplizierter. Vor dem Lesen wird die Ladung auf
der Bitleitung gelöscht:
(−)
QCx = Cx · Ux(−) = 0
Die Speicherkapazität hat vor dem Lesen die Ladung
(
0
für eine gespeicherte »0«
(−)
QCS = CS ·
UV − UTN für eine gespeicherte »1«
(4.42)
Anschließend wird der Transistor geöffnet. Es kommt zum Ladungsausgleich.
Die gespeicherte Ladung geht dabei nicht verloren, sondern verteilt sich auf
beide Kapazitäten:
(−)
QCS + QCx = QCS
(4.43)
Im stationären Zustand nach dem Einschalten des Transistors sind die Spannungsabfälle über beiden Kapazitäten gleich:
(+)
UCS = Ux(+)
(4.44)
Die Ausgabespannung auf der Bitleitung strebt gegen
(
0
für eine gespeicherte »0«
CS
(+)
·
Ux =
CS + Cx
UV − UTN für eine gespeicherte »1«
(4.45)
Die Kapazität Cx der Bitleitung ist um mindestens zwei Zehnerpotenzen größer als die Speicherkapazität CS , so dass der Potenzialunterschied zwischen
einer gelesenen »0« und einer gelesenen »1« nur wenige Millivolt beträgt (Abb.
4.72 a). Die Auswertung der Lesepotenziale auf den Bitleitungen erfolgt nach
den Grundprinzipien des Analogentwurfs »Symmetrie und Kompensation«.
In einer vollkommen symmetrischen Anordnung werden immer paarweise zwei
Ladungsausgleich
UV
uCS
a)
CS
Cx
Lese-Schreib-Steuerung
Zwischenspeicher
Leseverstärker
ux (wenige
Millivolt)
xj
xref
zi
Leseablauf:
Vorladen (L = 1)
Ladungsausgleich (zi = 1)
Vergleich und Speichern
Zurückschreiben
Cs
b)
1: positiv
0: negativ
Cx
L
1
Cs
2
Cx
Abb. 4.72. Lesen einer DRAM-Zelle a) Ersatzschaltung für den Ladungsausgleich b) symmetrische Anordnung zur Auswertung der Lesepotenziale
4.4 Schreib-Lese-Speicher
373
Zellen gelesen, eine richtige und eine aufgeladene Dummy-Zelle mit der halben
Kapazität. Wenn nach dem Ladungsausgleich das Potenzial der Leseleitung
der richtigen Zelle größer als das der Leseleitung der Dummy-Zelle ist, wird
eine »1« erkannt, sonst eine »0« (Abb. 4.72 b).
Beim Lesen wird der gespeicherte Wert zerstört, so dass jede Zelle nach
dem Lesevorgang neu beschrieben werden muss. Der komplette Lesezyklus
besteht praktisch aus vier Schritten:
• Entladen der Leseleitungen und Aufladen der Dummy-Zellen,
• Ladungsausgleich,
• Bestimmung der Logikwerte auf den Leseleitungen und Übernahme in den
Zwischenspeicher und
• Zurückschreiben der gelesenen Inhalte.
Ein DRAM hat noch mindestens eine weitere Betriebsart, das Auffrischen
(engl. refresh). Die Daten in den Speicherzellen bleiben nur wenige Millisekunden gültig (vgl. Abschnitt 4.3.1). Deshalb ist es notwendig, dass jede
Speicherzelle innerhalb von wenigen Millisekunden einmal gelesen und der gelesene Inhalt zurückgespeichert wird. Damit das zeitlich möglich ist, erfolgt
das Auffrischen und damit auch das Lesen nicht zellen-, sondern zeilenweise.
Die Zeilenanzahl bestimmt die Bitleitungskapazität Cx . Sie darf, damit die Potenzialunterschiede auf den Bitleitungen beim Lesen noch sicher ausgewertet
werden können, die Größenordnung Hundert bis Tausend nicht überschreiten. Dadurch gilt für alle DRAMs unabhängig von ihrer Organisation und
Speichergröße, dass mindestens alle Hundert bis Tausend Speicherzugriffe ein
Auffrischzyklus einzufügen ist.
Ansteuerung
DRAMs haben heute praktisch alle eine programmierbare synchrone Schnittstelle, die die komplexen internen Zeitabläufe verbirgt. Die Ansteuerung erfolgt über Befehle. Abbildung 4.73 zeigt einen vereinfachten Operationsablaufgraphen für die Ansteuerung eines DDR2-RAMs. Nach Zuschalten der Versorgungsspannung ist die Schnittstellenschaltung des Speichers zu initialisieren,
bevor sie für Datenzugriffe bereit ist. Das beinhaltet die Initialisierung der Regelkreise für die interne Takterzeugung und dauert einige Hundert Takte (vgl.
Abschnitt 4.3.6). Im Zustand »bereit« akzeptiert die Schnittstellenschaltung
zwei Kommandos:
• ACT (activate): Lesen einer Speicherzeile in den Zwischenpuffer und
• SFR (refresh): Lesen, Verstärken und Zurückschreiben.
Das Activate-Kommando benötigt zusätzlich die Zeilenadresse, das RefreshKommando entnimmt die Zeilenadresse einem internen Zähler, der nach jedem Refresh weitergeschaltet wird. Beide Operationen dauern mehrere Takte.
374
4 Vom Transistor zur Schaltung
Anfangsinitialisierung
bereit
ACT
RD
SFR
Zeile auffrischen
Zeile gelesen
RD
WR
WR
Schreibzyklus
Lesezyklus
RDA
letzter
Lesezyklus
PR
WRA
letzter
Schreibzyklus
Zeile zurückspeichern, Vorladen(1)
SFR
ACT
RD
RDA
WR
WRA
PR
(1)
Zeile auffrischen
Zeile aktivieren
Lesen
abschließendes Lesen
Schreiben
abschließendes Schreiben
Seite schließen
Vorbereitung für das
Lesen der nächsten Zeile
Zustandsübergang ohne
Befehl
Abb. 4.73. Vereinfachter Operationsablaufgraph für die Ansteuerung eines DDR2SDRAMs
Im Zustand »Zeile gelesen« wird nur noch mit dem Zwischenpuffer gearbeitet. Dieser verhält sich ähnlich wie ein wahlfrei adressierbarer Schreib-LeseSpeicher. Wenn eine Zeile im Zwischenpuffer steht, kann der Speicherschaltkreis folgende Kommandos ausführen:
• RD, RDA: Lesen, abschließendes Lesen,
• WR, WRA: Schreiben, abschließendes Schreiben und
• PR (precharge) Seite schließen.
Mit den Schreib- und Lesebefehlen ist zusätzlich die Spaltenadresse zu übergeben. Nach den Abschlussoperationen RDA, WRA und PR werden die Werte
aus dem Zwischenspeicher zurück in die Speicherzeile geschrieben, die Bitleitungen entladen und die Dummy-Zellen aufgeladen. Danach ist der Schaltkreis
wieder für eine Auffrischoperation oder die Aktivierung einer anderen Zeile
bereit.
Die Lese- und Schreibzugriffe auf einen DRAM erfolgen in der Regel Burstorientiert. Bei jedem Zugriff werden die Daten für z.B. vier oder acht aufeinanderfolgende Adressen übertragen. In Abb. 4.74 wird zuerst mit dem ActivateBefehl und der Übergabe der Zeilenadresse der Lesevorgang einer Speicherzeile gestartet. Das dauert typisch zwei bis drei Takte. Anschließend wird mit
einem Lesebefehl und der Übergabe einer Spaltenadresse eine Leseoperation
gestartet. Danach vergehen weitere zwei bis drei Takte, bevor der Schaltkreis
eine Datenfolge schickt. Die Daten wechseln sowohl nach der fallenden als
auch nach der steigenden Flanke, so dass in jeder Taktperiode zwei Datenworte übertragen werden. Letzterem verdankt das Schnittstellenprotokoll seinen Namen (DDR – double date rate). Der Zeitablauf einer Schreiboperation
ist ähnlich. Nach Übersenden des Schreibkommandos und der Spaltenadresse
vergeht eine definierte Anzahl von Takten, nach denen die zu schreibenden
Daten mit der doppelten Taktrate auf den Datenbus zu legen sind.
4.5 Festwertspeicher
0
Takt
Befehl
ACT
Adresse
za
1
2
3
NOP
RD
5
6
NOP
sar
tACT
Daten
4
7
WR
8
9
375
10
NOP
saw
tRD
Z
NOP kein Befehl (no operation)
za Zeilenadresse
sar Spaltenadresse Leseoperation
tWR
o0 o1 o2 o3
i0 i1 i2 i3
saw Spaltenadresse Schreiboperation
oi gelesene Daten
ii zu schreibende Daten
Abb. 4.74. Datenaustausch über eine DDR2-Schnittstelle
Ein einzelner Lese- oder Schreibzugriff auf einen DRAM-Schaltkreis dauert mehrere Takte, aber es ist im günstigsten Fall fast möglich, in jedem Takt
zwei Datenworte zu übertragen. Der hohe Datendurchsatz lässt sich jedoch
nur nutzen, wenn die Daten in größeren Blöcken gelesen und gespeichert werden. Schaltungen mit DRAMs als Speicher für große Datenmengen besitzen
deshalb meist schnelle Zwischenspeicher, die aus den DRAM-Schaltkreisen
blockweise geladen und deren Daten einzeln weiterverarbeitet werden. Umgekehrt werden die Daten in den schnellen Zwischenspeichern einzeln berechnet
und blockweise in die DRAMs zurückgeschrieben. In Rechnern sind diese Zwischenspeicher die Cache-Speicher. Weiterführende und ergänzende Literatur
siehe [36, 47].
4.5 Festwertspeicher
Festwertspeicher, abgekürzt ROM (read only memory), können nur einmal
oder nur mit großem Zeitaufwand beschrieben werden und behalten ihre Daten
auch ohne Versorgungsspannung über Jahre. Das Speicherelement ist heute
meist ein einzelner Transistor, der entweder ein- und ausschaltbar ist oder
nur einen der beiden Schaltzustände besitzt. Bei einem NOR-ROM sind die
Transistoren, die die Speicherzellen bilden, parallel geschaltet. Die deaktivierten Transistoren schalten nicht ein. Die Zeilenauswahlschaltung steuert pro
Spalte nur einen Transistor mit »1« und alle anderen mit »0« an. Die gesamte Parallelschaltung ist leitend, wenn der ausgewählte Transistor einschaltet.
Die Pull-Up-Elemente der Spalten wandeln die Schaltzustände in Logikwerte
um (Abb. 4.75). Es gibt noch weitere Organisationsformen.
Die Deaktivierung der Transistoren kann bei der Herstellung oder beim
Anwender erfolgen, nur einmal oder mehrmals möglich sein etc. [30]. Das Verhaltensmodell eines Festwertspeichers ist eine initialisierte Bitvektor-Konstante, deren Elemente mit der Adresse als Index gelesen werden (vgl. Abschnitt
3.4.3). Die Zugriffszeit ist wie bei anderen Blockspeichern um Zehnerpotenzen größer als die Verzögerung eines Logikgatters. Denn auch nur lesbare
376
4 Vom Transistor zur Schaltung
Spaltenauswahl und
Pull-Up-Elemente
a
T1.1 Z
T1.2 Z
T1.3 Z
T2.1{0,Z}
T2.2{0,Z}
T2.3{0,Z}
T3.1 Z
T3.2 Z
T3.3 Z
0
a
1
0
a)
a
Zeilenauswahl
Zeilenauswahl
Spaltenauswahl und
Pull-Up-Elemente
H
H
H
T1.1
T1.2
T1.3
T2.1
T2.2
T2.3
T3.1
T3.2
T3.3
b)
progr. Transistoren
Adresse
Polysilizium-Streifen
n+ -Gebiet
Metallleiterbahn
Durchkontaktierung
Abb. 4.75. Festwertspeicher a) Schaltung b) geometrische Anordnung
Speicher besitzen Zeilen- und Spaltenleitungen mit großen Lastkapazitäten,
die von verhältnismäßig schmalen Transistoren angesteuert werden.
4.6 Programmierbare Logikschaltkreise
Ein programmierbarer Logikschaltkreis besteht aus programmierbaren Logikblöcken, programmierbaren Verbindungsnetzwerken und programmierbaren
Eingabe-Ausgabe-Schaltungen (Abb. 4.76). Größere programmierbare Logikschaltkreise enthalten zusätzlich konfigurierbare Taktversorgungsschaltungen,
Blockspeicher, Rechenwerke und Prozessorkerne. Die Funktion wird über Konfigurationsspeicher festgelegt. Kostengünstige programmierbare Logikschaltkreise können inzwischen Schaltungen nachbilden, die in nicht programmierbaren Schaltkreisen aus Millionen von Transistoren bestehen. Eingesetzt werden
programmierbare Logikschaltkreise in Prototypen, Kleinserien, studentischen
Praktika und auch zunehmend, um Hardware umprogrammieren zu können.
IO
PLB
PLB
PLB
IO
IO
PLB
PLB
IO
programmierbarer
Logikblock
programmierbares
Verbindungsnetzwerk
programmierbare Eingabe-Ausgabe-Schaltung
Abb. 4.76. Grundstruktur eines programmierbaren Logikschaltkreises
4.6 Programmierbare Logikschaltkreise
377
4.6.1 Programmierbare Tabellenfunktionen
Eine programmierbare Tabellenfunktion ordnet jedem Eingabewert einen individuell einstellbaren Ausgabewert zu. Auf diese Weise lässt sich jede kombinatorische Funktion nachbilden. Die Schaltung ähnelt einem Speicher mit
wahlfreiem Zugriff, einem Festwertspeicher oder einem RAM. Der Zeilendecoder – eine UND-Matrix – aktiviert für jede Eingabevariation genau eine
der 2n Zeilenauswahlsignale. Die Zeilenauswahlsignale werden als Produktterme bezeichnet. Die ODER-Matrix, die für jedes Ausgabebit auswählt, bei
welchen aktivierten Produkttermen eine »1« ausgegeben wird, ist programmierbar (Abb. 4.77).
xn−1
x2 x1 x0
2n Produktterme
···
UND-Matrix
ODER-Matrix
(1 aus 2n - Decoder) · · · (programmierbar)
ym−1
···
y2 y1 y0
Abb. 4.77. UND-ODER-Matrix zur Programmierung von Tabellenfunktionen
Abbildung 4.78 zeigt eine mögliche Realisierung. Die schwarzen Querstriche an den Kreuzungspunkten der Zeilen- und Spaltenleitungen in der UNDMatrix sind normale NMOS-Transistoren, die bei einer »1« am Gate einschalten. An den anderen Kreuzungspunkten befindet sich entweder kein oder ein
deaktivierter Transistor, der auch bei einer »1« am Gate ausgeschaltet bleibt
(vgl. Abschnitt 4.5). Das PMOS-Netzwerk ist durch Pull-Up-Elemente ersetzt.
Die Treiber zwischen den Ausgängen der UND-Matrix und den Eingängen
der ODER-Matrix sind Puffer zur Verringerung der Verzögerungszeiten (vgl.
Abschnitt 4.2.7). Die ODER-Matrix besteht aus programmierbaren Transistoren. Um bei der Auswahl einer Zeile am Ausgang eine »0« auszugeben, ist
x2
x1
x0
ODER-Matrix
H
H
H
p0 = x̄2 x̄1 x̄0
H
p1 = x̄2 x̄1 x0
H
···
H
···
p2 = x̄2 x1 x̄0
···
p7 = x2 x1 x0
UND-Matrix
y 1 = p0 ∨ p2
y 0 = p0 ∨ p7
H
Pull-Up-Element
Treiber
normaler
Transistor
programmierbarer
Transistor
ständig gesperrt
einschaltbar
Abb. 4.78. Logikschaltung mit programmierter ODER-Matrix
378
4 Vom Transistor zur Schaltung
der zugeordnete Transistor zu deaktivieren. Die Inverter an den Ausgängen
bewirken, dass bei einem eingeschalteten (ausgewählten, nicht deaktivierten)
Transistor eine »1« ausgegeben wird.
Eine Tabellenfunktion mit n Eingängen und m Ausgängen benötigt m · 2n
Programmierelemente. Eine einzelne Tabellenfunktion ist entsprechend nur
für die Nachbildung von Schaltungen mit wenigen Eingängen geeignet. Größere Schaltungen werden aus mehreren Tabellenfunktionen zusammengesetzt.
Das erfordert zusätzlich ein programmierbares Verbindungsnetzwerk. Dieses
ist eine Matrix aus deaktivierbaren Treibern oder Transfergattern mit Programmierstellen an den Steuereingängen. Abbildung 4.79 zeigt als Beispiel die
Aufspaltung der fünfstelligen Logikfunktion
(4.46)
y = x1 x2 (x3 ∨ x4 ∨ x5 )
in zwei kleinere Tabellenfunktionen mit je nur drei Eingängen:
Tabellenfunktion 1 : z = x3 ∨ x4 ∨ x5
Tabellenfunktion 2 : y = x1 x2 z
(4.47)
Bei der Technologieabbildung mit Tabellenfunktionen als Bausteine werden
die minimierten logischen Ausdrücke oder Entscheidungsdiagramme in Teilfunktionen mit der Eingangsanzahl des Tabellentyps und einem Ausgang aufgeteilt.
x3
x4
x5
Tabellenfunktion 1
z = x3 ∨ x4 ∨ x5
x3
x4
x5
x1
x2
y
x5 x4 x3
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
z
0
1
1
1
1
1
1
1
Tabellenfunktion 2
y = x1 x2 z
z
Verdrahtungskanal
genutzte Verbindung
z
x1
x2
x2 x1
0 0
0 0
0 1
0 1
1 0
1 0
1 1
1 1
z
0
1
0
1
0
1
0
1
y
0
0
0
0
0
0
0
1
y
programmierbare Verbindung
programmierte Verbindung
Abb. 4.79. Programmierte Logikschaltung mit zwei Tabellenfunktionen
4.6.2 Programmierbare UND-Matrix
Statt der ODER-Matrix kann auch die UND-Matrix programmierbar ausgeführt sein. Die ODER-Matrix ist dann die ODER-Verknüpfung aller Pro-
4.6 Programmierbare Logikschaltkreise
379
duktterme (Abb. 4.80). Die nachzubildende Funktion wird mit Hilfe von KVDiagrammen oder des Verfahrens von Quine und McCluskey minimiert (vgl.
Abschnitt 2.2). Die begrenzende Ressource für die Größe der programmierbaren Funktionen ist hier die Eingangsanzahl der UND-Matrix (Größenordnung 8 . . . 16) und die maximale Anzahl der Produktterme (Größenordnung
4 . . . 16).
xn−1
x2
x1
...
H
H
x0 ODER-Verknüpfung
aller Produktterme
H
p0 = x̄2
H
Treiber
normaler
Transistor
p1 = x̄n−1 x̄0
H
p2 = x0
H
Pull-Up-Element
p3 = x̄n−1 x2 x0
programmierbare
UND-Matrix
y = p3 ∨ p 2 ∨ p1 ∨ p0
programmierbarer
Transistor
ständig gesperrt
einschaltbar
Abb. 4.80. Logikschaltung mit programmierter UND-Matrix
4.6.3 Weitere programmierbare Elemente
Eine typische Erweiterung einer Logikfunktion mit programmierbarer UNDMatrix ist eine programmierbare Ausgabeinvertierung. Sie besteht aus einem
EXOR-Gatter mit einer Programmierstelle am zweiten Eingang (Abb. 4.81).
Bei einer programmierten »0« liefert die EXOR-Verknüpfung den Wert selbst
und bei einer »1« den invertierten Wert der programmierten Logikfunktion.
Auf diese Weise kann die nachzubildende Funktion wahlweise nach den Nullen
oder Einsen entwickelt werden (vgl. Abschnitt 2.2.4).
Logikschaltung
mit programmierter UND-Matrix
Programmierstelle zur
Ausgabeinvertierung
=1
x
I
0
1
Programmierstelle
zur Überbrückung
Speicherzelle
programmierbarer Takt- und
Initialisierungsanschluss
Abb. 4.81. Erweiterte programmierbare Funktionseinheit
Digitale Schaltungen benötigen immer eine größere Anzahl von Speicherzellen für die Abtastung und Zwischenspeicherung von Daten. In der üblichen
Schaltungsarchitektur ist hinter jeder programmierbaren Logikfunktion eine
380
4 Vom Transistor zur Schaltung
überbrückbare taktflankengesteuerte Speicherzelle angeordnet, die bei Bedarf
in den Signalfluss eingefügt und mit Steuersignalen verbunden werden kann.
Konfigurierbare Blockspeicher haben eine bestimmte Speicherkapazität und
eine bestimmte Portanzahl. Konfigurierbar sind z.B. die genutzte Datenbreite, die genutzte Speichertiefe und die Anzahl der genutzten Ports. Bei konfigurierbaren Taktversorgungsschaltungen mit Phasenregelkreisen sind die Teilerverhältnisse und die Phasenverschiebungen der Ausgabetakte einstellbar
(vgl. Abschnitt 4.3.6). Bei konfigurierbaren Rechenwerken und Prozessorkernen gibt es Bitbreitenoptionen und die Möglichkeiten, nur Teile davon zu
nutzen.
4.6.4 Zusammenfassung
Programmierbare Logikschaltkreise bestehen aus programmierbaren Logikblöcken, programmierbaren Verbindungsnetzwerken, programmierbaren Eingabe-Ausgabe-Schaltungen und weiteren programmierbaren Elementen wie
überbrückbaren Speicherzellen, programmierbaren Taktversorgungsschaltungen und programmierbaren Blockspeichern. Für sie wird ein Schaltungsentwurf nicht in Fertigungs-, sondern in Konfigurationsdaten übersetzt, mit denen die einzelnen Konfigurationsbits – Tabellenwerte für Logikfunktionen,
Multiplexerauswahlwerte für die Überbrückung oder Einfügung von Speicherzellen etc. – programmiert werden. Auf diese Weise lässt sich die Funktion
von Hardware genauso schnell und unkompliziert ändern wie die von Software. Weiterführende und ergänzende Literatur siehe [14, 18, 31, 43].
5
Komplexe Beispielentwürfe
In den vergangenen Kapiteln wurde gezeigt, wie die unterschiedlichen Bestandteile einer digitalen Schaltung realisiert, modelliert und simuliert werden. Dieses Kapitel führt anhand von drei Beispielen in den Entwurf komplexer Systeme ein. Zuvor werden zwei strukturbestimmende Aspekte für die
Nachbildung rechenzeitintensiver Algorithmen in Hardware behandelt.
5.1 Pipeline-Verarbeitung und Speicherengpass
Eine wesentliche Zielgröße einer digitalen Schaltung ist ihre Verarbeitungsleistung. Sie wird durch die Anzahl der Operationen, die pro Zeit fertiggestellt
werden, beschrieben. Um die Verarbeitungsleistung über die der bisher betrachteten sequenziellen Verarbeitung zu erhöhen, gibt es zwei Möglichkeiten:
• Parallelverarbeitung mit mehr Hardware und
• Pipeline-Verarbeitung.
Die Pipeline-Verarbeitung ist eine Art zeitversetzte Parallelverarbeitung, bei
der statt zusätzlicher Hardware die vorhandene Hardware besser ausgelastet
wird. Es genügt dabei jedoch nicht, nur die Verarbeitungswerke zu betrachten.
Denn den Engpass bilden in der Regel die Blockspeicher, aus denen die zu verarbeitenden Eingabedaten bereitgestellt und in die die Ergebnisse geschrieben
werden.
5.1.1 Prinzip der Pipeline-Verarbeitung
Pipeline-Verarbeitung heißt auf Deutsch Fließbandverarbeitung. Eine umfangreiche Aufgabe wird in eine Folge von nacheinander auszuführenden Arbeitsschritten mit vergleichbar großem Arbeitsaufwand aufgeteilt. Das zu bearbeitende Objekt fährt auf dem Fließband von einer Arbeitsstation zur nächsten. An jeder Station wird ein Arbeitsschritt ausgeführt. Die Fertigstellung
G. Kemnitz, Technische Informatik, eXamen.press,
DOI 10.1007/978-3-642-17447-6_5, © Springer-Verlag Berlin Heidelberg 2011
382
5 Komplexe Beispielentwürfe
eines Einzelproduktes geht dadurch nicht schneller. Aber es wird gleichzeitig
an NP Objekten gearbeitet. In jedem Fließbandtakt rücken die zu bearbeitenden Objekte eine Station weiter. Am Anfang kommt ein neues unbearbeitetes Objekt auf das Fließband und am Ende verlässt ein fertiges Produkt
das Fließband. Bei einer Aufteilung in NP Teilaufgaben mit derselben Bearbeitungsdauer erhöht sich die Verarbeitungsleistung auf das NP -fache (Abb.
5.1).
Arbeitsstationen
1
2
3
fertig
4
Arbeits- 3
station 2
1
4
Fließband
Werkstück
Dauer eines Fließbandtakts
tP
Fließbandtakt: 1 · tP
Fertigungszeit: 4 · tP
1
2
3
4
5
t
tP
Abb. 5.1. Prinzip der Pipeline-Verarbeitung
In einer digitalen Schaltung ist das zu fertigende Produkt das Ergebnis
einer Berechnung. Die Arbeitsstationen sind die nacheinander auszuführenden Operationen. Nach jeder Operation wird das Zwischenergebnis von einem
Register abgetastet und an die nächste Operation weitergereicht. Die Teilung
der Gesamtoperation in Schritte reduziert die Ausführungszeit der einzelnen
Register-Transfer-Operationen. Die Gesamtschaltung kann idealerweise mit
der mehrfachen Taktfrequenz arbeiten. Genau wie bei einem richtigen Fließband bleibt die Ausführungszeit insgesamt mindestens so groß wie bei einer
sequenziellen Verarbeitung. Aber es werden mehr Ergebnisse pro Zeit fertig
(Abb. 5.2).
tdS1
tdR
x
x’
f1 (x’)
tdS2
z
tsR
y
f2 (z)
y’
f (x’) = f2 (f1 (x’))
T
tdR
x
T
x’
tdS1
f1 (x’)
tsR tdR
z
z’
tdS2
f2 (z’)
tsR
y’
tdR
tdS1
tdS2
tsR
x
z
y
...’
Registerverzögerungszeit
Verzögerungszeit von f1 (...)
Verzögerungszeit von f2 (...)
Registervorhaltezeit
Eingabesignal
Zwischensignal
Ausgabesignal
abgetastetes Signal
minimale Taktperiode
ohne Pipeline
y”
tdR + tsR + tdS1 + tdS2
mit Pipeline
tdR + tsR + max(tdS1 , tdS2 )
Abb. 5.2. Aufteilung einer Register-Transfer-Funktion in zwei Pipeline-Phasen
5.1 Pipeline-Verarbeitung und Speicherengpass
383
In VHDL wird eine Pipeline durch eine Folge von Signalzuweisungen in
einem Abtastprozess beschrieben. Für die Schaltung in Abb. 5.2 unten lautet
die Prozessbeschreibung z.B.
process(T)
if rising_edge(T) then
x_del <= x;
z_del <= f1(x_del);
y_del2 <= f2(z_del);
end if;
end process;
Die erste Signalzuweisung beschreibt die Abtastung des Eingabesignals. Der
Funktionsaufruf in der zweiten Signalzuweisung beschreibt die erste kombinatorische Verarbeitungsschaltung und die Zuweisung selbst das nachfolgende
Zwischenregister. Die dritte Signalzuweisung beschreibt die Verarbeitung des
abgetasteten Zwischensignals durch die zweite kombinatorische Teilschaltung
und die Abtastung mit dem Ausgaberegister.
5.1.2 Ausbalancieren einer Pipeline
Das Black-Box-Modell einer Pipeline ist eine Register-Transfer-Operation, deren Ergebnis erst nach NP Verarbeitungsschritten für die Weiterverarbeitung
oder die Ausgabe zur Verfügung steht (NP – Pipeline-Tiefe). Die Mindestlänge der Taktperiode, mit der eine Pipeline betrieben werden kann, und
damit ihre maximale Verarbeitungsleistung, wird von der längsten RegisterRegister-Verzögerung bestimmt. Zur Minimierung der maximalen Verzögerung müssen die Verzögerungszeiten der Operationen zwischen den Registern
aneinander angeglichen werden. Dieser Angleich wird als Ausbalancieren der
Pipeline bezeichnet. Zum Ausbalancieren werden alle Register, die ihre Daten
nach derselben Anzahl von Abtastschritten in Bezug auf den Operationsstart
übernehmen, mit einer Zeitschnittlinie verbunden. Dann werden die Register in dem Datenflussgraphen so verschoben, dass die maximale Verzögerung
zwischen zwei aufeinanderfolgenden Zeitschnittlinien ein Minimum oder einen
hinreichend kleinen Wert erreicht.
In Abb. 5.3 a bilden die Abtastregister ein Schieberegister am Ausgang
der Verarbeitungsfunktion. Die Verzögerung vom Eingang bis zum ersten Register td1a ist sehr groß und die Verzögerungen zwischen den angehängten
Abtastregistern sind fast null. Die zusätzlichen Register verzögern die Ergebnisfertigstellung, ohne die Verarbeitungsleistung zu erhöhen. Abbildung 5.3 b
zeigt eine Schaltung mit demselben Anschlussverhalten und einer ausbalancierten Pipeline, in der die Verzögerungen zwischen den Registern nur etwa ein
Drittel der ursprünglichen maximalen Verzögerung td1a in Abb. 5.3 a betragen. Die geänderte Schaltung kann etwa mit der dreifachen Frequenz getaktet
werden und besitzt dann die dreifache Verarbeitungsleistung.
384
5 Komplexe Beispielentwürfe
x1
f1
td1a
z1
f3
x2
f2
z2
x1
x2
Zeitebene 0
z
f1 1
f2
z2
y
Zeitebene 1
z’1
z’3
f3
z’2
f4
b)
f5
z4
f4
a)
td2a
z3
td1b
z’4
unausbalanciert
td1a ≫ td2a ≈ td3a
td3a
y’
y”
y”’
Zeitebene 2
z”3
f5
y”
ausbalanciert
td1b ≈ td2b ≈ td3b
y”’
z”4
Zeitschnittlinie
td3b
td2b
Pipeline-Register
Abb. 5.3. Pipeline-Einbau a) Anhängen von Abtastregistern an den Ausgang b)
Ausbalancieren der Pipeline
5.1.3 Engpass Speicher
Für eine schnelle Verarbeitung und Übertragung müssen die Eingabedaten
mit der Verarbeitungsgeschwindigkeit bereitgestellt und die Ergebnisse nach
ihrer Berechnung abgeholt werden. Die Datenquellen und die Empfänger für
die Ergebnisse sind in der Regel Blockspeicher. Die Zugriffszeit auf einen größeren Blockspeicher übersteigt die Verzögerung von Logikgattern um Zehnerpotenzen und wächst mit der Datenkapazität (vgl. Abschnitt 4.4.1) [23].
Eine Vergrößerung der transferierten Datenmenge verlangt mehrere parallele
Speicher, Mehrportspeicher, eine Erhöhung der Datenwortbreite oder andere
schaltungsaufwändige Maßnahmen. Der Entwurf von schnellen Verarbeitungswerken beginnt deshalb in der Regel mit der Planung der Speicherstruktur, einer Ablaufplanung der Speicherzugriffe und einer Planung der VerarbeitungsPipelines. Die folgenden Abschnitte demonstrieren das an drei komplexen Beispielentwürfen.
5.2 FIR-Filter mit Blockspeichern
Ein FIR-Filter ist ein Filter mit endlicher Impulsantwort (FIR – f inite impulse
response) und ein wichtiger rechenzeitintensiver Algorithmus der digitalen Signalverarbeitung. Typische Anwendungen sind die Trennung der Spektralanteile in analogen Signalen, die Echo-Unterdrückung bei der Signalübertragung
über lange Leitungen und die Bildverarbeitung. Trotz der vielfältigen Anwendungen ist die Funktion eines FIR-Filters einfach. Jeder Ausgabewert yn ist
eine gewichtete Summe von M aufeinanderfolgenden Eingabewerten:
yn =
M
−1
X
m=0
cm · xk
mit k = n − m
(5.1)
5.2 FIR-Filter mit Blockspeichern
385
(xk – Eingabewert; yn – Ausgabewert; n – Nummer des Zeitschritts; cm –
Koeffizient; M – Länge der Impulsantwort, Größenordnung 100). Die Filterfunktion – Hochpass, Tiefpass, Glättungsfilter etc. – legt der Vektor der Koeffizienten cm fest1 . Es gibt Anwendungen in der Signalverarbeitung, in denen
viele Millionen Ergebnisse pro Sekunde zu berechnen sind. Jede Ergebnisberechnung erfordert 2 · M Speicherzugriffe mit den zugehörigen Adressrechnungen, M Multiplikationen und M − 1 Additionen. Für Anwendungen mit
einem kontinuierlichen Rechenleistungsbedarf von 108 und mehr Operationen
pro Sekunde ist eine Hardware-Lösung eine interessante Alternative zu einer
Software-Lösung.
5.2.1 Planung der Speicherstruktur und der Pipeline-Abläufe
Abbildung 5.4 a zeigt eine Skizze für den Berechnungsfluss, den Gleichung 5.1
beschreibt. Für jeden Ausgabewert yn werden M Eingabewerte mit M Koeffizienten multipliziert und die Produkte aufsummiert. Es fehlt der Datenspeicher, aus dem die Eingabedaten und Koeffizienten gelesen werden. Wie könnte
der Speicher organisiert sein? Ein M -Port-Blockspeicher scheidet wegen der
Größe von M hier aus. Eine nahe liegende Lösung wäre ein Schieberegister
der Länge M , das die Eingabewerte abtastet und an seinen Ausgängen die
um einen bis M Schritte verzögerten Eingabewerte bereitstellt (Abb. 5.4 b).
An jedem Schieberegisterausgang ist ein Multiplizierer anzuschließen, der das
Produkt cm · xk bildet. Der zweite Faktor ist eine Konstante, die fest codiert sein oder in einem Konfigurationsregister stehen kann. Die Teilprodukte
werden mit einem Addiererbaum zusammengefasst. Die Umsetzung in eine
VHDL-Beschreibung ist relativ einfach, aber die Schaltung wird sehr groß2 .
a)
xn
c0
xn−1
c1
xn−2
c2
xn−3
c3
*
+
*
*
*
+
yn
+
b)
x+
n
xn
c0
xn−1
c1
xn−2
c2
c3
xn−3
*
+
*
*
+
yn
+
*
Abb. 5.4. Datenfluss für eine FIR-Operation mit M = 4 a) ohne Operandenspeicher b) mit einem Schieberegister als Operandenspeicher
1
2
Der Koeffizientenvektor wird auch als Impulsantwort bezeichnet. Denn er ist
gleich mit der Ausgabefolge für einen Impuls der Form x0 = 1,0 und xn6=0 = 0
als Eingabefolge.
Man würde zumindest versuchen, die Multipliziereranzahl durch Einbau von
Pipeline-Stufen in die Multiplizierer drastisch zu verringern. Das erfordert eine
vollkommen andere Schaltungsstruktur.
386
5 Komplexe Beispielentwürfe
Wir wollen hier statt eines Schieberegisters, das für einen größeren Filtergrad M recht schaltungsaufwändig ist, einen wesentlich kompakteren Blockspeicher verwenden. Aus einem (1-Port-) Blockspeicher kann in jedem Zeitschritt nur ein Datenwort gelesen werden. Das ist der Flaschenhals für die Berechnung. Jetzt folgt ein Puzzle, in dem die Operationen auf Rechenwerke und
Berechnungsschritte aufgeteilt werden. Die Berechnung für jeden Ausgabewert
besteht aus M Teilberechnungen. Fast jede der Teilberechnungen beginnt mit
der Erhöhung der Koeffizientenadresse um eins und der Erhöhung der Datenadresse um eins. Danach werden ein Koeffizient und ein Datenwert aus dem
Speicher gelesen. Anschließend werden beide Werte miteinander multipliziert
und das Ergebnis zur bisherigen Teilsumme addiert. Mit den Koeffizienten und
Daten im selben Speicher müsste der Speicher entweder zwei Ports haben oder
die beiden Werte wären nacheinander zu lesen. Die eine Lösung ist aufwändig
und die andere halbiert die Verarbeitungsleistung. Die nahe liegende Alternative ist der Einsatz von zwei Blockspeichern, einem Schreib-Lese-Speicher
für die Daten und einem Nur-Lese-Speicher für die Koeffizienten. Das Zwischenergebnis der Überlegungen bis hierher ist ein Berechnungsfluss, der mit
zwei parallelen Adressrechnungen beginnt. Danach folgen die zwei parallelen
Speicherzugriffe. Die gelesenen Werte werden multipliziert und das Produkt
zum bisher akkumulierten Wert addiert. Das ist die Kernoperation, die für jeden zu berechnenden Ausgabewert mit geringfügigen Modifikationen M -mal
hintereinander ausgeführt werden muss.
cAdr
+1
xAdr
+1
AR
cDat
cROM
a ROM y
xDat
xRAM
x RAM y
a
w
OF
Register
cAdr Koeffizientenadressregister
xAdr Datenadressregister
cDat Koeffizientenregister
xDat Datenregister
Prod
mult
Mult
Akku
+
Add
Ergebnis
Pipeline-Phasen
AR Adressrechnung
OF Operanden lesen
Mult Multiplikation
Add Addition
Prod Produktregister
Akku Akkumulator (Summationsregister)
Blockspeicher
cROM Koeffizientenspeicher
xRAM Datenspeicher
Abb. 5.5. Blockspeicher-Pipeline-Struktur der Kernfunktion des FIR-Filters
Als Nächstes soll die Kernoperation in Pipeline-Phasen unterteilt werden.
Die Blockspeicherzugriffe, die den zeitlichen Engpass bilden, bekommen eine
eigene Pipeline-Phase. Dasselbe gilt für die Multiplikation, die auch relativ
viel Zeit benötigt3 . Die verbleibenden Adressrechnungen zu Beginn des Be3
Wenn die Multiplikation länger als der Speicherzugriff dauert, kann sie auch auf
mehrere Pipeline-Phasen aufgeteilt werden.
5.2 FIR-Filter mit Blockspeichern
387
rechnungsflusses und die Akkumulation der Produkte nach der Multiplikation
erhalten gleichfalls je eine eigene Pipeline-Phase. Das Zwischenergebnis des
Entwurfsprozesses ist die 4-stufige Verarbeitungs-Pipeline in Abb. 5.5. In der
ersten Pipeline-Phase »AR« (Adressrechnung) werden die Adressen weitergeschaltet. In der zweiten Phase »OF« (operand f etch) werden der Datenwert
und der Koeffizient gelesen. In der nächsten Phase »Mult« (Multiplikation)
wird multipliziert und in der letzten Phase »Add« (Addition) werden die
Produkte aufsummiert.
5.2.2 Der gesamte Operationsablauf
Nach der Skizzierung der Kernoperation ist der Operationsablauf zu präzisieren. Nach der Initialisierung der Adressregister sind die ersten M − 1 Eingabewerte x0 bis xM −2 in den Datenspeicher zu schreiben. Mit dem Schreiben
des Eingabewertes xM −1 beginnt die Berechnung des ersten Ausgabewertes.
Dieser Wert wird gleichzeitig in das Datenregister »xDat« und der zugehörige
Koeffizient c0 in das Koeffizientenregister »cDat« übernommen. Im nächsten Schritt wird das Produkt des ersten Koeffizient-Wert-Paares gebildet und
gleichzeitig das zweite Koeffizient-Wert-Paar aus den Blockspeichern gelesen.
Danach wird das erste Produkt in das Akkumulatorregister übernommen,
das zweite Produkt gebildet und das nächste Koeffizient-Wert-Paar aus dem
Speicher gelesen etc. (Abb. 5.6). Die Koeffizientenadresse zählt immer zyklisch
weiter. Die Daten stehen in absteigender Reihenfolge im Speicher und die Datenadresse zählt außer im letzten Schritt eines jeden Zyklus vorwärts. Nach
dem letzten Schritt bleibt die Datenadresse unverändert und der älteste Wert
wird mit dem neusten Wert überschrieben. Nach dem Startzyklus steht immer, während der Koeffizient »c2« gelesen wird (»cAdr=2«), ein abholbereites
Ergebnis im Akkumulator.
0
1
2
3
cAdr
1
2
3
0
1
2
3
0
3
2
1
0
1
2
3
3
0
1
2
2
xAdr
xRAM W(x0 ) W(x1 ) W(x2 ) W(x3 ) R(x2 ) R(x1 ) R(x0 ) W(x4 ) R(x3 ) R(x2 ) R(x1 ) W(x5 )
c0
c1
c2
c3
c3
c0
c1
c2
cDat
x3
x2
x1
x1
x0
x4
x3
x2
xDat
c0 · x3 c1 · x2 c2 · x1 c3 · x0 c0 · x4 c1 · x3 c2 · x2
Prod
P1
P1
P2
c0 · x3
y0 c0 · x4
Akku
...
...
...
Zustand
Init
Startzyklus
Normal...
Normalzyklus
Register
cAdr Koeffizientenadressreg.
xAdr Datenadressregister
cDat Koeffizientenregister
xDat Datenregister
Prod Produktreg.
Akku Akku.-Reg.
Blockspeicher
cROM Koeffizientenspeicher
xRAM Datenspeicher
Speicheroperationen
W(...) Speichern
R(...) Lesen
Abb. 5.6. Beispielablauf der FIR-Operation für M = 4
Bearbeitungsstand: Halbformale Beschreibung der Blockspeicher-Pipeline-Struktur und des Operationsablaufs, aus denen in den weiteren
Entwurfsschritten das Simulationsmodell zu entwickeln ist.
388
5 Komplexe Beispielentwürfe
5.2.3 Datentypen und Bearbeitungsmethoden
Eine komplexe Funktionsbeschreibung sollte immer in überschaubaren Schritten, nach denen jeweils eine Zwischenkontrolle erfolgt, entwickelt werden. In
Anlehnung an die objektorientierte Programmierung empfiehlt es sich, mit
der Definition der Typen der zu verarbeitenden Datenobjekte und den Unterprogrammen zu ihrer Verarbeitung zu beginnen (vgl. Abschnitt 3.4.1). Der
VHDL-Beschreibungsrahmen für Datentypen und Unterprogramme ist ein
Package und der Beschreibungsrahmen für Testabläufe ein Testrahmen.
Das erste Simulationsmodell einer zu entwerfenden Funktionseinheit dient
in der Regel zur Kontrolle des Algorithmus (vgl. Abschnitt 3.4.5 und Abschnitt
3.4.6). Für die Darstellung der zu verarbeitenden Daten genügen in dieser
Entwurfsphase wertebereichsbeschränkte reelle Zahlen und für die Adressen
wertebereichsbeschränkte natürliche Zahlen:
–- Typvereinbarungen zur Beschreibung eines FIR-Filters
constant M: positive := 4;
–- Filtergrad
subtype tAdr is natural range 0 to M-1;
–- Wertebereichsgrenze
constant max_abs: real := 1000.0;
type tDaten is real range -(max_abs) to max_abs;
type tMem is array (natural range <>) of tDaten;
Die zwei Adressregister und die vier Datenregister der Pipeline in Abb. 5.5
sollen zur gemeinsamen Übergabe an die Bearbeitungs-Prozeduren zu einem
Verbund zusammengefasst werden:
–- Datentyp für den Pipeline-Zustand
type tPipeline is record
cAdr, xAdr: tAdr;
cDat, xDat, Prod, Akku: tDaten;
end record;
Der Gesamtzustand des FIR-Filters besteht aus dem Datenspeicherzustand
und dem Pipeline-Zustand.
Eine Aufgabe des Simulationsmodells ist die Kontrolle, dass bei den arithmetischen Operationen keine Wertebereichsüberläufe oder andere Situationen,
die die Ergebnisse invalidieren, auftreten. Im Beispiel wird für die Einprogrammierung dieser Kontrollen der kleinste Wert des Zahlenbereichs als PseudoWert für »ungültig« reserviert und als Initialwert, als Operationsergebnis für
ungültige Operanden sowie bei einem Über- und Unterlauf des Zahlenbereichs
zugewiesen. Die Operatoren für die Addition und die Multiplikation werden
entsprechend überladen. Sie bilden zuerst aus den nach real konvertierten
Operanden das Ergebnis und entscheiden dann anhand der Gültigkeit der
Operanden und des Ergebniswertes, ob der Pseudo-Wert für »ungültig« oder
das nach »tDaten« zurückkonvertierte Ergebnis zurückgegeben wird:
5.2 FIR-Filter mit Blockspeichern
389
tDaten
tDaten
function "+"(a, b: tDaten) return tDaten is
+
constant sum: real := real(a) + real(b);
tDaten
begin
if a=tDaten’low or b=tDaten’low or (abs sum)>max_abs then
–- Pseudo-Wert für ungültig
return tDaten’low;
else return tDaten(sum);
end if;
end function;
tDaten
tDaten
function "*"(a, b: tDaten) return tDaten is
*
constant prod: real := real(a) * real(b);
tDaten
begin
if a=tDaten’low or b=tDaten’low or (abs prod)>max_abs then
–- Pseudo-Wert für ungültig
return tDaten’low;
else return tDaten(prod);
end if;
⇒WEB-Projekt: P5.2/FIR1_pack.vhdl
end function;
Als Nächstes sind alle Register-Transfer-Funktionen aus Abb. 5.6 auf Bearbeitungsmethoden aufzuteilen. Eine in Hardware nachzubildende Bearbeitungsmethode sollte nur Operationen zusammenfassen, die im selben Zeitschritt ausgeführt werden. In der Initialisierungsphase wird in jedem Zeitschritt die Koeffizientenadresse um eins erhöht, die Datenadresse um eins
verringert und ein Eingabewert in den Datenspeicher geschrieben. Dieses Verhalten lässt sich mit einer Prozedur mit dem zu speichernden Datenwert als
Eingabeparameter sowie mit dem Datenspeicher und dem Pipeline-Objekt als
les- und veränderbare Signale beschreiben:
procedure InitStep(x: tDaten; signal xRAM: inout tMem;
signal pp: inout tPipeline) is
begin
pp.cAdr <= (pp.cAdr + 1) mod M;
cAdr
1
2
... M − 1
pp.xAdr <= pp.xAdr - 1;
xAdr M −1 M −2 . . .
1
xRAM(pp.xAdr) <= x;
xRAM
W(x
)
W(x
)
.
.
.
W(x
0
1
M −2 )
end procedure;
Die Register-Transfer-Operationen im Start- und im Normalzyklus sind
einander sehr ähnlich (Abb. 5.7). Die Koeffizientenadresse wird modulo-M
hochgezählt, das Koeffizientenregister übernimmt den adressierten Inhalt des
Koeffizientenspeichers und das Produktregister das berechnete Produkt. Für
die anderen Datenobjekte weicht die auszuführende Operation jeweils für eine
Koeffizientenadresse von der Standardoperation ab. Der Datenspeicher wird
bei Zählstand null beschrieben statt gelesen. Bei Zählstand zwei wird dem
Akkumulator das Produkt statt der Summe zugewiesen und beim höchstwertigen Zählstand wird die Datenadresse nicht weitergezählt. Die in Abb. 5.7
mit einem grauen Dreieck gekennzeichneten Zuweisungen sind im Startzyklus
390
5 Komplexe Beispielentwürfe
1
cAdr
0
+1 mod M +1 mod M
xAdr
R(xn−1 )
xRAM
W(xn )
c0
cDat
cM −1
xn
xn−M +1
xDat
Prod c
· xn−M +2 cM −1 · xn−M +1
M −2
PM −3
PM −2
Akku
...
...
a) cAdr
cROM
cDat
xAdr
xRAM
Koeffizientenadressregister
Koeffizientenspeicher
Koeffizientenregister
Datenadressregister
Datenspeicher
2
+1 mod M
R(xn−2 )
c1
xn−1
...
...
...
c2
xn−2
M −2
+1 mod M
R(xn−M +2 )
...
...
M −1
nicht zählen
R(xn−M +1 )
cM −2
xn−M +2
c0 · xn
PM −1
yn = ...
c1 · xn−1
c2 · xn−2
P2
...
c0 · xn
...
xDat Datenregister
Prod Produktregister
Akku Akkumulationsregister
im Startzyklus optional
geänderter Datenfluss
x...
c...
W(...)
R(...)
M
...
Datenwert
Koeffizient
Schreiben
Lesen
Filtergrad
procedure NormalStep(x: tDaten; cROM: tMem; signal xRAM:
inout tMem; signal pp: inout tPipeline) is
begin
pp.cAdr <= (pp.cAdr + 1) mod M;
if pp.cAdr=0 then xRAM(pp.xAdr) <= x; pp.xDat <= x;
else pp.xDat <= xRAM(pp.xAdr);
end if;
pp.cDat <= cROM(pp.cAdr); pp.Prod <= pp.cDat * pp.xDat;
if pp.cAdr=2 then pp.Akku <= pp.Prod;
else pp.Akku <= pp.Akku + pp.Prod;
end if;
if pp.cAdr/=M-1 then pp.xAdr <= (pp.xAdr + 1) mod M;
end if;
b) end procedure;
⇒Web-Projekt:P5.2/FIR1 pack.vhdl
Abb. 5.7. Speicher- und Registerzuweisungen in allen Takten nach der Initialisierung a) tabellarisch b) als Bearbeitungsprozedur
nicht erforderlich. Aber sie stören auch nicht, so dass auf Fallunterscheidungen verzichtet werden kann. Die Unterbindung der Ausgabe im Startzyklus
erfolgt in der Ausgabefunktion.
Bearbeitungsstand: Für die einzelnen Bestandteile und für die gesamte
Blockspeicher-Pipeline-Struktur sind Datentypen definiert und für die
Datentypen sind die benötigten Bearbeitungsmethoden programmiert.
5.2.4 Das erste komplette Simulationsmodell
Die erste simulierbare Beschreibung ist im Beispielprojekt ein Prozess im Testrahmen. Innerhalb des Testrahmens werden vereinbart:
• eine initialisierte Konstante für den Koeffizientenspeicher:
constant cROM: tMem(tAdr) := (0.5, 1.0, -1.0, -0.5);
• ein Signal für den Datenspeicher
5.2 FIR-Filter mit Blockspeichern
391
signal xRAM: tMem(tAdr);
• ein Signal für das Pipeline-Objekt
signal pp: tPipeline;
• ein Dateiobjekt zum Einlesen der Eingabewerte xn
file Eingabedatei: text open read_mode is "Eingabe.txt";
• und eine Konstante für die Taktperiode
constant Tp: delay_length := 10 ns;
Der Filtergrad M steckt in der Typvereinbarung von »tAdr« und ist vier (vgl.
Abschnitt 5.2.3).
Der Ablauf der Filteroperationen beginnt mit einer Schleife mit Initialisierungsschritten gefolgt von einer Schleife mit Verarbeitungsschritten. Die grau
unterlegten Programmzeilen sind Textverarbeitungsanweisungen für die Einund Ausgabe:
–- Vereinbarungen im Testprozess
variable x: tDaten;
variable InitRdy: boolean;
variable s: tString;
–- Anweisungsfolge im Testprozess
–- Initialisierung und Ausgabe Tabellenkopf
pp.cAdr <= 1; pp.xAdr <= tAdr’high; wait for tp;
write("Eingabe:" & StatusKopfText & "Ausgabe:");
–- Initialisierungszyklus
while pp.cAdr/=0 loop
read(Eingabedatei, x); write(str(x) & str(pp, xRAM));
InitStep(x, xRAM, pp); wait for tp;
end loop;
–- Endlosschleife für Verarbeitungsschritte
loop
if pp.cAdr=0 then
if endfile(Eingabedatei) then wait; end if;
read(Eingabedatei, x); assign(s, str(x));
else assign(s, "
");
end if;
append(s, str(pp, xRAM));
if pp.cAdr=2 then
if not InitRdy then InitRdy := true;
else –- Ausgabe
append(s, str(pp.Akku));
end if;
end if;
write(s); –- Ausgabe der Ergebniszeichenkette
NormalStep(x, cROM, xRAM, pp); wait for tp;
end loop;
⇒WEB-Projekt: P5.2/Test_FIR1.vhdl
392
5 Komplexe Beispielentwürfe
In der Initialisierungsschleife wird in jedem Schritt ein Eingabewert aus der
Datei gelesen, die Prozedur »InitStep(...)« aufgerufen und ein Takt gewartet.
Der Start- und der Normalzyklus sind zusammengefasst. Die Unterscheidung
im Ablauf erfolgt mit der prozessinternen Variablen »InitRdy«, die im ersten Zyklus nach der Initialisierung die Ausgabe unterdrückt. Die Hauptarbeit
leistet die Prozedur »NormalStep(...)«. Bei dem Koeffizientenzählstand »0«
(Übernahme eines neuen Eingabewertes) wird zusätzlich vor dem Verarbeitungsschritt ein Wert aus der Datei gelesen und bei dem Koeffizientenzählstand »2« erfolgt zusätzlich nach der Warteanweisung ab dem zweiten Zyklus
eine Ausgabe.
Die Textausgaben werden mit den für Textobjekte vom Typ »tString« im
Package »Tuc.Ausgabe« definierten Prozeduren
• assign(Textobjekt, Text): alten Text löschen und neuen Text zuweisen,
• append(Textobjekt, Text): neuen Text anhängen und
• write(Textobjekt): Text auf dem Bildschirm ausgeben
erzeugt (siehe Abschnitt 3.3). Die Str-Funktionen für die Umwandlung der
projektspezifischen Datentypen »tDaten« etc. in Textdarstellungen sind mit
im Package »P5.2/FIR1_pack.vhdl« definiert. Sie sind ähnlich wie die bereits
behandelten Str-Funktionen aufgebaut und repräsentieren einen erheblichen
Anteil des Gesamtprogrammieraufwands.
Die Darstellung der Testausgaben hat entscheidenden Einfluss darauf, ob
fehlerhafte Zustände und Ausgaben bei der Simulation als solche erkannt werden. Für die Kontrolle von Pipeline-Operationen ist die in Abb. 5.8 dargestellte Tabellenform zu empfehlen. Die durch einen einfachen Strich getrennten
Spalten gehören zur selben Pipeline-Phase. Nach einem Doppelstrich beginnt
die nächste Pipeline-Phase. Ungültige Werte werden durch »XX« dargestellt.
Zum Simulationsbeginn sind nur die Koeffizienten- und die Datenadresse gültig. Die Werte im Datenspeicher sind alle ungültig und werden von der höchsten Adresse absteigend mit den ersten Eingabewerten beschrieben. Der Datenwert für den niederwertigsten Speicherplatz wird – wie in Abb. 5.6 festgeEingabe:|cAdr|xAdr||
100.0|
1|
3||
200.0|
2|
2||
300.0|
3|
1||
400.0|
0|
0||
|
1|
1||
|
2|
2||
|
3|
3||
600.0|
0|
3||
|
1|
0||
|
2|
1||
|
3|
2||
-600.0|
0|
2||
|
1|
3||
|
2|
0||
cDat |
XX |
XX |
XX |
XX |
0.2000|
0.5000|
-0.5000|
-0.2000|
0.2000|
0.5000|
-0.5000|
-0.2000|
0.2000|
0.5000|
xDat ||
XX ||
XX ||
XX ||
XX ||
400.0||
300.0||
200.0||
100.0||
600.0||
400.0||
300.0||
200.0||
-600.0||
600.0||
Prod |
XX |
XX |
XX |
XX |
XX |
80.0|
150.0|
-100.0|
-20.0|
120.0|
200.0|
-150.0|
-40.0|
-120.0|
Akku ||
XX ||
XX ||
XX ||
XX ||
XX ||
XX ||
80.0||
230.0||
130.0||
110.0||
120.0||
320.0||
170.0||
130.0||
r(0)
XX
XX
XX
XX
400.0
400.0
400.0
400.0
400.0
400.0
400.0
400.0
400.0
400.0
r(1)
XX
XX
XX
300.0
300.0
300.0
300.0
300.0
300.0
300.0
300.0
300.0
300.0
300.0
r(2)
XX
XX
200.0
200.0
200.0
200.0
200.0
200.0
200.0
200.0
200.0
200.0
-600.0
-600.0
r(3) |Ausgabe:
XX |
100.0|
100.0|
100.0|
100.0|
100.0|
100.0|
100.0|
600.0|
600.0|
110.0
600.0|
600.0|
600.0|
600.0|
130.0
Abb. 5.8. Simulationsausgaben des FIR-Filtermodells (r(i) – Abkürzung für
xRAM(i))
5.2 FIR-Filter mit Blockspeichern
393
legt – gleichzeitig in das Datenregister »xDat« kopiert. Die Datenweitergabe
über eine Pipeline-Phase ist immer mit einer Verzögerung um einen Taktschritt verbunden. Anhand der Testausgaben sind alle spezifizierten Abläufe
und Operationen in einer anschaulichen Weise kontrollierbar. Der zusätzliche
Programmieraufwand für übersichtliche, gut auswertbare Ausgaben – Richtwert 50% des Gesamtprogrammieraufwands – gilt als gute Investition. Denn
der Test, die Fehlersuche und nicht erkannte Entwurfsfehler sind in der Regel
erheblich teurer.
Bearbeitungsstand: Die Zielfunktion ist in einer simulierbaren Form
beschrieben und wurde mit Beispieleingaben getestet.
5.2.5 Ersatz der Zahlentypen durch Bitvektortypen
In Hardware werden Zahlen durch Bitvektoren dargestellt. In einem strukturierten Entwurf mit Bearbeitungsmethoden und Unterprogrammen lassen
sich die Zahlentypen gegen die entsprechenden Bitvektoren austauschen, ohne dass das gesamte Modell neu geschrieben werden muss. Die Darstellung
der Adresswerte »0« bis »3« erfordert einen 2-Bit-Vektor für vorzeichenfreie
Zahlen:
subtype tAdr is tUnsigned(1 downto 0);
Mit einem Bitvektor als Adresse ändern sich die Operationen für die Adressrechnung und die Speicherzugriffe. Aus den Additionen bzw. Subtraktionen
mod-4 werden einfache Additionen bzw. Subtraktionen, weil arithmetische
Ergebnisse immer mod-(2n ) (n – Ergebnisbitanzahl) gebildet werden. Die
Speicherzugriffe mit einem Bitvektor als Adresse müssen auch die Fälle für
ungültige und unzulässige Adressen mit erfassen. Im Beispiel werden deshalb
die Speicherzugriffe durch Aufrufe der Lesefunktion
function read(Mem: tMem; adr: tAdr) return tDaten;
und der Schreibprozedur
procedure write(signal Mem: inout tMem; adr: tAdr; x: tDaten);
aus Abschnitt 3.4.3 ersetzt. Die Daten sollen durch 16-Bit vorzeichenbehaftete
Festkommazahlen dargestellt werden:
subtype tDaten: tSigned(15 downto 0);
Die Koeffizienten haben einen Betrag kleiner eins. Die gedachte Kommaposition sei hinter dem führenden Bit. Der kleinste mit einer Vorkommastelle und
fünfzehn Nachkommastellen darstellbare Koeffizient ist 1,00 . . . 02 und hat den
Wert −1. Der größte darstellbare Koeffizient ist 0,11...1 mit dem Wert 1−2−15 .
Der Wertebereich für Daten soll wie im ersten Modell mindestens von −1000
bis +1000 reichen. Das erfordert einschließlich Vorzeichenbit elf Stellen vor
394
5 Komplexe Beispielentwürfe
dem Komma. Die restlichen fünf Bit sind Nachkommastellen. Bei einer Multiplikation addieren sich die Anzahlen der Vor- und der Nachkommastellen. Die
Produkte aus Koeffizienten- und Datenwerten haben zwölf Vorkomma- und
20 Nachkommastellen.
Die akkumulierten Werte sollen, um Wertebereichsüberläufe auszuschließen, dreizehn Vorkommastellen erhalten (siehe hierzu auch Aufgabe 5.1). Die
Anzahl der Nachkommastellen muss nicht größer als die der Daten sein. Für
den akkumulierten Wert genügt entsprechend ein 18-Bit-Vektor:
subtype tAkku is tSigned(17 downto 0);
Damit die Produkte ohne Konvertierung an den Akkumulator zugewiesen werden können, sollen sie denselben Typ mit derselben gedachten Kommaposition
haben. Die Multiplikation ist entsprechend so umzudefinieren, dass zu dem
normal berechneten Produkt vorzeichenerweitert eine Vorkommastelle hinzugefügt und die fünfzehn niederwertigsten Nachkommastellen abgeschnitten
werden4 :
function mult(a, b: tDaten) return tAkku is
constant prod: tSigned(2 * tDaten’length - 1 downto 0) := a * b;
begin
return prod(prod’high) & prod(prod’high downto tDaten’high);
end function;
Für die Kontrolle, dass die geänderten Datendarstellungen und Operationen
das Eingabe-Ausgabe-Verhalten des Gesamtmodells nicht beeinträchtigen, sollen sich die Wertedarstellungen der Adressen, Daten und Koeffizienten nicht
von denen im ersten Modell unterscheiden. Das erfordert eine Anpassung der
Str-Funktionen zur Konvertierung in die Ausgabetexte. Für die Datendarstellung wird der Wert der Daten durch 25 dividiert und mit sieben Zeichen und
einer Nachkommastelle dargestellt:
function str_dat(x: tSigned) return string is
begin
if is_x(x) then return "
XX";
else return rechts(str(real(int(x))/(2.0**5), 1),7);
end if;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end function;
Die ganzzahlige Werterepräsentation der Koeffizienten wird durch 215 geteilt
und mit vier Nachkommastellen dargestellt:
4
Überladen des »*«-Operators scheidet hier aus, weil »tDaten« ein Untertyp und
kein eigener Typ ist. Der Wert von »tDaten’high« ist fünfzehn und der Wert von
»tProd’high« ist 31.
5.2 FIR-Filter mit Blockspeichern
395
function str_coeff(c: tSigned) return string is
begin
XX";
if is_x(c) then return "
else return rechts(str(real(int(c))/(2.0**15), 4),7);
end if;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end function;
Als Nächstes müssten die geänderten Typvereinbarungen und Unterprogramme so in die beiden Bearbeitungsprozeduren und in den Testrahmen der vergangenen Abschnitte eingearbeitet werden, dass die Simulationsausgaben im
fehlerfreien Fall genau wie in Abb. 5.8 aussehen. Letzteres ist nur eine Empfehlung, aber eine nützliche. Wir wollen diese Schritte überspringen. Nach dem
Ersatz aller Zahlentypen durch Bitvektortypen bildet die Simulation bereits
die Registerstruktur und überwiegend auch die Register-Transfer-Funktionen
der zu entwerfenden Schaltung bit-genau nach. Damit sind wir wieder einen
Schritt näher am Ziel.
5.2.6 Ein- und Ausgabe über Signale
In den bisherigen Simulationsmodellen für den FIR-Filter wurden die benötigten Eingabedaten aus einer Datei gelesen und die Ausgaben in einer Zeichenkettenvariablen zusammengesetzt und ausgegeben. Eine Schaltung kommuniziert mit ihrer Umgebung über Signale statt über Ein- und Ausgabeanweisungen. In der nächsten Version des Simulationsmodells wird der Testrahmen
deshalb in drei über Signale kommunizierende Prozesse geteilt, und zwar in
• einen Prozess für die Bereitstellung der Eingabesignale,
• einen Prozess zur Modellierung des Testobjekts und
• einen Ausgabeprozess, der möglichst dieselben Textausgaben wie die bisherigen Simulationsmodelle erzeugen soll (Abb. 5.9 a).
Test- RD
daten- x
quelle
I
T
a)
Testobjekt
x FIR RD
WR
I
pp
xRAM
I
Testx
ausgabeRD prozess
T
WR
pp.cAdr 00 01 10 11 00 01 10 11 00 01 10
pp
RD
xRAM
x w0 w1 w2 w3 w4
w5
T
pp Pipeline-Zustand
b)
···
Abb. 5.9. Testrahmen für den FIR-Filter mit Ein- und Ausgabesignalen a) Prozessstruktur b) Signalverläufe
Das Testobjekt – die Funktionsbeschreibung des FIR-Filters – erhält außer
dem Dateneingabesignal x und dem Datenausgabesignal y einen Takteingang
396
5 Komplexe Beispielentwürfe
T , einen Initialisierungseingang I, ein Bestätigungssignal für Leseoperationen
RD und ein Bestätigungssignal für Schreiboperationen W R. Das Signal für
die Lesebestätigung wird während der Lesetakte aktiviert und signalisiert der
Datenquelle, dass sie ab dem nächsten Takt den Folgewert ausgeben soll. Das
Schreibbestätigungssignal W R wird in den Ausgabetakten aktiviert und signalisiert dem Testausgabeprozess, dass im Akkumulatorregister ein gültiger
Ausgabewert steht, der an die Ausgabezeile anzuhängen ist. Der Testeingabeprozess soll durch eine nebenläufige Prozedur beschrieben werden:
procedure Testdatenquelle(Dateiname: string; signal RD: std_logic;
signal T, I: out std_logic; signal x: out tDaten;
tp: delay_length := 10 ns) is
variable pstr: tPString; variable ZNr: natural;
variable r: real;
RD Test- x
file f: textio.text open read_mode is Dateiname;
daten- I
quelle T
begin
I <= ’1’; T <= ’0’; wait for tp; I <= ’0’ after tp/10;
loop
T <= ’1’, ’0’ after tp/2;
if RD=’1’ then
if textio.endfile(f) then wait; end if;
read(f, pstr); get(pstr, r, -1000.0, 1000.0);
if pstr.Status/=ok then
write("Zeile " & str(znr) & ":" & str(pstr.err_msg)); wait;
else x <= to_tSigned(integer(r * (2.0**5)), x’length) after tp/3;
ZNr := ZNr + 1;
end if;
end if;
wait for tp;
end loop;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end procedure;
Die Eingabedatei enthält die Filtereingabedaten. Das Initialisierungssignal I,
das Taktsignal T und der Eingabevektor x werden innerhalb der Prozedur
generiert. Nebenläufig aufgerufen generiert die Prozedur zu Beginn einen Initialisierungsimpuls und erzeugt danach mit der Taktperiode TP Taktimpulse.
Nach der ersten aktiven Taktflanke wird der erste gültige Eingabewert an das
Signal x zugewiesen. Danach wird nach jeder aktiven Taktflanke, bei der das
Lesebestätigungssignal aktiv ist – d.h. bei den nachfolgenden drei und dann in
jedem vierten simulierten Takt –, der nächste Eingabewert aus der Datei gelesen und verzögert an x zugewiesen (Abb. 5.9 b). Wenn das Dateiende erreicht
ist, terminiert die Prozedur mit einer Warteanweisung ohne Weckbedingung.
Durch das Ausbleiben der Eingabeänderungen terminieren auch die anderen
Prozesse des Testrahmens und die Simulation stoppt.
Der Testausgabeprozess soll etwa dieselben Ausgaben wie in Abb. 5.8 erzeugen. Dazu müssen der Prozedur, die nebenläufig aufgerufen den Protokollprozess nachbildet, das Taktsignal, das Schreib- und das Lesebestätigungssi-
5.2 FIR-Filter mit Blockspeichern
397
gnal, das Eingabesignal, der Pipeline-Zustand und der Zustand des Datenspeichers übergeben werden. Nach Aufruf schreibt die Prozedur die Kopfzeile
der Ausgabetabelle und in einer Endlosschleife nach jeder aktiven Taktflanke
die Textzeilen mit dem Bearbeitungszustand und optional dem Eingabe- oder
Ausgabewert. Zur Kontrolle der Zeitverläufe wird jeder Ausgabezeile zusätzlich die aktuelle Simulationszeit vorangestellt (siehe später Abb. 5.11):
procedure Testausgabe(signal T, RD, WR: std_logic;
Testx
signal pp: tPipeline; signal x: tDat;
RD ausgabeprozess
signal xRAM: tMem) is
WR
pp
variable s: tString;
xRAM
begin
(1)
T
write(" Zeit |Eingabe|Z| ... r(3)|Ausgabe");
loop
–- Endlosschleife
wait until rising_edge(T);
–- warte auf aktive Taktflanke
assign(s, rechts(str(now, 1),8));
–- Anhängen eines Zeilentextes wie in Abb.5.8,
–- der den Zustand der Schaltung beschreibt
write(s);
–- Textzeile ausgeben
end loop;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end procedure;
((1) – Ausgabe der Kopfzeile).
Bearbeitungsstand: Ein komplettes Verhaltensmodell der Soll-Funktion
mit Anschlusssignalen und einer internen Bitvektordarstellung. Der
dazu entwickelte Testrahmen kann auch für alle weiteren schnittstellengleichen Versionen des Simulationsmodells genutzt werden.
5.2.7 Umformung in eine Automatenbeschreibung
In dem bis hierher entwickelten Ablaufmodell wird in den Schleifenkörpern
nach jeder Register-Transfer-Operation eine Taktperiode lang gewartet (Abb.
5.10 a). Der funktionsgleiche synthesefähige Abtastprozess darf nur eine Warteanweisung enthalten, und zwar am Ende der Anweisungsfolge im Prozess
(Abb. 5.10 b, vgl. Abschnitt 1.4.2). Nach der Warteanweisung, d.h. zu Beginn
der Anweisungsfolge des Prozesses, verzweigt der Kontrollfluss mit Hilfe von
Fallunterscheidungen. Jeder Wartezustand in der Ablaufbeschreibung benötigt hierfür einen eigenen Kontrollflusszustand.
Der Kontrollflusszustand für drei nacheinander abzuarbeitende Schleifen
besteht aus dem Schleifenzähler und einem Aufzählungstyp zur Unterscheidung, welche der drei Schleifen gerade abgearbeitet wird:
type tZustand is XX, Init, Startzyklus, Normalzyklus;
Der vierte Zustandswert »XX« bedeutet »ungültig« und dient als Initialwert
für den Simulationsstart. Der Schleifenzähler ist der Zähler für die Koeffizientenadresse, die im Register »pp.cAdr«, gespeichert wird, so dass hierfür keine
398
5 Komplexe Beispielentwürfe
a) Ablaufbeschreibung
Init: for ... loop
...
wait for tP;
end loop;
Startzyklus: for ... loop
...
wait for tP;
end loop;
loop
Normalzyklus: for ... loop
...
wait for tP;
end loop;
end loop;
b) synthesefähige Beschreibung
Endlosschleife
des Prozesses
if I=’1’ then
Anfangswertzuweisungen;
elsif aktive Taktflanke then
Berechnungsschritte mit Fallunterscheidungen nach Schleife
und Schleifenzählerwert
end if ;
wait on T, I;
Warteliste
Abb. 5.10. Kontrollflussumformung in einen synthesefähigen Abtastprozess
zusätzliche Hardware erforderlich ist. Der Datentyp für den Pipeline-Zustand
erweitert sich zu
–- erweiterter Datentyp für den Pipeline-Zustand
type tPipeline is record
cAdr, xAdr: tAdr;
cDat, xDat: tDaten;
Prod, Akku: tAkku;(1)
Zustand: tZustand;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end record;
((1) – breiterer Bitvektortyp als »tDaten«, um Wertebereichsüberläufe zu vermeiden, vgl. Abschnitt 5.2.5).
Die Übergangsfunktion sei durch eine Prozedur beschrieben, die bei jeder
aktiven Taktflanke aufgerufen wird:
–- Übergangsfunktion des gesamten FIR-Filters
procedure PipeStep(x: tDat; cROM: tMem; signal xRAM: inout tMem;
signal pp: inout tPipeline) is
begin
cAdr
1
2
... M − 1
case pp.Zustand is
xAdr M −1 M −2 . . .
1
when XX => null;
xRAM W(x0 ) W(x1 ) . . . W(xM −2 )
when Init =>
pp.cAdr <= pp.cAdr + "1";
pp.xAdr <= pp.xAdr - "1";
write(xRAM, pp.xAdr, x);
if pp.cAdr=to_tUnsigned(M-1, tAdr’length) then
pp.Zustand <= Startzyklus; end if;
when others =>
–- Operationen im Start- und Nomalzyklus
...
end case;
end procedure;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
5.2 FIR-Filter mit Blockspeichern
399
Der Eingabevektor x und der Koeffizientenspeicher »cROM« sind Eingabewerte, der Datenspeicher »xRAM« und das Pipeline-Objekt les- und veränderbare Signale. In den Initialisierungsschritten wird die Koeffizientenadresse, die
als Zustandszähler dient, hochgezählt. Die Datenadresse wird abwärts gezählt
und der Eingabewert auf den adressierten Datenspeicherplatz geschrieben. Die
Speicherzugriffe erfolgen hier mit der Read-Funktion und der Write-Prozedur
aus Abschnitt 3.4.3, die im Gegensatz zu einem indizierten Feldzugriff auch
den Fall, dass die Zugriffsadresse ungültig oder unzulässig ist, mit berücksichtigen. Für die Synthese sind diese Unterprogramme entsprechend zu vereinfachen oder wieder durch indizierte Zugriffe zu ersetzen. Im letzten Initialisierungsschritt wird der Zustand von »Init« auf »Startzyklus« geändert.
In allen anderen Fällen, d.h. im Zustand »Startzyklus« oder »Normalzyklus«, sind die Fallunterscheidungen aus Abb. 5.7 zu übernehmen:
• Schritt 0: Datenwert in den Datenspeicher schreiben statt lesen (FU1),
• Schritt 2: Produkt in den Akkumulator kopieren statt zum Akkumulatorinhalt zu addieren und Ergebnis ausgeben (FU2) und
• letzter Schritt: Datenadresse nicht weiterzählen (FU3).
Im Startzyklus entfällt die Ergebnisausgabe. Statt dessen wird der Zustand
weitergeschaltet:
–- Operationen im Start- und Nomalzyklus
(1)
pp.cAdr <= pp.cAdr + "1";
if pp.cAdr="00" then
–- Fallunterscheidung FU1
(2)
write(xRAM, pp.xAdr, x);
pp.xDat <= x;
else
(2)
pp.xDat <= read(xRAM, pp.xAdr);
end if;
(2)
pp.cDat <= read(cROM, pp.cAdr);
pp.Prod <= mult(pp.cDat, pp.xDat); (3)
if pp.cAdr="10" then
–- Fallunterscheidung FU2
pp.Akku <= pp.Prod;
if pp.Zustand=Startzyklus then pp.Zustand <= Normalzyklus; end if;
else
pp.Akku <= pp.Akku + pp.Prod;
end if;
–- Fallunterscheidung FU3
if pp.cAdr/="11" then
pp.xAdr <= pp.xAdr + "1";
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end if;
((1) – für 2-Bit-Vektoren automatisch mod 4; (2) – Lesefunktion und Schreibprozedur aus Abschnitt 3.4.3; (3) – Spezialmultiplikation für Faktoren vom
Typ »tDaten« und dem Ergebnistyp »tAkku« aus Abschnitt 5.2.5).
Die Schaltungsschnittstelle des FIR-Filters in Abb. 5.9 a besitzt drei
Ausgabesignale: das Lesebestätigungssignal, das Schreibbestätigungssignal
400
5 Komplexe Beispielentwürfe
und den Akkumulatorzustand. Die beiden Bit-Signale ergeben sich aus dem
Pipeline-Zustand und sollen durch getrennte Funktionen berechnet werden.
Das Lesebestätigungssignal ist im Initialisierungszustand immer und in den
beiden anderen Zuständen nur, wenn die Koeffizientenadresse null ist, zu aktivieren:
function RdGnt(pp: tPipeline) return std_logic is
begin
if pp.Zustand=Init or pp.cAdr=to_tUnsigned(0, tAdr’length)
then return ’1’;
else return ’0’;
end if;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end function;
Das Signal für die Schreibbestätigung ist nur im Normalzyklus, wenn die Koeffizientenadresse den Wert zwei hat, zu aktivieren:
function WrGnt(pp: tPipeline) return std_logic is
begin
if pp.Zustand=Normalzyklus and pp.cAdr=to_tUnsigned(2, tAdr’length)
then return ’1’;
else return ’0’;
end if;
⇒WEB-Projekt: P5.2/FIR2_pack.vhdl
end function;
Das komplette Verhaltensmodell soll als Prozess beschrieben werden. Dazu
sind im Testrahmen folgende Konstanten und Signale zu vereinbaren:
constant cROM: tMem := (to_tKoeff( 0.2), to_tKoeff( 0.5),
to_tKoeff(-0.5), to_tKoeff(-0.2));
signal xRAM: tMem(0 to M-1);
signal pp: tPipeline;
signal T, I, rd, wr: std_logic;
⇒WEB-Projekt: P5.2/Test_FIR2.vhdl
signal x: tDat;
Die Funktion »to_tKoeff(...)« ist eine im Package definierte Hilfsfunktion zur
Konvertierung einer Gleitkommazahl in die Bitvektordarstellung für Koeffizienten. Die Ein- und Ausgabe wird durch nebenläufige Aufrufe der Prozeduren
aus dem Vorabschnitt beschrieben:
Testdatenquelle("Eingabe.txt", rd, T, I, x);
Testausgabe(T, rd, wr, pp, x, xRAM);
Das Verhaltensmodell der kompletten Übergangsfunktion des FIR-Filters ist
ein Abtastprozess mit asynchroner Initialisierung. Zur Initialisierung werden
den beiden Adressregistern und dem Zustandsregister ihre Anfangswerte zugewiesen und bei jeder aktiven Taktflanke wird die Prozedur, die die Übergangsfunktion beschreibt, aufgerufen:
5.2 FIR-Filter mit Blockspeichern
401
process(T, I)
begin
if I=’1’ then
pp.cAdr <= to_tUnsigned(1, tAdr’length);
pp.xAdr <= to_tUnsigned(M-1, tAdr’length);
pp.Zustand <= Init;
elsif rising_edge(T) then
PipeStep(x, cROM, xRAM, pp);
end if;
⇒WEB-Projekt: P5.2/Test_FIR2.vhdl
end process;
Die beiden Ausgabesignale werden nebenläufig aus dem Pipeline-Zustand mit
Hilfe der vordefinierten Funktionen gebildet:
rd <= RdGnt(pp);
wr <= WrGnt(pp);
Abbildung 5.11 zeigt die Simulationsausgaben. Die noch fehlenden Schritte
bis zu einer synthesefähigen Schaltung beinhalten
• Beseitigung aller Abfragen und Zuweisungen mit dem Pseudo-Wert »ungültig«,
• den entsprechenden Ersatz bzw. die Vereinfachung der Read-Funktion und
der Write-Prozedur und
• eine Kapselung der Testobjektbeschreibung in eine eigenständige Entwurfseinheit mit Schnittstellenbeschreibung5 .
Zeit |Eingabe|Z|cAdr|xAdr|| cDat |
10.0 ns|
XX|I|
1|
3||
XX|
20.0 ns| 100.0|I|
1|
3||
XX|
30.0 ns| 200.0|I|
2|
2|| 0.5000|
40.0 ns| 300.0|I|
3|
1||-0.5000|
50.0 ns| 400.0|S|
0|
0||-0.2000|
60.0 ns|
|S|
1|
1|| 0.2000|
70.0 ns|
|S|
2|
2|| 0.5000|
80.0 ns|
|S|
3|
3||-0.5000|
90.0 ns| 600.0|N|
0|
3||-0.2000|
100.0 ns|
|N|
1|
0|| 0.2000|
110.0 ns|
|N|
2|
1|| 0.5000|
120.0 ns|
|N|
3|
2||-0.5000|
xDat || Prod |
XX||
XX|
XX||
XX|
XX||
XX|
XX||
XX|
XX||
XX|
400.0||
XX|
300.0||
80.0|
200.0|| 150.0|
100.0|| -100.0|
600.0|| -20.0|
400.0|| 120.0|
300.0|| 200.0|
Akku ||
XX||
XX||
XX||
XX||
XX||
XX||
XX||
80.0||
230.0||
130.0||
110.0||
120.0||
r(0)
XX
XX
XX
XX
XX
400.0
400.0
400.0
400.0
400.0
400.0
400.0
r(1)
XX
XX
XX
XX
300.0
300.0
300.0
300.0
300.0
300.0
300.0
300.0
r(2)
XX
XX
XX
200.0
200.0
200.0
200.0
200.0
200.0
200.0
200.0
200.0
r(3)|Ausgabe
XX|
XX|
100.0|
100.0|
100.0|
100.0|
100.0|
100.0|
100.0|
600.0|
600.0| 110.0
600.0|
Abb. 5.11. Simulationsausgaben des FIR-Filtermodells
5
Für den Test und die Fehlersuche in den ersten Entwurfsphasen ist es günstiger,
die Zielfunktion im Testrahmen in einem Prozess als sequenzielles Programm zu
beschreiben. Denn so ist das Einfügen, Ändern und Löschen von Testausgaben
einfacher. Die Kapselung in eine separate Entwurfseinheit ist erst später nützlich,
wenn die betrachtete Funktionseinheit gründlich getestet ist, zuverlässig funktioniert und in eine übergeordnete Entwurfseinheit als Teilschaltung eingefügt wird.
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement