Entwickeln mit CPLDs - Homepage von Stefan Buchgeher

Transcription

Entwickeln mit CPLDs - Homepage von Stefan Buchgeher
Entwickeln
mit CPLDs
(am Beispiel einer
DCF-Uhr)
Autor:
Letzte Bearbeitung:
Buchgeher Stefan
15. Oktober 2006
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Seite 2
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Inhaltsverzeichnis
1.
EINLEITUNG..........................................................................................................5
2.
GRUNDLEGENDES ZU DCF.................................................................................6
3.
SCHALTUNGSBESCHREIBUNG (DCF-UHR) ......................................................8
4.
SOFTWAREENTWURF MIT CPLDS AM BEISPIEL DCF-UHR ..........................11
4.1.
Grundlagen..............................................................................................................................................11
4.2.
Einteilung der Aufgabe in Blöcke ...........................................................................................................11
4.3.
Einteilung in Blöcke am Beispiel der DCF-Uhr ......................................................................................11
5.
UMSETZUNG DES DESIGNS IN AHDL ..............................................................23
Schritt 1: Ein neues Projekt in Quartus anlegen................................................................................................23
Schritt 2: Eingabe des Designs in AHDL............................................................................................................27
Schritt 3: Systemtakt definieren .........................................................................................................................38
Schritt 4: Erste Kompilierung ............................................................................................................................39
Schritt 5: Pinnummern zuweisen........................................................................................................................42
Schritt 6: Zweite Kompilierung..........................................................................................................................43
6.
SIMULATION .......................................................................................................44
Schritt 1: Ein Vector Waveform File für dieses Projekt erzeugen.....................................................................44
Schritt 2: Simulator-Einstellungen.....................................................................................................................48
Schritt 3: Simulation beginnen ...........................................................................................................................49
Schritt 4: Simulationsergebnis analysieren ........................................................................................................50
Schritt 5: Zweite Simulation ...............................................................................................................................50
7.
PROGRAMMIEREN .............................................................................................53
8.
NACHBAUANLEITUNG.......................................................................................55
Schritt 1: Platinen herstellen ..............................................................................................................................55
Schritt 2: Platinen bestücken..............................................................................................................................55
Schritt 3: Test der Steuerplatine.........................................................................................................................58
Schritt 4: DCF-Modul montieren und erste Funktionskontrolle .......................................................................58
Seite 3
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Schritt 5: Steuer- und Anzeigeplatinen miteinander verbinden und zweite Funktionskontrolle......................59
Schritt 6: „Befestigungswinkel“ und Acrylglas-Scheibe vorbereiten.................................................................60
Schritt 7: Endmontage........................................................................................................................................61
ANHANG A:
LAYOUTS .............................................................................................62
ANHANG B:
STÜCKLISTE ........................................................................................64
ANHANG C:
QUELLEN .............................................................................................66
Seite 4
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
1.
Einleitung
Die Abkürzung CPLD steht für Complex Programmable Logic Device und bedeutet
soviel wie programmierbarer Logikbaustein für komplexe Anwendungen. Solche
programmierbaren Logikbausteine werden von unterschiedlichen Herstellern angeboten
und unterscheiden sich erheblich voneinander. Zudem gibt es noch unterschiedliche
Technologien vom eher einfachen (PAL1 und GAL2) bis zu sehr komplexen (CPLD3 und
FPGA4).
Hier bei diesem Projekt wurde ein CPLD von Altera ausgewählt. Dies ist rein willkürlich,
denn grundsätzlich könnte auch ein Baustein eines anderen Herstellers verwendet
werden. Einschränkungen ergeben sich nur in der Anzahl der verfügbaren Pins und der
„Größe“ des Bausteins. Mit Größe ist hier nicht die Abmessung gemeint sondern die
Größe der Schaltung sprich die Anzahl der Makrozellen.
Bei programmierbaren Logikbausteinen ist weiters zu beachten dass die Funktion der
Schaltung in den Baustein programmiert werden muss. Dazu muss diese aber zuerst in
irgendeine Form erstellt werden. Hier hat sich eine spezielle Sprache entwickelt und
durchgesetzt. Mit dieser Sprache ist es möglich die zu programmierende Schaltung zu
beschreiben. Man nennt diese HDL5, wobei sich hier verschiedene Dialekte entwickelt
haben (VHDL6, AHDL7, ABEL-HDL usw.). Hier, bei diesem Projekt wurde die vom
Hersteller entwickelte Sprache AHDL verwendet.
Schließlich muss die erstellte Software noch in den Logikbaustein (IC) gebracht werden.
Dazu gibt es vom Hersteller mehrere Downloadkabel, die entweder die parallele
Schnittstelle oder die USB-Schnittstelle verwenden.
Zuletzt soll noch erwähnt werden, dass der Hersteller zu seinen programmierbaren
Logikbausteinen auch eine kostenlose Entwicklungsumgebung bereitstellt. Diese kann
von der Hersteller-Hompage (www.altera.com) kostenlos gedownloadet werden.
1
PAL steht für Programmable Array Logic
GAL steht für Generic Array Logic
3
CPLD steht für Complex Programmable Logic Device
4
FPGA steht für Field Programmable Gate Array
5
HDL steht für Hardware Description Language
6
VHDL steht für Very high speed integrated circuit Hardware Description Language
7
AHDL steht für Altera Hardware Description Language
Seite 5
2
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
2.
Grundlegendes zu DCF
Der Zeitzeichensender DCF77 befindet sich in Mainflingen, ca.
25 km südöstlich von Frankfurt am Main. Dieser
Langwellensender
hat,
bedingt
durch die
niedrige
Trägerfrequenz von 77,5 kHz eine Reichweite von ca. 1500 km
bis 2000 km. (Bild 2.1)
Bild 2.1: Rechweite des DCF77-Senders
(Quelle: www.dcf77.com/)
Der Dauerträger des
DCF-Senders senkt im
Sekundentakt für 100ms oder 200ms die
Amplitude der Trägerfrequenz auf 25 % ab, was
einer einfachen Amplitudenmodulation entspricht. Die Länge dieser so genannten
Sekundenmarken überträgt in codierter Form das
Zeittelegramm. Eine Absenkdauer des Trägers
um 100ms (Toleranz: ±20ms) entspricht dabei
Bild 2.2: Amplitudenmodulation des
77,5kHz-Trägers
einem logischen Low-Pegel, während ein
logischer High-Pegel mit einer Absenkdauer von
200ms (Toleranz ±40ms) codiert ist. In jeder 59.
Sekunde wird die Absenkung nicht vorgenommen, so dass damit eine eindeutige
Zuordnung des Minutenanfangs möglich ist. Die neue Sekunde beginnt, mit Ausnahme
der 59. Sekunde, jeweils mit dem Absenken des 77,5 kHz-Trägers.
Im jeweils einminütigem Zeittelegramm ist die Zeit (Stunde und Minute) der nächstfolgenden Minute sowie das komplette Datum und der jeweilige Wochentag codiert. Die
folgende Tabelle zeigt die Bedeutung der 59 Bits, die pro Minute versandt werden.
Bit Bedeutung
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Wertig- Bit Bedeutung
keit
Minutenbeginn Low
20 Telegrammbeginn High
Reserve
21 Minuten Einer
Reserve
22 Minuten Einer
Reserve
23 Minuten Einer
Reserve
24 Minuten Einer
Reserve
25 Minuten Zehner
Reserve
26 Minuten Zehner
Reserve
27 Minuten Zehner
Reserve
28 Prüfbit 1
Reserve
29 Stunden Einer
Reserve
30 Stunden Einer
Reserve
31 Stunden Einer
Reserve
32 Stunden Einer
Reserve
33 Stunden Zehner
Reserve
34 Stunden Zehner
Reserveantenne
35 Prüfbit 2
Zeitumstellung Ankündigung
36 Kalendertag Einer
Zeitzonenbit 1
37 Kalendertag Einer
Zeitzonenbit 2
38 Kalendertag Einer
Schaltsekunde Ankündigung
39 Kalendertag Einer
Tabelle 2.1: Zeittelegramm
Seite 6
Wertigkeit
1
2
4
8
10
20
40
1
2
4
8
10
20
1
2
4
8
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bit Bedeutung
40
41
42
43
44
45
46
47
48
49
Wertig- Bit Bedeutung
keit
Kalendertag Zehner
10
50 Jahr Einer
Kalendertag Zehner
20
51 Jahr Einer
Wochentag
1
52 Jahr Einer
Wochentag
2
53 Jahr Einer
Wochentag
4
54 Jahr Zehner
Monat Einer
1
55 Jahr Zehner
Monat Einer
2
56 Jahr Zehner
Monat Einer
4
57 Jahr Zehner
Monat Einer
8
58 Prüfbit 3
Monat Zehner
10
59 Keine Austastung
Tabelle 2.1: Zeittelegramm (Fortsetzung)
Wertigkeit
1
2
4
8
10
20
40
80
Die Synchronisation des Sekundenzählers erfolgt mit Ausbleiben der Absenkung der
59. Sekunde. Die nächste Absenkung ist immer Low. Die Bits 1 bis 14 sind nicht belegt.
Bit 15 zeigt durch einen High-Pegel an, dass zurzeit die Reserveantenne des DCF77Senders aktiv ist. Im Normalfall ist dieses Bit auf „Low“ gesetzt. Bit 16 wird eine Stunde
bevor die Zeitumstellung von Sommer- auf Winterzeit bzw. umgekehrt erfolgt auf „high“
gesetzt und mit der Zeitumstellung wieder zurückgesetzt. Die Zeitangaben beziehen
sich auf die UTC-Zeit (Universal Time Coordinated). Bezogen auf die UTC-Zeit eilt die
mitteleuropäische Zeit (MEZ) um eine Stunde vor, während die mitteleuropäische
Sommerzeit (MESZ) um 2 Stunden voreilt. Diese Differenz wird in den Zeitzonenbits 17
und 18 ausgedrückt. Während der MEZ ist Bit 17 High und Bit 18 Low, während bei der
Sommerzeit (MESZ) der Abstand zur UTC 2 Stunden beträgt und somit Bit 17 Low und
Bit 18 High ist. Bit 19 kündigt eine bevorstehende Schaltsekunde an. Das eigentliche
Zeit- und Datumstelegramm ist in den Bits 20 bis 58 codiert. Für die Einerstellen der
Zeit und Datumsinformationen sind jeweils 4 Bit, während für die Zehnerstellen nur 2
oder 3 Bit erforderlich sind. Die Zahlendarstellung der Zeit- und Datumsinformation
erfolgt im Binärformat (BCD-Code). Für die Jahreszahl werden nur die Einer- und
Zehnerstelle übertragen. Die Bits 42 bis 44 geben in binärer Schreibweise den
Wochentag an (der Wert 1 steht für den Montag, der Wert 7 für den Sonntag). Das
Prüfbit 1 ergänzt die Bits 21 bis 27 auf gerade Parität, d.h. es werden die High-Bits 21
bis einschließlich 28 addiert, deren Ergebnis muss dann eine gerade Zahl ergeben. Das
Prüfbit 2 ergänzt die Parität von Bit 29 bis 34, während Prüfbit 3 für die Parität der Bits
36 bis 57 zuständig ist. Diese Prüfbits sind ein erstes Überprüfungskriterium für ein
DCF-Empfangsprogramm, welches damit zunächst auf einfache Weise die Konformität
der empfangenen Daten überprüfen kann. Für eine fehlerfreie DCF-Decodierung sind
allerdings noch weitere Maßnahmen notwendig. (Zum Beispiel ein Vergleich der soeben
dekodierten Uhrzeit und des Datums mit der Uhrzeit und dem Datum welches mit der
vorhergehenden Minute übertragen wurde und zusätzlich noch eine mitlaufende
Softwareuhr).
In unregelmäßigen Zeitabständen muss eine Schaltsekunde eingefügt werden. Dies ist
dadurch bedingt, dass sich die Erde nicht genau in 24 Stunden um sich selbst dreht.
Auf die koordinierte Weltzeitskala UTC bezogen, wird diese Korrektur zum Ende der
letzten Stunde des 31. Dezember oder 30. Juni vorgenommen. In Mitteleuropa muss
die Schaltsekunde daher am 1. Januar um 1.00 Uhr MEZ oder am 1.Juli um 2.00 MESZ
eingeschoben werden. Zu den genannten Zeiten werden daher 61 Sekunden gesendet.
Seite 7
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
3.
Schaltungsbeschreibung (DCF-Uhr)
Bild 3.1.: Schaltung
Seite 8
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Die Schaltung sieht auf dem ersten Blick vielleicht etwas umfangreich aus, ist aber
eigentlich sehr einfach. Es handelt sich um einige Standardlösungen.
Der größte Bauteil ist das CPLD (IC1). Dieser benötigt neben der
Versorgungsspannung (Anschlüsse VCCxx und GND) zunächst eine ResetBeschaltung und eine Takt-Beschaltung.
Die Reset-Beschaltung besteht aus einem einfachen RC-Glied bestehend aus dem
Widerstand R1 und dem Elektrolyt-Kondensator C1. Dieses RC-Glied bewirkt bei jedem
Einschalten einen Reset.
Die Takt-Beschaltung ist schon etwas umfangreicher. Sie besteht aus einem speziellen
Inverter (IC2), einem 32,768kHz-Quarz (X1) zwei Kondensatoren (C2 und C3) und zwei
Widerständen (R2 und R3)8.
Der eher unübliche Wert für den Quarz von 32,768kHz wurde deswegen gewählt, weil
daraus sehr einfach ein 1-Hz-Takt erzeugt werden kann. Dieser 1-Hz wird im CPLD für
die Uhr benötigt. (siehe auch Abschnitt 4.3.).
Wichtig: Für IC2 muss unbedingt der in der Stückliste angegebene Typ 74HCU04
verwendet werden.
Die Ausgabe der Uhrzeit erfolgt mit 7-Segment-Anzeigen (LD1 bis LD5). LD5 beinhaltet
zwei solche 7-Segment-Anzeigen, während LD1 bis LD4 nur jeweils eine beinhalten,
dafür sind diese aber etwas größer. Für jede 7-Segment-Anzeige ist jeweils ein eigener
Dekoder-IC notwendig (IC3 bis IC8 vom Typ 74LS47). Diese Dekoder haben die
Aufgabe die richtigen Segmente einer 7-Segment-Anzeige anzusteuern. Weiters sind
für jedes Segment der 7-Segment-Anzeige Vorwiderstände notwendig (R5 bis R18 und
R21 bis R48). Dabei fällt auf, dass die Vorwiderstände R35 bis R48 einen größeren
Wert besitzen. Dies liegt daran, dass unterschiedliche 7-Segment-Anzeigen verwendet
wurden, die unterschiedlich stark leuchten. Durch diese unterschiedlichen
Widerstandswerte wird erreicht, dass trotzdem alle Anzeigen in etwa gleich hell
leuchten. Die Dekoder-ICs besitzen einige Steuerleitungen, die hier zu besonderen
„Effekten“ führen. Mit dem Steuereingang RBI (Pin 5) wird die 7-Segment-Anzeige nur
dann aktiv, wenn sie einen Wert größer als 0 anzeigen soll. Mit anderen Worten: eine 0
wird nicht angezeigt. Dies wird hier bei der Zehnerstelle der Stundenanzeige
ausgenützt. Die übrigen 7-Segment-Anzeigen verwenden den Steuereingang BI/RB0
(Pin 4). Mit diesem kann die Anzeige ein- und ausgeschaltet werden. Bei diesem
Projekt erzielt man damit, dass die Anzeige erst dann eingeschaltet wird, wenn ein
gültiges DCF-Telegramm empfangen wurde.
Die Leuchtdioden D1 und D2 mit den Vorwiderständen R19 und R20 dienen zur
Anzeige des Sekundentakts zwischen der Stunden- und Minutenanzeige. Die
Leuchtdioden D3 bis D9 mit den Vorwiderständen R49 bis R55 dienen zur Anzeige von
Statusinformationen. Diese sind optional und können mit den Jumpern JP1 bis JP7
ausgeschaltet werden. Die Leuchtdioden D8 und D9 haben hier noch keine Bedeutung,
sie sind aber für weitere Zwecke vorhanden, da noch genügend Ein/Ausgabepins
vorhanden sind. IC9 dient hier zur Isolierung, da Verbraucher (Leuchtdioden, Relais,
Motoren etc.) nicht direkt an das CPLD angeschlossen werden sollen.
Der 10polige Anschluss JTAG (K1) dient zum Programmieren des CPLD.
8
Eine genauere Beschreibung zu dieser Takt-Schaltung finden Sie im Buch „306 Schaltungen“ (ISBN: 389576-022-6), Seite 399f
Seite 9
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Zur Dekodierung des DCF-Telegramms dient ein bei Conrad erhältliches DCFEmpfangsmodul (Bestell-Nr.: 641138). Dieses Modul enthält eine Empfangsantenne
und einen Demodulator, so dass am Ausgang des Moduls das übertragene
Zeittelegramm mit einem CPLD ausgewertet werden kann. Bild 3.2. zeigt dieses DCFEmpfangsmodul.
Bild 3.2.: DCF-Empfangsmodul
Der Ausgangsstrom von nur einem Milliampere ist für die Kontroll-Leuchtdiode (D12)
zuwenig. Die nachgeschaltete Transistorstufe (T1) mit den Widerständen R56 und R58
gleicht diesen Nachteil aus. Der Widerstand R57 dient als Vorwiderstand für die
Leuchtdiode (D12). Diese Leuchtdiode signalisiert den empfangenen Datenstrom, wenn
der Jumper JP9 gesteckt ist. Bei einem korrekten Empfang blinkt diese Leuchtdiode im
Sekundentakt. Dieses Blinken zeigt sozusagen den Ausgangspegel der AnpassSchaltung an. Das Puls-Pausen-Verhältnis (Leuchtzeit/Dunkelzeit der Leuchtdiode D12)
entspricht der im Abschnitt 2 genannten Zeiten. Bei etwas Übung kann der Unterschied
zwischen Low (100ms Absenkung des Trägers, LED ist 100ms dunkel) und High
(200ms Absenkung des Trägers, LED ist 200ms dunkel) optisch erkannt werden.
Der Kondensator C16 dient zur Entkoppelung der Betriebsspannung für das DCFModul. Für diesen Koppelkondensator sollte ein Keramiktyp verwendet werden. Dieser
muss möglichst nahe am DCF-Modul angebracht werden.
Für die Stromversorgung wurde ebenfalls eine Standardschaltung bestehend aus dem
Festspannungsregler (IC10) vom Typ 7805 und den Kondensatoren C4 bis C7 gewählt.
Da die 7-Segment-Anzeigen und das CPLD einiges an Strom benötigen, wird der
Festspannungsregler schon ziemlich warm. Daher sollte dieser mit einem Kühlkörper
(gemäß Stückliste im Anhang B) versehen werden.
Die Diode D10 dient als Verpolungsschutz und die Leuchtdiode D11 zeigt an, ob die
DCF-Uhr mit Spannung versorgt ist.
Die Kondensatoren C8 bis C12 dienen zur Entkoppelung der Betriebsspannung für IC2
bis IC9. Für diese Koppelkondensatoren sollten Keramiktyp verwendet werden. Diese
sollten möglichst nahe an den ICs angebracht werden.
Seite 10
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
4.
Softwareentwurf mit CPLDs am Beispiel DCF-Uhr
4.1. Grundlagen
Komplexe digitale Schaltungen sind stets eine Zusammensetzung aus kombinatorischer
Logik9 (in Form von Addierer, Adressdekodierer, Multiplexer und Demultiplexer, usw.)
und sequentieller Logik10 (in Form von Zählern, Schieberegister, diskreten FlipFlops
und Zustandsmaschinen). Es ist daher unbedingt notwendig, dass man diese digitalen
Grundschaltungen beherrscht.
4.2. Einteilung der Aufgabe in Blöcke
Bei der Entwicklung von Schaltungen mit CPLDs gibt es eine Vielzahl von Ansätzen
und Vorgehensweisen. Eine davon ist die so genannte „Top-Down-Methode“. Bei dieser
Methode wird der gesamten Prozess in Blöcke unterteilen. Diesen Blöcken ordnet man
bestimmte Aufgaben zu, wobei man sich vorerst noch nicht um deren Innenleben zu
kümmern braucht. Auf dieser Ebene denkt man über den gesamten Prozess nach und
versucht dabei das Zusammenspiel dieser Blöcke zu optimieren. Erscheint einem diese
Aufteilung optimal, so Unterteilt man die einzelnen Blöcke wieder in Unterblöcke. Dabei
geht man genau so vor, wie in der ersten Ebene. Nun kann man sich auf die Aufteilung
dieser bereits kleineren Blöcke konzentrieren und muss sich nicht mehr so intensiv mit
dem gesamten Prozess kümmern. Diese Vorgehensweise wiederholt man so lange, bis
man schließlich bei Blöcken mit einer überschaubaren Größe angekommen ist. Diese
Blöcke können dann meist als einfache Zustandsmaschinen oder als kombinatorische
Logik realisiert werden.
4.3. Einteilung in Blöcke am Beispiel der DCF-Uhr
Bevor man die gestellte Software-Aufgabe in Blöcke einteilen kann, muss man sich
zuerst im Klaren sein, was denn die Software alles erledigen muss, und wie man diese
am besten und sinnvollsten realisiert. (Dabei spielt sicher auch die Erfahrung eine
wichtige Rolle!)
Hier, bei der DCF-Uhr hat die Software (im Zusammenspiel mit der Hardware) folgende
Aufgaben:
• Aus dem seriellen DCF-Datenstrom (Eingangspin 55) „Low“, „High“
„Minutenwechsel“ ermitteln. (gemäß Abschnitt 2. Grundlegendes zu DCF). Diese
Informationen zwischenspeichern und an den Ausgängen 51 (für „Low“) und 52 (für
„High“) ausgeben.
• Bei einem fehlerhaften Empfang (d.h. wenn weder ein „Low“, ein „High“ oder ein
„Minutenwechsel“ erkannt wurde, die Fehler Ausgänge 41 und 49 setzen.
• Eine frei mitlaufende Uhr, welche ständig mit einer gültigen Uhrzeit aus dem DCFEmpfang synchronisiert wird. Eine gültige Uhrzeit liegt vor, wenn ein DCFTelegramm fehlerfrei empfangen wurde.
9
Kombinatorische Logik wird oft auch mit „Schaltwerke“ bezeichnet
Sequentielle Logik wird oft auch mit „Schaltnetze“ bezeichnet
Seite 11
10
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
•
•
•
Die Anzeige der Uhrzeit soll erst dann erfolgen, wenn ein gültiges DCF-Telegramm
empfangen wurde. (Ausgangspin 16). Dies soll außerdem am Ausgang „Sync“ (Pin
45) angezeigt werden.
Die Uhrzeit in BCD-Form ausgeben.
Alle Eingänge mit dem Takt synchronisieren. Dies erfolgt normalerweise mit einem
einfachen D-FlipFlop. Anmerkung: Die DCF-Uhr besitzt nur einen Eingang, folglich
ist nur ein D-FlipFlop notwendig.
Bild 4.1. zeigt die Blockeinteilung für die DCF-Uhr. Bei dieser ersten Aufteilung spricht
man auch vom „Top-Design“ oder „Top-Level-Design“.
Bild 4.1.: Top-Level-Design (DCF-Uhr)
Hier, bei der DCF-Uhr erfolgt das Top-Level-Design aus zwei Blöcken.
Anmerkung: Die hier getroffene Blockeinteilung ist sicher nur eine Möglichkeit von
mehreren. Hier liegt die Freiheit des Entwicklers, die geforderte Aufgabe in sinnvolle
Teilaufgaben zu zerlegen, was mitunter auch ein wenig Erfahrung benötigt.
Block „DCF-Dekodierung“
Dieser Block hat die Haupt-Aufgabe aus dem seriellen DCF-Datenstrom das
Telegramm (Low- und High-Bits) zu ermitteln und diese zwischenzuspeichern.
Die Bilder 4.2. und 4.3. zeigen die Realisierung dieses Blocks. Dieser Block besteht aus
einer Zustandsmaschine (iZM_DCF), einem Zähler (iZAEHLER_DCF) zur Ermittlung
von Zeiten, einem Schiebregister (iSR_DCF) zur Speicherung des Telegramms, und
einigen D-FlipFlops zur Speicherung diverser Zustände und zur Synchronisierung des
DCF-Eingangs mit dem Systemtakt (iFF_DCF_In).
Seite 12
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 4.2.: Block “DCF-Dekodierung”
Die Hauptaufgabe der Zustandsmaschine (iZM_DCF) ist es aus dem seriellen
Datenstrom am Eingang die LOWs und HIGHs zu ermitteln. Gemäß Abschnitt 2 erfolgt
zu jeder Sekunde ein Impuls. Ein Low-Impuls dauert zwischen 80ms und 120ms und
ein High-Impuls zwischen 160ms und 240ms. Bei einem Minutenwechsel bleibt dieser
Impuls aus. Bild 4.3 (links oben) zeigt noch einmal diesen Zusammenhang. Für die
Auswertung ist aber nicht diese Impulszeit interessant, sondern vielmehr die Zeit
zwischen zwei Impulsen (siehe Bild 4.3, links oben). Denn mit dieser Zeit kann
eindeutig zwischen einem Low, einem High und einem Minutenwechsel unterschieden
werden. Die Grundidee ist nun die, dass, diese Zeit mit Hilfe eines Zählers
(iZAEHLER_DCF im Bild 4.2.) gezählt wird, wobei der Zähler bei einer steigenden
Flanke am Eingang freigegeben (also gestartet wird) und bei einer fallenden Flanke am
Eingang wird der Zählwert eingelesen und ausgewertet. Im Zustandsdiagramm (Bild
4.3.) sind dies die Zustände Z0, Z1 und Z2. Erfolgt aber nach einer gewissen Zeit keine
fallende Flanke, so erfolgt ein Time-Out, also ein Fehler. Gemäß Zustandsdiagramm
(Bild 4.3.) erfolgt dann nach dem Zustand Z1 der Zustand Z7, wo die beiden FehlerFlipFlops (iFF_DCF_BitFehler und iFF_DCF_Fehler) gesetzt werden. Anschließend
gelangt die Zustandsmaschine in den Ausgangszustand (Z0) zurück und wartet auf die
nächste steigende Flanke.
Seite 13
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 4.3.: Zustandsdiagramm „iZM_DCF“
Erfolgt aber eine fallende Flanke am Eingang innerhalb der Time-Out-Zeit, so gelangt
die Zustandmaschine nun zum Zustand Z2. hier erfolgt die Auswertung des
Zählerstands des Zählers iZAEHLER_DCF.
• Entspricht der Zählerstand dieses Zählers einem Wert zwischen 28835 (entspricht
880 ms) und 30147 (entspricht 920 ms), so wurde ein LOW empfangen. Daher folgt
auf den Zustand Z2 nun der Zustand Z3, wo dem Schieberegister (iSR_DCF) ein
LOW hinzugefügt wird. Weiters wird das FlipFlop iFF_DCF_Lo gesetzt, zur
Kennzeichnung, dass ein Low empfangen wurde, während die FilpFlops
iFF_DCF_High und iFF_DCF_BitFehler gelöscht werden. Anschließend gelangt die
Zustandsmaschine in den Ausgangszustand (Z0) zurück und wartet auf die nächste
steigende Flanke.
• Entspricht der Zählerstand dieses Zählers einem Wert zwischen 24903 (entspricht
760 ms) und 27526 (entspricht 840 ms), so wurde ein HIGH empfangen. Daher folgt
auf den Zustand Z2 nun der Zustand Z4, wo dem Schieberegister (iSR_DCF) ein
HIGH hinzugefügt wird. Weiters wird das FlipFlop iFF_DCF_High gesetzt, zur
Kennzeichnung, dass ein High empfangen wurde, während die FilpFlops
iFF_DCF_Lo und iFF_DCF_BitFehler gelöscht werden. Anschließend gelangt die
Zustandsmaschine in den Ausgangszustand (Z0) zurück und wartet auf die nächste
steigende Flanke.
• Entspricht der Zählerstand dieses Zählers einem Wert zwischen 57671 (entspricht
1760 ms) und 62915 (entspricht 1920 ms), so wurde ein Minutenwechsel
empfangen. Daher folgt auf den Zustand Z2 nun der Zustand Z5, wenn das FehlerFlipFlop iFF_DCF_Fehler nicht gesetzt ist, oder der Zustand Z6, wenn das FehlerFlipFlop iFF_DCF_Fehler gesetzt ist. Diese Unterscheidung hat folgende Gründe:
o Ist das Fehler-FlipFlop iFF_DCF_Fehler nicht gesetzt, so bedeutet dass,
das ein komplettes DCF_Telegramm fehlerfrei empfangen wurde, da ja
sobald ein Fehler auftritt dieses Fehler-FlipFlop gesetzt wird
o Zu Beginn (also nach dem Einschalten) ist das Fehler-FlipFlop gesetzt
(der Set-Eingang dieses FlipFlops ist ja mit der Reset-Leitung verbunden,
Seite 14
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
siehe Bild 4.2.). Das bedeutet, dass zunächst auf einen Minutenwechsel
gewartet werden muss.
Im Zustand Z5 wird die frei mitlaufende Uhr mit der empfangenen DCF-Uhrzeit (und
Datum) synchronisiert. Die Daten (Uhrzeit und Datum) befinden sich ja nun im
Schieberegister und können an den entsprechenden Ausgängen abgegriffen
werden. Bild 4.4. zeigt, welche Daten an welchen Ausgängen des Schieberegisters
anliegen. Weiters wird im Zustand Z5 das FlipFlop iFF_DCF_Sync gesetzt. Diese
zeigt an, dass die DCF-Uhr nun synchronisiert ist. Anschließend gelangt die
Zustandsmaschine in den Ausgangszustand (Z0) zurück und wartet auf die nächste
steigende Flanke.
Der Zustand Z6 hat nur die Aufgabe, das Fehler-FlipFlop iFF_DCF_Fehler wieder
zurückzusetzen. In diesem Fall wird die frei mitlaufende Uhr nicht mit den Daten
vom Schieberegister synchronisiert, da die Daten im Schieberegister fehlerhaft sind.
Anschließend gelangt die Zustandsmaschine in den Ausgangszustand (Z0) zurück
und wartet auf die nächste steigende Flanke.
Bild 4.4.: Schieberegister iSR_DCF
Seite 15
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Noch eine Anmerkung zum Zähler iZAEHLER_DCF:
Der Systemtakt beträgt, wie schon im Abschnitt 3 erläutert, f = 32,768 kHz. Da der
Zähler iZAEHLER_DCF mit diesem Takt getaktet wird ergibt sich eine Zeit T von
T=
1
1
s
=
f 32768
Für eine Zeit von Beispielsweise t = 880ms (wie oben erwähnt) ergibt sich somit ein
Zählerstand von
Zählerwert =
t
= t ⋅ f = 0,88 s ⋅ 32768 s −1 = 28835,84
T
Also ein Zählwert von 28835.
Achtung: Der Nachteil bei dieser Auswertemethode ist, dass die Uhr um 1 Sekunde
nachgeht, da ja die Auswertung am „Ende der Sekunde erfolgt“, und da beginnt ja
schon die „neue Sekunde“. Im Allgemeinen spielt dass aber nur eine sehr
untergeordnete Rolle.
Block „Freilaufende Uhr“
Dieser Block hat die Haupt-Aufgabe eine (freilaufende) Uhr zu erzeugen, welche auch
geladen werden kann. Die einfachste Realisierung einer Uhr besteht darin Zähler
hintereinander zu schalten, wobei der Ausgang des ersten Zählers der Takt für den
zweiten Zähler ist, der Ausgang des zweiten Zählers der Takt für den nächsten Zähler
usw. Diese asynchrone Methode wird als „Ripple-Counter“ bezeichnet. Ihr größter
Vorteil ist ihre Einfachheit. Ihre Nachteile sollten aber auch nicht unerwähnt bleiben.
Diese asynchrone Methode eignet sich nur für niedrige Frequenzen und es können
beim Übergang von einem Zählwert zum nächsten Zählwert kurzzeitig falsche
Zählwerte auftreten. Beide Nachteile sind bei dieser Anwendung als DCF-Uhr aber von
untergeordneter Rolle, da der Systemtakt mit 32.768kHz sehr gering ist, und die Uhrzeit
nur mit 7-Segment-Anzeigen angezeigt werden soll. Unser menschliches Auge
bekommt es gar nicht mit, wenn kurzzeitig (kurzzeitig bedeutet hier im 10ns-Bereich)
eine „falsche“ Uhrzeit angezeigt wird.
Bild 4.5. zeigt die Realisierung der freilaufenden Uhr.
Bild 4.5.: Block “Freilaufende Uhr”
Seite 16
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Dieser Block wird hier wieder in mehrere Blöcke gemäß Abschnitt 4.2 aufgeteilt. Hier
handelt es sich im Wesentlichen um verschiedene Zähler. Die Aufgabe des ersten
Zählers ist die Erzeugung eines 1-Sekunden-Taktes aus dem Systemtakt. Die nächsten
drei Blöcke sind für die Uhrzeit zuständig. Hier handelt es sich jeweils um BCD-Zähler
von 0 bis 59 (für Sekunden und Minuten) bzw. von 0 bis 23 (für die Stunden).
Neben dem Systemtakt (clock_DCF) sind noch die Leitungen „Uhr freigeben“, „Laden“
und das dekodierte DCF-Telegramm vorhanden. Die freilaufende Uhr soll erst dann „mit
ihrer Arbeit beginnen“, wenn ein gültiges DCF-Telegramm empfangen wurde. Erst ab
diesem Zeitpunkt wird die Anzeige mit der Leitung „Uhr freigeben“ aktiviert und die
freilaufende Uhr beginnt unabhängig von der DCF-Dekodierung zu laufen, wobei aber
jedes Mal wenn ein gültiges DCF-Telegramm empfangen wurde die Uhr (also die
Zähler) mit den Daten aus dem DCF-Telegramm überschrieben werden. Dazu ist die
Leitung „Laden“ zuständig. Weiters soll die Leitung „Laden“ auch den Sekundenzähler
und den Zähler für den Sekundentakt löschen.
Block „Zähler für Sekundentakt“
Dieser Block hat die Aufgabe aus dem Systemtakt (32.768kHz) einen 1-Sekunden-Takt
zu erzeugen. Wenn man bedenkt, dass 32768 nichts anderes als 215 ist, und man
außerdem weiß, dass jede Stufe eines Binärzähler durch 2 dividiert, so liegt es nahe für
diese Aufgabe einen 15-Stufigen-Binärzähler zu verwenden. Altera bietet in seiner
Entwicklungsumgebung (Quartus) u.a. solche Zähler (lpm_counter) an, welche noch
über einige Zusatzfunktionen (wie Zähler freigeben, Zähler löschen, Zähler laden usw.)
verfügen. Diese Zusatzfunktionen kommen uns sehr gelegen, da wir diese hier teilweise
verwenden, denn dieser Zähler soll wie Bild 4.5. zeigt, freigegeben und gelöscht werden
können.
Block „BCD-Zähler 0 - 59 (Sekunden)“
Bild 4.6. zeigt einen BCD-Zähler für die Sekunden. Dieser besteht aus einem 4-BitZähler für die Sekunden-Einer (iZAEHLER_SEK_E) und einem 3-Bit-Zähler für die
Sekunden-Zehner (iZAEHLER_SEK_Z), wobei diese Zähler aber nicht ihren gesamten
Zählbereich (0 bis 15 bzw. 0 bis 7) ausnützen sondern nur den für Sekunden sinnvollen
Bereich von 0 bis 9 (Einer) und 0 bis 5 (Zehner). Diese Eigenschaft lässt sich in der
Software für jeden Zähler angeben. (siehe Abschnitt 5, Schritt 2)
Die Steuerleitung „Laden“ setzt beide Zähler zurück.
Bild 4.6.: Block “BCD-Zähler 0-59 (Sekunden)”
Der Takt für den Sekunden-Einer-Zähler (iZAEHLER_SEK_Z) stammt vom Block
„Zähler für Sekundentakt“ (siehe Bild 4.5.). Als Takt für den Sekunden-Zehner-Zähler
(iZAEHLER_SEK_Z) dient der höchstwertige Ausgang (q[3]) des Sekunden-EinerSeite 17
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Zählers (iZAEHLER_SEK_E) in negierter Form (siehe Bild 4.6). Bild 4.7. zeigt weshalb.
Beim Übergang von 9 nach 0 des Sekunden-Einer-Zählers geht der Ausgang q[3] von
high nach low. Da dies der einzige high-low-Übergang von q[3] ist und dieser genau
dann auftritt wenn der Zählstand der Sekunde von 9 nach 0 übergeht kann dieser als
Takt für die Zehner-Stelle dienen. Allerdings in negierter Form.
Bild 4.7.: Zeitdiagramm des Zählers für die Einerstelle der Sekunde
Ähnliches gilt als Takt für den nachfolgenden Minuten-Zähler-Block. Als Takt für den
Minuten-Einer-Zähler (iZAEHLER_MIN_E) dient der höchstwertige Ausgang (q[2]) des
Sekunden-Zehner-Zählers (iZAEHLER_SEK_Z) in negierter Form (siehe Bild 4.5). Bild
4.8. zeigt weshalb. Beim Übergang von 5 nach 0 des Sekunden-Zehner-Zählers geht
der Ausgang q[2] von high nach low. Da dies der einzige High-Low-Übergang von q[1]
ist und dieser genau dann auftritt wenn der Zählstand der Minute von 5 nach 0 übergeht
kann dieser als Takt für die Einer-Stelle für die Minute dienen. Allerdings in negierter
Form.
Bild 4.8.: Zeitdiagramm des Zählers für die Zehnerstelle der Sekunde
Block „BCD-Zähler 0 - 59 (Minuten)“
Bild 4.9. zeigt einen BCD-Zähler für die Minuten. Auch dieser Block besteht aus einem
4-Bit-Zähler (für die Minuten-Einer, iZAEHLER_MIN_E) und einem 3-Bit-Zähler (für die
Minuten-Zehner, iZAEHLER_MIN_Z). Der Unterschied zum Block „BCD-Zähler 0-59
(Sekunden)“ ist, dass diese beiden Zähler geladen werden können. Und zwar mit der
Minuten-Information aus dem DCF-Telegramm. Die Steuerleitung „Laden“ hat also hier
die Aufgabe die beiden Zähler mit den anliegenden Daten aus dem DCF-Telegramm zu
laden. Diese Daten liegen an den Zähler-Eingängen data[3..0] (für die Einerstelle) bzw.
data[2..0] für die Zehnerstelle an.
Als Takt für Einerzähler dient, wie schon vorher erwähnt, der höchstwertige
Zählerausgang des Zählers für die Sekunden-Zehnerstelle (q[2]), allerdings in negierter
Form. Als Takt für den Minuten-Zehner-Zähler dient der höchstwertige Ausgang (q[3])
des Minuten-Einer-Zählers (iZAEHLER_MIN_E) in negierter Form (siehe Bild 4.9). Auch
hier gelten die gleichen Überlegungen wie für den Block „BCD-Zähler 0-59 (Sekunden)“.
Seite 18
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 4.9.: Block “BCD-Zähler 0-59 (Minuten)”
Block „BCD-Zähler 0 - 23 (Stunden)“
Bild 4.10. zeigt einen BCD-Zähler für die Stunden. Auch dieser Block besteht aus einem
4-Bit-Zähler (für die Stunden-Einer, iZAEHLER_STD_E) und einem 2-Bit-Zähler (für die
Stunden-Zehner, iZAEHLER_STD_Z).
Bild 4.10.: Block “BCD-Zähler 0-23 (Stunden)”
Die Besonderheit bei diesem BCD-Zähler ist, dass dieser nur bis 23 zählen soll. Dies
erreicht man dadurch, indem man, sobald der BCD-Zähler zum Wert 24 gelangt beide
Zähler löscht. Diese Aufgabe übernimmt das UND-Gatter (siehe Bild 4.10). Der
Ausgang dieses UND-Gatters ist mit den Lösch-Eingängen (.aclr) der beiden Zähler
verbunden. D.h. sobald beide Eingänge am UND-Gatter logisch high sind wird der
Zähler gelöscht und beginnt wieder beim Wert 0 zu zählen. Das Zeitdiagramm (Bild
4.11.) zeigt uns warum q[2] der Einerstelle und q[1] der Zehnerstelle als “Auslöser“ für
das Löschen der Zähler zu verwenden sind.
Seite 19
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 4.11.: Zeitdiagramm (BCD-Zähler 0-23, Stunden)
Die Kombination q[2] (Einer) = 1 und q[1] (Zehner) = 1 tritt wie im Bild 4.11. zu erkennen
nur beim BCD-Zählwert 24 auf.
Der „Nachteil“ bei dieser Methode ist, dass kurzzeitig der Wert 24 am Ausgang des
BCD-Zählers ansteht. Hier, bei dieser Anwendung als einfach DCF-Uhr, welche nur die
Uhrzeit anzeigen soll ist dieser Nachteil nicht von großer Bedeutung, da die Zeit, wo
dieser „falsche“ Wert angezeigt wird nur sehr, sehr gering ist (im ns-Bereich), und daher
vom menschlichen Auge gar nicht wahrgenommen wird.
Beginnt man nun mit den zuletzt beschriebenen Blöcken und fügt man diese in den
jeweils übergeordneten Block ein, also die Bilder 4.10., 4.9. und 4.6. in 4.5., diesen und
4.2. in das Top-Level-Design (Bild 4.1.) so ergibt sich das fertige Design. Bild 4.12a.
zeigt dieses fertige Gesamtdesign für die Anwendung des CPLD als DCF-Uhr. Bild
4.12b. zeigt nochmals die Zustandsmaschine (iZM_DCF) vom Bild 4.3.
Seite 20
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 4.12a. Gesamtdesign
Seite 21
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 4.12b.: Gesamtdesign (Zustandsdiagramm „iZM_DCF“)
Seite 22
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
5.
Umsetzung des Designs in AHDL
Als nächster Schritt erfolgt nun die Umsetzung des am Papier entworfenen Designs
(hier für die DCF-Uhr) in eine für das CPLD verständliche Sprache. Hierfür gibt es
mehrere Möglichkeiten. Eine Möglichkeit wäre die Eingabe in Form eines Schaltplans.
Diese Methode wird aber selten verwendet, da sie sehr zeitintensiv ist. Eine andere
Methode ist die Verwendung einer so genanten „Hardware-Beschreibungssprache“
(engl. HDL für Hardware Description Language). Da hier ein CPLD des Herstellers
Altera verwendet wird liegt es nahe die von Altera entwickelte Variante AHDL zu
verwenden. Weiters ist eine Entwicklungsumgebung notwendig. Hier fiel die Wahl auf
das von Altera entwickelte Entwicklungssystem „Quartus“ (Version II 5.0 Web-Edition),
welches kostenlos vom Internet unter www.altera.com gedownloadet werden kann.
Nach der Installation dieses Programms ist eine kostenlose Lizenz notwendig. (Durch
umgehen dieser Lizenz kann zwar ein Design erstellt und kompiliert werden, es ist aber
nicht möglich dieses Design in ein CPLD zu programmieren)
Die nun folgenden Schritte sollen zeigen, wie man ein neues Projekt (mit Quartus)
erstellt, welche Einstellungen notwendig sind, wie man das Design (vom Bild 5.12.) mit
AHDL beschreibt, usw. Zu diesen Schritten existiert in der Online-Hilfe ein sehr gutes
Tutorial (allerdings nur in englischer Sprache)
Schritt 1: Ein neues Projekt in Quartus anlegen
Quartus starten. Nach einer Weile erscheint der Startbildschirm (nach Bild 5.1)
Bild 5.1.: Startbild der Entwicklungssoftware Quartus (hier II Version 5.0)
Seite 23
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Durch anklicken von „File“ und „New Project Wizard…“ wird ein Dialog zur Erstellung
eines neues Projektes gestartet. Es erfolgt zunächst eine Einführung über folgenden
durch zu führenden Schritte (Bild 5.2)
Bild 5.2.: Dialog zur Erstellung eines
neuen Projekts (Einführung)
Taste „Next >“
1
2
3
4
Bild 5.3.: Dialog zur Erstellung eines
neuen Projekts (Schritt 1)
Hier erfolgt die Auswahl des Projekt-Ordners, des Projekt-Namens und des Namens
des Top-Level-Designs.
Anmerkungen: Für den Projekt-Namen und für den Namen des Top-Level-Designs
sollten „sprechende“ Namen verwendet, so dass man schon an diesen Namen erkennt
worum es bei diesem Projekt geht. Für beide kann durchaus, so wie hier, der gleiche
Name gewählt werden.
Taste „Next >“
Seite 24
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 5.4.: Dialog zur Erstellung eines
neuen Projekts (Schritt 2)
Hier können schon vorhanden Design-Files in das Projekt eingebunden werden. Bei
diesem Projekt gehen wir davon aus, dass noch keine Design-Files vorhanden sind. Die
Eingabefelder bleiben daher leer.
Taste „Next >“
1
2
1
3
4
Bild 5.5.: Dialog zur Erstellung eines
neuen Projekts (Schritt 3)
Nun wird das CPLD ausgewählt. Wir verwenden hier ein Mitglied der MAX7000SFamilie (1). Mit dem Filter (2) kann die Suche nach dem verwendeten Typ erleichtert
werden. Da wir hier den Typ EPM7128SLC84-15 verwenden wählen wir diesen auch
aus (3). Siehe auch Schaltungsbeschreibung (Abschnitt 3) und Stückliste (Anhang B)
Taste „Next >“
Seite 25
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 5.6.: Dialog zur Erstellung eines
neuen Projekts (Schritt 4)
Hier können weitere (spezielle) Werkzeuge ausgewählt werden. Wir benötigen hier
keine.
Taste „Next >“
Bild 5.7.: Dialog zur Erstellung eines neuen
Projekts (Schritt 5, Zusammenfassung)
Abschließend erfolgt eine Zusammenfassung über die gewählten Einstellungen.
Taste „Finish“
Seite 26
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
1
2
Bild 5.8.: Arbeitsbereich nach dem Erstellen eines neuen Projekts
Bild 5.8. zeigt wieder den Arbeitsbereich der Entwicklungsumgebung. Im Gegensatz
zum Startbild (Bild 5.1) zeigt dieses nun ganz oben den Projekt-Ordner, den
Projektnamen und den Namen des Top-Level-Designs an (1) und im Abschnitt „Project
Navigator“befindet sich das gewählte CPLD (hier: EPM7128SLC84-15) und der Name
des Top-Level-Design (hier: dcf) (2). Nun folgt die Eingabe des Designs in der Sprache
AHDL.
Schritt 2: Eingabe des Designs in AHDL
Durch anklicken von „File“ und „New“ kann neues Design-File dem Projekt hinzugefügt
werden. Bild 5.9. zeigt eine Liste mit den möglichen Design-Arten. Wir wollen unser
Design in AHDL erstellen und wählen daher „AHDL File“ aus (1). Anschließend „OK“
(2).
1
2
Bild 5.9.: Design-File-Auswahl
Seite 27
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 5.10 zeigt nun den „neuen“ Arbeitsbereich. Im neuen Fenster erfolgt nun die
Eingabe der Code-Zeilen.
Bild 5.10.: Arbeitsbereich
Da wir unser Design in AHDL beschreiben wollen, zunächst den grundlegenden Aufbau
eines AHDL-Design-Files.
SUBDESIGN xxx
(
…
)
Name des Designs
VARIABLE
…
Werden im Design FlipFlops, Zähler, Schieberegister, usw.
verwendet, so werden diese hier definiert und ggf.
parametrisiert.
Hier werden alle Ein- und Ausgänge definiert.
BEGIN
…
END;
In diesem Block befindet sich die Beschreibung der Schaltung.
Auf den folgenden Seiten ist nun das AHDL-File für die DCF-Uhr in Form eines Listings
zu sehen. Man erkennt den soeben erwähnten Aufbau. Zur besseren Orientierung habe
ich auch die Zeilennummern angegeben, so wie sie auch in der Entwicklungsumgebung
angezeigt werden:
• In Zeile 27 erkennt man den Namen des Designs, hier: SUBDESIGN dcf.
• In den Zeilen 29 bis 52 werden alle Ein- und Ausgänge definiert (Anmerkung: Die
Zuweisung der Pinnummern erfolgt an anderer Stelle, siehe Schritt 5)
• In den Zeilen 57 bis 147 erfolgt die Definition und Einstellung aller verwendeten
Flipflops, Zähler, Schieberegister und der Zustandsmaschine.
• Ab Zeile 151 (bis zum Ende) beginnt schließlich die Beschreibung der Schaltung.
Seite 28
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Listing (dcf.tdf)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
%****************************************************************************%
%* DCF-Dekodierung (ohne Datum) (in AHDL) mit EPM7128S und 32,768-kHz-Takt *%
%*
*%
%* Entwickler: Buchgeher Stefan
*%
%* Entwicklungsbeginn: 28. Dezember 2004
*%
%* Funktionsfaehig seit: 3. Mai 2005
*%
%* Letzte Bearbeitung: 15. September 2005
*%
%****************************************************************************%
%***************** Include-Dateien ******************************************%
INCLUDE "lpm_counter.inc";
INCLUDE "lpm_shiftreg.inc";
%***************** Konstanten ***********************************************%
CONSTANT KONSTDCFLMIN = 28835;
% entspricht 880 ms %
CONSTANT KONSTDCFLMAX = 30147;
% entspricht 920 ms %
CONSTANT KONSTDCFHMIN = 24903;
% entspricht 760 ms %
CONSTANT KONSTDCFHMAX = 27526;
% entspricht 840 ms %
CONSTANT KONSTDCFMINMIN = 57671;
% entspricht 1760 ms %
CONSTANT KONSTDCFMINMAX = 62915;
% entspricht 1920 ms %
CONSTANT KONSTDCFTIMEOUT = 65400; % Time-Out %
CONSTANT KONST_ANZ_SR = 36;
% 36...0 %
%***************** Definition der Ein- und Ausgaenge ************************%
SUBDESIGN dcf
(
clock_DCF
: INPUT;
% System-Takt %
reset
: INPUT;
inDCF_In
: INPUT;
% DCFIN %
outSEK_Takt,
outDCF_Fehler
outDCF_Sync
: OUTPUT;
: OUTPUT;
% Zustandsanzeige "FEHLER" %
% Zustandsanzeige "SYNC" %
outDCF_BitFehler,
outDCF_Lo,
outDCF_Hi
: OUTPUT;
% Zustandsanzeige "?" %
% Zustandsanzeige "LO" %
% Zustandsanzeige "HI" %
outANZEIGE_EN
: OUTPUT;
% Aktiviert die Anzeige %
outSEK_E[3..0],
outSEK_Z[2..0]
: OUTPUT;
% Sekunden im BCD-Format %
outMIN_E[3..0],
outMIN_Z[2..0]
: OUTPUT;
% Minuten im BCD-Format %
outSTD_E[3..0],
outSTD_Z[1..0]
: OUTPUT;
% Stunde im BCD-Format %
)
%***************** Definition der Variablen *********************************%
VARIABLE
% D-FlipFlops %
iFF_DCF_In
: DFF;
% D-Flipflop zur Synchronisierung des
DCF-Eingangs %
iFF_DCF_Fehler
: DFFE;
iFF_DCF_Sync
: DFFE;
iFF_DCF_Lo
: DFFE;
iFF_DCF_Hi
: DFFE;
iFF_DCF_BitFehler
: DFFE;
Seite 29
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
.96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
% 16-Bit-Zaehler %
iZAEHLER_DCF
: lpm_counter WITH
(
LPM_WIDTH = 16,
LPM_DIRECTION = "UP"
);
% 15-Bit-Zaehler fuer 1-Hz-Takt %
iZAEHLER_Uhr
: lpm_counter WITH
(
LPM_WIDTH = 15,
LPM_DIRECTION = "UP"
);
% Sekunden - Zaehler 0-59 (BCD) %
iZAEHLER_SEK_E
: lpm_counter WITH
(
LPM_WIDTH = 4,
LPM_DIRECTION = "UP",
LPM_MODULUS = 10
);
iZAEHLER_SEK_Z
: lpm_counter WITH
(
LPM_WIDTH = 3,
LPM_DIRECTION = "UP",
LPM_MODULUS = 6
);
% Minuten - Zaehler 0-59 (BCD) %
iZAEHLER_MIN_E
: lpm_counter WITH
(
LPM_WIDTH = 4,
LPM_DIRECTION = "UP",
LPM_MODULUS = 10
);
iZAEHLER_MIN_Z
: lpm_counter WITH
(
LPM_WIDTH = 3,
LPM_DIRECTION = "UP",
LPM_MODULUS = 6
);
% Stunden - Zaehler 0-23 (BCD) %
iZAEHLER_STD_E
: lpm_counter WITH
(
LPM_WIDTH = 4,
LPM_DIRECTION = "UP",
LPM_MODULUS = 10
);
iZAEHLER_STD_Z
: lpm_counter WITH
(
LPM_WIDTH = 2,
LPM_DIRECTION = "UP",
LPM_MODULUS = 4
);
% 37-Bit-Schieberegister %
iSR_DCF
: lpm_shiftreg WITH
(
LPM_WIDTH = KONST_ANZ_SR + 1
);
% Zustandsmaschine fuer die DCF-Dekodierung %
iZM_DCF
: MACHINE OF BITS (q[2..0])
WITH STATES
Seite 30
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
138
(
139
z0 = B"000",
140
z1 = B"001",
141
z2 = B"010",
142
z3 = B"011",
143
z4 = B"100",
144
z5 = B"101",
145
z6 = B"110",
146
z7 = B"111"
147
);
148
149
150 %***************** Beginn der Schaltungsbeschreibung ************************%
151 BEGIN
152
% Synchronisation des DCF-Eingangs mit einem D-Flopflop %
153
iFF_DCF_In.clk = clock_DCF;
154
iFF_DCF_In.d = inDCF_In;
155
iFF_DCF_In.prn = VCC;
156
iFF_DCF_In.clrn = VCC;
157
158
% FlipFlops (Takt, Reset und nicht benoetigte Eingaenge) %
159
iFF_DCF_Fehler.clk = clock_DCF;
160
iFF_DCF_Fehler.prn = reset;
161
iFF_DCF_Fehler.clrn = VCC;
162
163
iFF_DCF_Sync.clk = clock_DCF;
164
iFF_DCF_Sync.clrn = reset;
165
iFF_DCF_Sync.prn = VCC;
166
167
iFF_DCF_Lo.clk = clock_DCF;
168
iFF_DCF_lo.clrn = reset;
169
iFF_DCF_lo.prn = VCC;
170
171
iFF_DCF_Hi.clk = clock_DCF;
172
iFF_DCF_Hi.clrn = reset;
173
iFF_DCF_Hi.prn = VCC;
174
175
iFF_DCF_BitFehler.clk = clock_DCF;
176
iFF_DCF_BitFehler.clrn = reset;
177
iFF_DCF_BitFehler.prn = VCC;
178
179
% Zaehler (Takt) %
180
iZAEHLER_DCF.clock = clock_DCF;
181
iZAEHLER_Uhr.clock = clock_DCF;
182
183
iZAEHLER_SEK_E.clock = iZAEHLER_Uhr.q[14];
184
iZAEHLER_SEK_Z.clock = !iZAEHLER_SEK_E.q[3];
185
iZAEHLER_MIN_E.clock = !iZAEHLER_SEK_Z.q[2];
186
iZAEHLER_MIN_Z.clock = !iZAEHLER_MIN_E.q[3];
187
iZAEHLER_STD_E.clock = !iZAEHLER_MIN_Z.q[2];
188
iZAEHLER_STD_Z.clock = !iZAEHLER_STD_E.q[3];
189
190
191
% Schieberegister (Takt) %
192
iSR_DCF.clock = clock_DCF;
193
194
195
% Zustandsmaschine %
196
iZM_DCF.clk = clock_DCF;
197
iZM_DCF.reset = !reset;
198
199
CASE iZM_DCF IS
200
WHEN z0 =>
% Ausgangszustand (iZAEHLER_DCF loeschen) %
201
iZAEHLER_DCF.aclr = VCC;
202
IF iFF_DCF_In.q THEN
203
iZM_DCF = z1;
204
END IF;
205
206
207
WHEN z1 =>
% iZAEHLER_DCF freigeben (=starten) %
Seite 31
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
iZAEHLER_DCF.cnt_en = VCC;
iZAEHLER_DCF.clk_en = VCC;
IF !iFF_DCF_In.q THEN
iZM_DCF = z2;
ELSIF (iZAEHLER_DCF.q[] >= KONSTDCFTIMEOUT) THEN
iZM_DCF = z7;
END IF;
WHEN z2 =>
IF ((iZAEHLER_DCF.q[] >= KONSTDCFLMIN) &
(iZAEHLER_DCF.q[] <= KONSTDCFLMAX)) THEN
% LOW %
iZM_DCF = z3;
ELSIF ((iZAEHLER_DCF.q[] >= KONSTDCFHMIN) &
(iZAEHLER_DCF.q[] <= KONSTDCFHMAX)) THEN
% HIGH %
iZM_DCF = z4;
ELSIF ((iZAEHLER_DCF.q[] >= KONSTDCFMINMIN) &
(iZAEHLER_DCF.q[] <= KONSTDCFMINMAX)) THEN % Min-Wechsel%
IF iFF_DCF_Fehler.q THEN
iZM_DCF = z6;
ELSE
iZM_DCF = z5;
END IF;
ELSE
iZM_DCF = z7;
END IF;
% Fehler %
WHEN z3 =>
iSR_DCF.enable = VCC;
% LOW dem Schieberegister hinzufuegen %
iFF_DCF_Lo.d = VCC;
% iFF_DCF_Lo setzen %
iFF_DCF_Lo.ena = VCC;
iFF_DCF_Hi.ena = VCC;
% iFF_DCF_Hi loeschen %
iFF_DCF_BitFehler.ena = VCC; % iFF_BitFehler loeschen %
iZM_DCF = z0;
% Naechster Zustand %
WHEN z4 =>
iSR_DCF.shiftin = VCC;
iSR_DCF.enable = VCC;
% High dem Schieberegister hinzufuegen %
iFF_DCF_Hi.d = VCC;
% iFF_DCF_Hi setzen %
iFF_DCF_Hi.ena = VCC;
iFF_DCF_Lo.ena = VCC;
% iFF_DCF_Lo loeschen %
iFF_DCF_BitFehler.ena = VCC; % iFF_BitFehler loeschen %
iZM_DCF = z0;
% Naechster Zustand %
WHEN z5 =>
% Neue Minute und gueltiges Telegramm %
iFF_DCF_Sync.d = VCC;
iFF_DCF_Sync.ena = VCC; % iFF_DCF_Sync setzen %
iZAEHLER_Uhr.aclr = VCC; % iZAEHLER_Uhr loeschen %
iZAEHLER_SEK_E.aclr = VCC; % iZAEHLER_SEK_E loeschen %
iZAEHLER_SEK_Z.aclr = VCC; % iZAEHLER_SEK_Z loeschen %
iZAEHLER_MIN_E.aload = VCC; % iZAEHLER_MIN_E laden %
iZAEHLER_MIN_Z.aload = VCC; % iZAEHLER_MIN_Z laden %
iZAEHLER_STD_E.aload = VCC; % iZAEHLER_STD_E laden %
iZAEHLER_STD_Z.aload = VCC; % iZAEHLER_STD_Z laden %
iZM_DCF = z0;
% Naechster Zustand %
Seite 32
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
278
279
WHEN z6 =>
% iFF_DCF_Fehler loeschen %
280
iFF_DCF_Fehler.ena = VCC;
281
iZM_DCF = z0;
% Naechster Zustand %
282
283
284
WHEN z7 =>
285
iFF_DCF_Fehler.d = VCC;
% iFF_DCF_Fehler setzen %
286
iFF_DCF_Fehler.ena = VCC;
287
288
iFF_DCF_BitFehler.d = VCC; % iFF_DCF_BitFehler setzen %
289
iFF_DCF_BitFehler.ena = VCC;
290
iFF_DCF_Lo.ena = VCC;
% iFF_DCF_Lo loeschen %
291
iFF_DCF_Hi.ena = VCC;
% iFF_DCF_Hi loeschen %
292
293
iZM_DCF = z0;
% Naechster Zustand %
294
END CASE;
295
296
297
% Schieberegister - Zaehler fuer Uhrzeit und Datum %
298
iZAEHLER_MIN_E.data[0] = iSR_DCF.q[36];
299
iZAEHLER_MIN_E.data[1] = iSR_DCF.q[35];
300
iZAEHLER_MIN_E.data[2] = iSR_DCF.q[34];
301
iZAEHLER_MIN_E.data[3] = iSR_DCF.q[33];
302
iZAEHLER_MIN_Z.data[0] = iSR_DCF.q[32];
303
iZAEHLER_MIN_Z.data[1] = iSR_DCF.q[31];
304
iZAEHLER_MIN_Z.data[2] = iSR_DCF.q[30];
305
306
iZAEHLER_STD_E.data[0] = iSR_DCF.q[28];
307
iZAEHLER_STD_E.data[1] = iSR_DCF.q[27];
308
iZAEHLER_STD_E.data[2] = iSR_DCF.q[26];
309
iZAEHLER_STD_E.data[3] = iSR_DCF.q[25];
310
iZAEHLER_STD_Z.data[0] = iSR_DCF.q[24];
311
iZAEHLER_STD_Z.data[1] = iSR_DCF.q[23];
312
iZAEHLER_STD_Z.aclr = iZAEHLER_STD_Z.q[1] & iZAEHLER_STD_E.q[2];
313
iZAEHLER_STD_E.aclr = iZAEHLER_STD_Z.q[1] & iZAEHLER_STD_E.q[2];
314
315
316
% Zaehler Uhr - FF Sync %
317
iZAEHLER_Uhr.cnt_en = iFF_DCF_Sync.q;
318
iZAEHLER_Uhr.clk_en = iFF_DCF_Sync.q;
319
320
321
% Ausgaenge %
322
outDCF_Fehler = iFF_DCF_Fehler.q;
323
outSEK_Takt = iZAEHLER_Uhr.q[14];
324
325
outDCF_Sync = iFF_DCF_Sync.q;
326
327
outDCF_Lo = iFF_DCF_Lo.q;
328
outDCF_Hi = iFF_DCF_Hi.q;
329
outDCF_BitFehler = iFF_DCF_BitFehler.q;
330
331
outSEK_E[] = iZAEHLER_SEK_E.q[];
332
outSEK_Z[] = iZAEHLER_SEK_Z.q[];
333
334
outMIN_E[] = iZAEHLER_MIN_E.q[];
335
outMIN_Z[] = iZAEHLER_MIN_Z.q[];
336
337
outSTD_E[] = iZAEHLER_STD_E.q[];
338
outSTD_Z[] = iZAEHLER_STD_Z.q[];
339
340
outANZEIGE_EN = iFF_DCF_Sync.q;
341 END;
Seite 33
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Anmerkungen und Erläuterungen zum Design-File:
• Das Design-File sieht wie ein Listing eines z.B. C-Programms aus. Es ist aber zu
beachten, dass es sich hier keinesfalls um ein Programm handelt, welches
sequentiell (also Schritt-für-Schritt) abgearbeitet wird. Hier handelt es sich um die
Beschreibung einer Schaltung!
• Die Zeilen 1 bis 8 sind Kommentare und dienen der Kurzbeschreibung der Software,
den Namen des Entwicklers und einige zusätzliche Informationen. (Anmerkung:
Kommentare befinden sich in AHDL zwischen zwei %-Zeichen, z.B. % Kommentar
%)
• In den Zeilen 11 und 12 werden die von ALTERA zur Verfügung gestellten
Bibliotheken eingebunden. Hier für die verwendeten Zähler (iZAEHLERxxx) und für
das Schieberegister (iSR_DCF)
• Im Design werden mehrere Konstanten verwendet. (Hier u.a. zur Unterscheidung
zwischen den Low- und High-Bits, einem Minutenwechsel, usw.) Konstanten werden
in AHDL mit dem Schlüsselwort CONSTANT definiert. In den Zeilen 16 bis 23 werden
alle in diesem Design verwendeten Konstanten definiert.
• In den Zeilen 29 bis 52 werden alle Ein- und Ausgänge definiert. Hier lautet die
AHDL-Syntax: Name des Ein- oder Ausgangs : Typ; (Als Typ kann
verwendet werden: INPUT (für Eingang), OUTPUT (für Ausgang) oder BIDIR (für
bidirektional).
• Die Zeilen 59 bis 65 definieren die verwendeten FlipFlops. Hier lautet die AHDLSyntax: Name des FlipFlops : FlipFlop-Typ; (Als FlipFlop-Typen stehen
z.B, DFF (D-FlipFlop), DFFE (D-FlipFlop mit Freigabe), SRFF (S-R-FlipFlop), SRFFE
(S-R-FlipFlop mit Freigabe), JKFF (J-K-FlipFlop), JKFFE (J-K-FlipFlop mit Freigabe)
usw. zur Verfügung)
• Die Zeilen 68 bis 125 definieren die verwendeten Zähler. Hier lautet die AHDLSyntax: Name des Zählers : lpm_counter WITH ( PARAMETERLISTE );
(Die Parameterliste beinhaltet zumindest die Anzahl der Bits (LPM_WIDTH). Weiters
können hier Parameter wie die Zählrichtung (LPM_DIRECTION), die obere
Zählgrenze (LPM_MODULUS), usw. definiert werden. Die obere Zählgrenze ist bei
dieser Anwendung ganz besonders wichtig. Denn der Zähler iZAEHLER_SEK_Z soll
beispielsweise nur von 0 bis 5 zählen. Daher ist für diesen Parameter der Wert 6
notwendig. Der folgende Programmausschnitt (Zeilen 90 bis 95) zeigt die Definition
für diesen Zähler.
90 iZAEHLER_SEK_Z
91
92
93
94
95
•
•
•
: lpm_counter WITH
(
LPM_WIDTH = 3,
LPM_DIRECTION = "UP",
LPM_MODULUS = 6
);
Die Zeilen 129 bis 132 definieren das verwendete Schieberegister (iSR_DCF). Hier
lautet die AHDL-Syntax: Name des Schieberegisters : lpm_shiftreg
WITH ( PARAMETERLISTE ); (Die Parameterliste beinhaltet zumindest die
Anzahl der Bits (LPM_WIDTH). Weiters können hier Parameter wie z.B. die
Schieberichtung (LPM_DIRECTION), usw. definiert werden.
Die Zeilen 136 bis 147 definieren die verwendete Zustandsmaschine (iZM_DCF).
Hier lautet die AHDL-Syntax: Name der Zustandsmaschine : MACHINE OF
BITS (Bitanzahl) WITH STATES (Z0 = 0, Z1 = 1, Z2 = 2 usw. );
Nun beginnt ab Zeile 151 die Beschreibung des Designs vom Bild 12a.
Seite 34
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
•
Die Zeilen 153 bis156 beschreiben die Eingänge des FlipFlops zur Synchronisierung
des DCF-Eingangs. Dieses FlipFlop hat die Bezeichnung iFF_DCF_In. Die
verschiedenen Eingänge eines Objektes werden folgendermaßen angesprochen:
Objekt.Eingang
(z.B. Dateneingang des FlipFlops zur Synchronisierung: iFF_DCF_in.d oder
Takteingang des Sekundentakt-Zählers iZAEHLER_Uhr.clock)
Zurück zum FlipFlop zur Synchronisierung des DCF-Eingangs. Gemäß dem Design
(Bild 5.12a) ist der Takteingang dieses Flipflops mit dem Systemtakt verbunden,
daher lautet die AHDL-Anweisung:
iFF_DCF_In.clk = clock_DCF; (Zeile 153),
Der Dateneingang ist mit dem DCF-Eingang verbunden, die AHDL-Anweisung lautet
daher:
iFF_DCF_In.d = inDCF_In; (Zeile 154)
Sowohl der Set- als auch der Reset-Eingang dieses FlipFlops sind mit VCC
verbunden. Die AHDL-Anweisungen lauten daher:
iFF_DCF_In.prn = VCC; (für Set-Eingang; Zeile 155)
iFF_DCF_In.clrn = VCC; (für Reset-Eingang; Zeile 156)
•
•
Die Zeilen 159 bis 177 beschreiben die Eingänge der restlichen FlipFlops, mit
Ausnahme der Dateneingänge. Die Dateneingänge stammen von der Zustandsmaschine (iZM_DCF) und werden an anderer Stelle beschrieben. Der System-Reset
stammt aus der Hardwarebeschaltung des CPLDs und ist lowaktiv (siehe auch
Abschnitt 3). Lowaktiv sind auch die Set und Reset-Eingänge der FlipFlops, sodass
diese direkt mit dem System-Reset verbunden werden können.
Die Zeilen 180 bis 188 beschreiben die Verdrahtung der Takteingänge für die
Zähler. Die Zähler iZAEHLER_DCF und iZAEHLER_Uhr sind mit dem Systemtakt
(clock_DCF) verbunden. In AHDL lautet diese Verbindungen daher
iZAEHLER_DCF.clock = clock_DCF; (Zeile 180)
iZAEHLER_Uhr.clock = clock_DCF; (Zeile 181)
Die weiteren Zähler (für die Uhrzeit) sind „hintereinander“ geschaltet, d.h. der Takt
eines Zählers stammt von einem Ausgang des vorhergehenden Zählers. (siehe Bild
5.12a) Weiters muss dieser Ausgang negiert werden. Für die Negierung wird in
AHDL ein “!“ verwendet. Somit lautet die AHDL-Anweisung für den Takteingang des
Zählers iZAEHLER_SEK_Z:
iZAEHLER_SEK_Z.clock = !iZAEHLER_SEK_E.q[3]; (Zeile 184)
Anmerkung: Der Zähler iZAEHLER_SEK_E ist ein 4-bit-Zähler. Das heißt er besitzt
daher 4 Ausgänge. Die eckige Klammer gibt an welche der 4 Ausgänge benutzt
wird, wobei beim Zählen mit 0 begonnen wird. [3] bedeutet daher, dass der vierte
Ausgang benutzt wird.
Seite 35
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
•
•
Zeile 192 beschreibt die Verdrahtung des Takteingangs für das Schieberegister. Als
Takt für das Schieberegister wird wieder der Systemtakt verwendet.
Die Zeilen 196 bis 294 zeigen die Umsetzung der Zustandsmaschine (iZM_DCF). Zu
Beginn erfolgen die Verdrahtungen für den Systemtakt (clock_DCF, Zeile 196) und
für den Reset (Zeile 197). Der System-Reset stammt aus der Hardwarebeschaltung
des CPLDs und ist lowaktiv (siehe auch Abschnitt 3). Der Reset-Eingang einer
Zustandsmaschine ist aber highaktiv. D.h. als Reset-Eingang muss der invertierte
Systemreset verwendet werden (Zeile 197).
Die Realisierung einer Zustandsmaschine sieht in AHDL wie folgt aus:
CASE Name der Zustandsmaschine IS
WHEN Zustand 0 =>
Anweisung1;
Anweisung2;
…
Anweisungn;
Übergang zum nächsten Zustand;
WHEN Zustand 1 =>
Anweisung1;
Anweisung2;
…
Anweisungn;
Übergang zum nächsten Zustand;
WHEN Zustand 2 =>
…
WHEN Zustand n =>
END CASE;
•
•
Die Zeilen 298 bis 311 zeigen die Umsetzung der Verbindungen zwischen den
Ausgängen des Schieberegisters (iSR_DCF) und den zu ladenden Zählern für die
(mitlaufende) Uhr.
Die Zeilen 312 und 313 zeigen die Realisierung des UND-Gatters beim StundenZähler (siehe Bild 4.10 und Bild 4.12a). Eine UND-Verknüpfung erfolgt in AHDL mit
dem „&“-Symbol. Tabelle 5.1. zeigt die wichtigsten logischen Verknüpfungen:
Verknüpfung
Symbol
UND
&
ODER
#
EXOR
$
NICHT
!
Tabelle 5.1.: logische Verknüpfungen
•
•
Die Zeilen 317 und 318 zeigen die Realisierung der Freigabe für den SekundenTakt-Zähler (iZAEHLER_Uhr)
Die Zeilen 322 bis 340 zeigen die Verdrahtungen aller verwendeten CPLDAusgänge. Anmerkung: eine leere, eckige Klammer bedeutet dass diese Anweisung
für alle Ausgänge dieses Namens gilt. Die Zeile 331
outSEK_E[] = iZAEHLER_SEK_E.q[];
Seite 36
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
bedeutet daher dass die vier Ausgänge outSEK_E[3..0] mit den vier Ausgängen des
Zählers iZAEHLER_SEK_E verbunden werden. Diese Anweisung ersetzt daher
folgende vier Anweisungen:
outSEK_E[0]
outSEK_E[1]
outSEK_E[2]
outSEK_E[3]
•
=
=
=
=
iZAEHLER_SEK_E.q[0];
iZAEHLER_SEK_E.q[1];
iZAEHLER_SEK_E.q[2];
iZAEHLER_SEK_E.q[3];
Wichtig: Die Indizes von outSEK_E und iZAEHLER_SEK_E müssen natürlich gleich
groß sein. Ansonst tritt beim Kompilieren eine Fehlermeldung aus.
Die Anweisung END; in Zeile 341 bedeutet das Ende der AHDL-Datei.
Das folgende Bild zeigt einen Ausschnitt des soeben beschriebenen AHDL-Files
(Listings)
Bild 5.11.: AHDL-Design-File (Ausschnitt)
Man erkennt sehr gut die farblichen Unterschiede, was die Arbeit und die Fehlersuche
erheblich erleichtert. Die folgende Tabelle zeigt einen Ausschnitt
• Blau:
AHDL-Schlüsselwörter
• Schwarz:
Name von Elementen (FlipFlops, Zähler, usw.), Ein- und
Ausgängen, Zuweisungen
• Grün:
Kommentare
• Hellgrau:
Zeilennummern
Seite 37
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Schritt 3: Systemtakt definieren
Nach anklicken von „Assignments“ und „Timing Settings…“ gelangt man zum folgenden
Bild (Bild 5.12).
1
2
Bild 5.12.: Timing Requirements & Options
Unter „Category“ den Eintrag „Timing Requirements & Options” auswählen (1)
Unter “Clock Settings” die Option “Settings for individual clock signals” auswählen (2)
und die Taste “Clocks…” anklicken.
Bild 5.13.: Eingabebox “Clocks”
Taste “New…”
Seite 38
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 5.14.: Eingabebox “New Clocks Settings”
Clock settings name: ein beliebiger Name
Applies to node: clock_DCF (Wichtig: Dieser Name muss mit dem Systemtakt im AHDLFile übereinstimmen!)
Required fmax: Hier gibt man die Taktfrequenz mit der richtigen Einheit an. Hier, bei
diesem Projekt handelt es sich um einen 32768-Hz-Takt (Siehe auch Abschnitt 3)
Duty cycle (%): Hier lässt man den Standardwert von 50.
Taste „OK“
Bild 5.15.: Eingabebox “Clocks” mit ausgewähltem Systemtakt
Taste „OK“ (2 mal)
Schritt 4: Erste Kompilierung
Nun erfolgt zum ersten Mal eine Kompilierung des Designs. Dies ist jetzt schon
notwendig, damit später (im Schritt 5) allen Ein- und Ausgängen die richtigen
Pinnummern zugewiesen werden können. Weiters wir beim Kompilieren (wie auch bei
anderen Programmiersprachen) das Design auf syntaktische Fehler überprüft.
Seite 39
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 5.16.: Kompilierung (Start)
Eine Kompilierung wird mit dem violetten Dreieck in der Symbolleiste (siehe Bild 5.16)
gestartet.
1
2
Bild 5.17.: Kompilierung
Bild 5.17. zeigt die Entwicklungsumgebung während der Kompilierung. Der Bereich
„Status“ (1) zeigt den Fortschritt an und der Bereich 2 gibt Auskunft was gemacht
wurde. Hier erscheinen auch Warnungen und (syntaktische) Fehler. Wird ein solcher
Fehler von der Entwicklungsumgebung entdeckt, so wird die Kompilierung
abgebrochen. Der Fehler muss natürlich gefunden und behoben werden, gefolgt von
Seite 40
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
einer neuen Kompilierung. Dieser Vorgang muss natürlich so oft wiederholt werden bis
keine Fehler mehr auftreten. Warnungen können natürlich schon auftreten. Diese
sollten aber nie völlig ignoriert werden. Es sollte immer überprüft werden, ob diese
Warnung „gewollt“ ist, oder ob beim Designentwurf etwas übersehen wurde. Was ich
damit meine, wird hoffentlich gleich klar.
Wurde die Kompilierung erfolgreich durchgeführt, so erscheint der folgende Hinweis
(Bild 5.18).
Bild 5.18.: Box „Kompilierung erfolgreich“
Hier, bei diesem Projekt trat beim Kompilieren eine Warnung auf. Bild 5.19. gibt
Auskunft über diese Warnung(en) (1). Weiters eine kleine Statistik über die Anzahl der
benötigten Makrozellen und Pins (2).
2
1
Bild 5.19.: Kompilierung (Endergebnis)
Da beim Kompilieren eine Warnung aufgetreten ist, sollte diese nun überprüft werden.
Bei den Warnungen handelt es sich hier um den Hinweis, dass ein so genannter „Ripple
Counter“ erzeugt wurde. Dies wurde aber beabsichtigt, da wir ja die freilaufende Uhr
tatsächlich als „Ripple Counter“ aufgebaut haben (siehe Bild 4.12a). Diese Warnung
kann also ignoriert werden.
Seite 41
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Schritt 5: Pinnummern zuweisen
Nach erfolgreicher erster Kompilierung können nun die Pinnummern den Ein- und
Ausgängen zugeordnet werden. Für diesen Schritt gibt es in Quartus mehrere
Möglichkeiten. Den „Pin-Planer“ möchte ich hier vorstellen. Dieser ist gerade bei
„kleineren“ CPLDs (so wie hier) sehr übersichtlich.
Nach anklicken von „Assignments“ und „Pin Planer“ gelangt man zum folgenden Bild
(Bild 5.20).
1
Bild 5.20.: Pin Planer
Zur besseren Übersicht sollte man hier in den „Vollbildmodus“ übergehen (1)
Vorgehensweise:
1. Aus der Liste „Unassigned Pins“ wählt man einen Pin („Node Name“) durch
einfaches anklicken aus.
2. Mit gedrückter Maustaste zieht man diesen nun auf den gewünschten Pin des
CPLDs (mittlerer Bildbereich). Der Mauszeiger zeigt an, ob an dieser Stelle ein
Pin zugeordnet werden kann.
3. Maustaste loslassen. In der Liste „Assigned Pins“ erscheint nun dieser Ein- oder
Ausgang mit der dazu ausgewählten Pinnummer. Zusätzlich wird dieser in der
grafischen Ansicht (Bildmitte) durch einen ausgefüllten Kreis dargestellt. (Bild
5.21. zeigt dies für den Ausgang „outANZEIGE_EN“ ,Pin 16)
Seite 42
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
2
1
Bild 5.21.: Pin Planer
Sind alle Ein- und Ausgänge zugeordnet, so sollte dies dem Bild 5.22 entsprechen.
1
Bild 5.22.: Pin Planer
Nun sollte wieder in die „gewohnte Ansicht“ zurückgekehrt werden (1)
Schritt 6: Zweite Kompilierung
Zum Abschluss muss die Kompilierung wiederholt werden. (gemäß Schritt 4)
Seite 43
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
6.
Simulation
Der nächste Schritt, nach dem Entwurf und der Eingabe des Designs, ist die Simulation.
Dabei wird überprüft ob das Design die geforderten Aufgaben erfüllt.
Das Grundprinzip der Simulation ist, dass man an den Eingängen des Designs so
genannte Eingangsvektoren anlegt, die auch in der Realität auftreten. Diesen
Eingangsvektor nennt man auch Stimuli. Aus diesen Eingangsvektoren ermittelt die
Entwicklungsumgebung alle Ausgänge des Designs und zeigt diese grafisch an. Daraus
lässt sich dann erkennen, ob das erstellte Design auch wirklich die geforderten
Aufgaben erfüllt.
Für die Simulation gibt es in Quartus mehrere Möglichkeiten. Ich möchte hier eine
grafische Methode mit Hilfe eines „Vector Waveform File“ (.vwf) vorstellen.
Schritt 1: Ein Vector Waveform File für dieses Projekt
erzeugen
Durch anklicken von „File“ und „New…“ wird ein neues File geöffnet. Hier soll nun ein
„Vector Waveform File“ geöffnet werden. Dies befindet sich unter „Other Files“ (siehe
Bild 6.1.)
1
2
Bild 6.1.: Waveform File erzeugen
Nach anklicken der „OK“-Taste zeigt Bild 6.2. den „neuen“ Arbeitsbereich. Im neuen
Fenster erfolgt nun die Eingabe der Eingangsvektoren.
Seite 44
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 6.2.: Waveform File erzeugen
Ein nützliches Werkzeug ist der so genannte „Node Finder“. Dieser wird wie folgt
aufgerufen: „View“ à „Utility Windows“ à „Node Finder“. Man schiebt ihn am Besten
neben den „Projekt Navigator“. Mit Hilfe dieses „Node Finder“ können ganz bequem die
zu simulierenden Ein- und Ausgänge ausgewählt werden. Im Filter sollte „Design Entry
(all Names)“ ausgewählt werden. Damit können „Komponenten“ innerhalb eines
Designs simuliert werden. Ein Klick auf die Taste „List“ zeigt nun alle auszuwählenden
„Komponenten“ (siehe Bild 6.3).
Bild 6.3.: Waveform File erzeugen
Seite 45
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Wichtig: Damit der „Node Finder“ wie der Name schon sagt etwas findet, muss das
Design kompiliert werden. (Dies erfolgte schon, und ist daher jetzt nicht notwendig!)
Als erstes definieren wir das zu simulierende Zeitfenster. Fürs erste interessiere ich
mich ob die Low- und High-Impulse des DCF-Datenstroms richtig ausgewertet werden.
Daher ist zunächst mal ein Zeitfenster von, sagen wir mal, 5 Sekunden notwendig.
Diese Einstellung erfolgt mit „Edit“ (ganz oben in der Symbolleiste) è „End Time…“
Bild 6.4.: Waveform File erzeugen
Nach der Bestätigung („OK“) sollte der ganz rechte Bereich so eingestellt werden, dass
der gesamte Zeitbereich sichtbar ist. Dazu mit der Maus in diesen Bereich klicken à
rechte Maustaste à „Zoom“ à „Fit in Window“ anklicken.
Als nächsten Schritt wollen wir nun alle Eingangsvektoren definieren. Als erstes ziehen
wir „clock_DCF“ mit gedrückter Maustaste vom „Node Finder“ in das Feld rechts neben
den „Node Finder“. Dies ist ja unser Systemtakt, welchen wir schon an anderer Stelle
definiert haben (siehe Schritt 3 im Abschnitt 5). Diesen Takt machen wir nun sichtbar,
indem wir auf „clock_DCF“ klicken à rechte Maustaste à „Value“ à „Clock…“
Bild 6.5.: Waveform File erzeugen
In dieser Box wählen wir die Option „Clock settings“ (Bild 6.5.) und anschließend „OK“.
Nun erscheint ein schwarzer Balken. Das ist schon okay. Denn wir haben hier einen
Systemtakt von 32768 Hz. Bei einem Zeitfenster von 5 Sekunden ergeben sich somit 5
x 32768 = 163840 Takte. Diese können vom Bildschirm und vom menschlichen Auge
nicht mehr als einzelne Taktimpulse aufgelöst werden. Es erscheint daher nur mehr ein
Balken.
Als nächstes definieren wir den Reset-Eingang. Zunächst ziehen wir diesen wieder mit
gedrückter Maustaste vom „Node Finder“ in das Feld rechts neben den „Node Finder“.
Hier, bei diesem Projekt ergibt sich der Reset aus der Hardware. Beim Einschalten der
Betriebsspannung ist der Reset für kurze Zeit Low. Danach, bis zum Ausschalten High.
Wir müssen daher für die Simulation dieses Verhalten nachbilden. Dies geschieht am
Einfachsten indem man mit der Maus ein Rechteck an der gewünschten Stelle aufzieht.
Dieses Rechteck wird hellblau dargestellt, (1) im Bild 6.6. Ein Klick auf „Forcing High“
(Symbol in der Toolbar zwischen „Project Navigator“ und „Node Finder“) ändert den
hellblauen Bereich in einen High-Pegel (2) im Bild 6.6.
Seite 46
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
2
1
Bild 6.6.: Waveform File erzeugen
Nun zum etwas aufwendigeren Teil. Als nächstes wollen wir den Eingang inDCF_In
(also den auszuwertenden DCF-Datenstrom) erstellen. Bild 6.7. zeigt dazu ein Beispiel.
Im Ruhezustand ist dieser Eingang High. Nach etwa einer Sekunde erfolgt für etwa
100ms ein Low-Impuls. Nach etwa zwei Sekunden ein 200ms langer Low-Impuls und
nach drei Sekunden wieder ein 100ms langer Low-Impuls. Zwischen der dritten und
vierten Sekunde soll ein kurzer Störimpuls auftreten und nach vier Sekunden wieder ein
200ms langer Low-Impuls (siehe Bild 6.7.)
Bild 6.7.: Waveform File erzeugen
Seite 47
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Als letztes müssen wir noch die Ausgänge angeben, die uns für diese Simulation
interessieren. Interessant sind hier zunächst nur die Ausgänge outDCF_Lo, outDCF_Hi
und outDCF_BitFehler. Interessant ist darüber hinaus auch das Verhalten der
Zustandsmaschine (iZM_DCF). Bild 6.8. zeigt die so entstandenen „Eingangsvektoren“.
Zur besseren Übersicht werden die Ausgänge „zaunartig“ dargestellt.
Bild 6.8.: Waveform File erzeugen
Abschließend muss diese Datei noch gespeichert werden. Ich persönlich lege für die
Eingangsvektoren (Stimuli) in einen eigenen Ordner namens „Stimuli“ im Projektordner
ab. Also „File“ à “Save“ oder „Save As“ à Bild 6.9. (Wichtig ist hier der Dateityp:
„Vector Waveform file“). Nennen wir diese Datei „dcf1“ à Taste „Speichern“
Bild 6.9.: Waveform File speichern
Schritt 2: Simulator-Einstellungen
Nach anklicken von „Assignments“ und „Settings“ gelangt man zum folgenden Bild (Bild
6.10).
Seite 48
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
2
1
Bild 6.10.: Simulator-Einstellungen
In der linken Liste „Simulator“ auswählen (1). Als „Simulation input“ das im Schritt 1
erzeugte Waveform File („dcf1.vwf“) (2).
Altera empfiehlt weiters die Option „Run simulation until all vector stimuli are used“,
„Automatically add pins to simulation output waveforms” und “Simulation coverage
reporting” (siehe Bild 6.10.)
Schritt 3: Simulation beginnen
Die Simulation wird mit dem Symbol „Start Simulation“ (gemäß Bild 6.11.) gestartet.
Bild 6.11.: Simulation starten
Die Dauer der Simulation hängt davon ab, wie groß die „End-Time“ (siehe Bild 6.4.)
gewählt wurde, und natürlich auch von der Leistungsfähigkeit des verwendeten
Computers. Hier, dauert die Simulation bei mir ca. 2 Minuten
Konnte die Simulation erfolgreich durchgeführt werden, erscheint ein Hinweis gemäß
Bild 6.12. Konnte die Simulation nicht erfolgreich durchgeführt werden, so müssen
natürlich die Fehler gesucht und behoben werden!
Bild 6.12.: Erfolgreiche Simulation
Seite 49
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Schritt 4: Simulationsergebnis analysieren
Bild 6.13.: Simulationsergebnis
Im Bild 6.13. erkennt man sehr gut, wie der Eingang (also der DCF-Datenstrom,
inDCF_in) ausgewertet wird. Der Ausgang „outDCF_Lo“ wird logisch „1“ nach einem
kurzen Impuls (ca. 100ms) und der nächsten steigenden Flanke vom Eingang
(inDCF_In), und der Ausgang „outDCF_Hi“ wird logisch „1“ nach einem langen Impuls
(ca. 200ms) und der nächsten steigenden Flanke vom Eingang (inDCF_In). Bei einem
„ungültigen“ Impuls des Eingangs wird der Ausgang „outDCF_BitFehler“ logisch „1“.
Die erste Simulation war also erfolgreich. Als nächstes wollen wir einen Zeitbereich von
ca. 80 Sekunden simulieren, damit wir sehen wie das Design ein komplettes DCFTelegramm einließt, und ob dann die freilaufende Uhr zu starten beginnt.
Schritt 5: Zweite Simulation
Wir erzeugen zunächst ein zweites Vector Waveform File. Wir wiederholen also die
Schritte 1 bis 4. Dieses File speichern wir unter „dcf2.vwf“ im Unterordner „Stimuli“. Als
„End Time“ geben wir hier 80 Sekunden ein.
Bild 6.14 zeigt dieses Vector Waveform File. Man erkennt bei ca. 10 Sekunden und bei
ca. 70 Sekunden, dass hier keine Impulse vorhanden sind. Diese sind die
Minutenmarken (gemäß dem DCF-Protokoll). Die kurzen und langen Impulse wurden so
gewählt, dass beim Simulieren eine sinnvolle Uhrzeit und ein sinnvolles Datum
zustande kommen.
Seite 50
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 6.14.: Zweite Simulation
Diese Simulation wird etwas mehr Zeit in Anspruch nehmen. Bei mir dauerte diese
Simulation ca. 28 Minuten!
Bild 6.15. zeigt das Simulationsergebnis.
Bild 6.15.: Ergebnis der zweiten Simulation
Seite 51
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Das Simulationsergebnis lässt sich mit der Taste „Full Screen“ (siehe Bild 6.15) zur
besseren Übersicht vergrößern. Bild 6.16. zeigt dasselbe Simulationsergebnis in
vergrößerter Darstellung.
Bild 6.16.: Ergebnis der zweiten Simulation (vergrößert)
Die Simulation zeigt sehr schön das Verhalten des Designs. Zu Beginn ist der Ausgang
„outDCF_Fehler“ gesetzt. Bei Sekunde 10 bleibt die Absenkung des DCF-Datenstroms
(Eingang inDCF_In) aus. Es erfolgt also ein Minutenwechsel. Der Ausgang
„outDCF_Fehler“ wird zurückgesetzt (gemäß dem Zustandsdiagramm, Bild 4.12b). Nun
werden alle kurzen und langen Impulse des Eingangs („inDCF_In“) ausgewertet. Die
Ausgänge „outDCF_Lo“ und „outDCF_Hi“ zeigen dies sehr schön an. Interessant wird
es bei Sekunde 70. Hier erfolgt der nächste Minutenwechsel. Da bei den vorhergehenden 60 Sekunden kein Fehler aufgetreten ist, muss nun die Uhrzeit an den
entsprechenden Ausgängen ausgegeben werden. Der Wert für Stunden-Zehner beträgt
„1“, für Stunden-Einer beträgt er „9“, für den Minuten-Zähler beträgt er „4“ und der
Minuten-Einer-Wert beträgt „7“. Es ergibt sich also eine Uhrzeit von 19:47 Uhr. Weiters
muss auch die Anzeige (Ausgang outANZEIGE_EN) aktiviert werden. Der
Statusausgang „outDCF_Sync“ geht ebenfalls von low auf high. Weiters erkennt man
sehr gut einen Sekundentakt und der Wert für die Sekunden-Einer-Stelle beginnt mit
jedem Sekundentakt hoch zu zählen.
Ist man an weiteren Details interessiert, so kann man natürlich auch Ausschnitte
genauer betrachten (Zoom-Funktion).
Die Funktionalität des hier gewählten Designs wird hier also prinzipiell erfüllt. Natürlich
kann man noch weitere, größere Zeitfenster (z. B. 2 Minuten) simulieren.
Seite 52
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
7.
Programmieren
Nach erfolgreicher Simulation kann nun das Design in das CPLD geladen werden.
Diesen Vorgang bezeichnet man auch als Programmieren.
Zum Programmieren ist neben der Hardware (also der bestückten Platine, gemäß
Abschnitt 8) auch noch ein so genanntes Download-Kabel notwendig. Ich verwende hier
den so genannten „Byte-Blaster“. Dieser wird von der Herstellerfirma des CPLDs (also
Altera) hergestellt. Natürlich kann auch ein Nachbau (z.B. aus dem Internet) verwendet
werden. Es muss nur sichergestellt sein, dass der Nachbau funktionell dem originalen
„Byte-Blaster“ entspricht. Das Download-Kabel verbindet also den PC (mittels paralleler
Schnittstelle) mit der Zielhardware (siehe auch Abschnitt 3).
Es ist zu beachten, dass das Download-Kabel richtig an die Zielhardware (hier die DCFUhr) angeschlossen wird. Dazu ist Pin 1 der Programmier-Schnittstelle (JTAG-Schnittstelle) extra gekennzeichnet.
Die Programmieroberfläche wird mit dem Symbol „Programmer“ gestartet (Bild 7.1.)
Bild 7.1.: Programmieren
Darauf hin öffnet sich die Programmierumgebung gemäß Bild 7.2.
3
1
2
Bild 7.2.: Programmieren
Folgende Einstellungen sollten dabei überprüft werden:
• ByteBlasterMV (LPT1)
• Mode: JTAG
• File: dcf.pof
• Device: EPM7128SL84
Seite 53
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
•
•
•
Program/Configure: Häkchen
Verify: Häckchen
Blank Check: Häkchen
Sind alle diese Einstellungen korrekt, so kann die Programmierung mit der Taste „Start“
begonnen werden. Wichtig: Beim Programmieren muss die DCF-Uhr eingeschaltet sein.
Ansonst treten die beiden Fehlermeldungen
“Error: JTAG ID code specified in JEDEC STAPL Format File does not match any
valid JTAG ID codes for device”
und
“Error: Operation failed”
auf.
Seite 54
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
8.
Nachbauanleitung
Dieser Abschnitt beschreibt den Nachbau der DCF-Uhr. Das Herstellen der Platine wird
hier nicht beschrieben, da hier jeder seine eigene Methode besitzt, außerdem werden
industriell gefertigte Platinen (auch in der Einzelfertigung und auch für eine
Privatperson) immer günstiger, so dass die Eigenfertigung immer mehr abnimmt.
Schritt 1: Platinen herstellen
Zu diesem Zweck sind im Anhang A die Layouts zu diesem Projekt abgedruckt, welche
üblicherweise seitenverkehrt sind.
Selbstverständlich können eigene Platinen entworfen werden, die den eigenen
Anforderungen entsprechen.
Achtung: Wird eine eigene Platine entworfen, so sollte folgendes beachtet werden: Es
hat sich gezeigt, dass die Kupferfläche unter der Antenne (des DCF-Empfängers)
entfernt werden muss. Mit der Kupferfläche war kein DCF-Empfang möglich, bzw. die
Antenne konnte nicht direkt auf der Platine montiert werden. Im Bild 8.1 ist zu erkennen,
dass ein erheblicher Teil auf beiden Seiten freigeätzt wurde.
Schritt 2: Platinen bestücken
Die Elektronik dieses Projektes wurde auf zwei Platinen aufgeteilt. Das Bestücken einer
Platine ist erst dann sinnvoll, wenn alle für diese Platine benötigten Bauteile vorhanden
sind. Es sollten generell nur erstklassige und neuwertige Bauteile verwendet werden.
Auf Bauteile aus ausgeschlachteten Geräten sollte grundsätzlich verzichtet werden, da
ihre Funktionalität nicht gewährleistet ist, und eine unnötige Fehlersuche dadurch
vermieden werden kann.
Weiters sollte ausreichend Platz und vor allem ausreichend Zeit für die Bestückung der
Platinen vorhanden sein.
Steuerplatine:
Die Bauelemente entsprechend Bild 8.2. (Bestückungsplan), der folgenden
Reihenfolge, der Stückliste (Anhang B) und dem Schaltplan (Abschnitt 3) bestücken.
Die nach dem anlöten überstehenden Anschlüsse mit einem kleinen Seitenschneider
entfernen.
Achtung: Bauteile, die an einem Ende mit Masse verbunden sind, sollten sofern dies
Möglich ist sowohl an der Lötseite als auch an der Bauteilseite angelötet werden (z.B.
bei den Keramikkondensatoren). Der Grund dafür ist, dass sonst die Massefläche
unterbrochen wird.
Reihenfolge zur Bestückung der Steuerplatine:
• Durchkontaktierungen (8 Stück) gemäß Bild 8.1. Tipp: Ich verwende für die
Durchkontaktierungen nur ein Stück Draht, welches ich an beiden Seiten der Platine
anlöte. Die überstehenden Reste entferne ich mit einem Seitenschneider.
Seite 55
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Durchkontaktierungen
Bild 8.1.: Durchkontaktierungen (Steuerplatine)
•
•
•
•
•
•
•
•
•
•
•
•
•
Quarz X1 (32,768 kHz)
Widerstände R1, R56, R58 (je 10k), R2 (10M), R3 (100k), R4, R19, R20, R35-R55
(je 1k), R5-R18, R21-R34 (je 220 Ohm) und R57 (470 Ohm): Tipp: Vor dem Einlöten
des Widerstandes diesen überprüfen, auch wenn die Bauteile in einem Regal
sortiert sind. (z.B. mit einem Multimeter). Die Praxis hat gezeigt, dass sich hin und
wieder doch falsche Bauteilwerte in das Regal eingeschlichen haben. Dies gilt nicht
nur für Widerstände, sondern auch für Dioden, Kondensatoren, Transistoren usw.
Einen 0-Ohm-Widerstand oder eine Drahtbrücke (siehe Bild 8.2.)
Diode D10 (1N4001): Achtung: Polarität beachten!
IC-Fassungen für IC2 (14polig), IC3-IC8 (je 16polig) und IC9 (20polig): Tipp 1:
Obwohl es bei den Fassungen elektrisch gesehen egal ist wie die Fassungen
eingelötet sind, sollte man doch die Fassung so einlöten, dass die Kerbe in die
richtige Richtung zeigt. Dies erleichtert das spätere Einsetzten der ICs bzw.
erleichtert die Arbeit bei einem IC-Tausch. Tipp 2: Beim Einlöten der Fassungen
sollte man wie folgt vorgehen: Fassung an der einzusetzenden Stelle lagerichtig
einsetzen und zunächst nur einen beliebigen Eckpin anlöten. Fassung kontrollieren
und eventuell Nachlöten. Sitzt die Fassung ordentlich, den gegenüberliegenden Pin
anlöten. Fassung wieder kontrollieren und eventuell nachlöten. Erst wenn Sie mit
der Lage der Fassung zufrieden sind, die restlichen Pins anlöten.
Tantal C7 (1µF/35V): Achtung: Polarität beachten! (der längere Anschluss ist der
Pluspol)
Keramikkondensator C3 (39pF)
Keramikkondensator C8 (10nF)
Keramikkondensatoren C5, C6, C12, C16 (je 100nF) und C9, C10, C11, C13, C14
(je 220nF)
Keramikkondensator C2 (10pF)
Transistor T1 (BC547B): Achtung: Polarität beachten!
Buchse für Netzteil
PLCC-Fassung für IC1 (84polig): Tipp 1: Obwohl es bei den Fassungen elektrisch
gesehen egal ist wie die Fassungen eingelötet sind, sollte man doch die Fassung so
einlöten, dass die abgeschrägte Ecke in die richtige Richtung zeigt. Dies erleichtert
das spätere Einsetzten der ICs bzw. erleichtert die Arbeit bei einem IC-Tausch. Tipp
2: Beim Einlöten der Fassungen sollte man wie folgt vorgehen: Fassung an der
einzusetzenden Stelle lagerichtig einsetzen und zunächst nur einen beliebigen
Eckpin anlöten. Fassung kontrollieren und eventuell Nachlöten. Sitzt die Fassung
Seite 56
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
•
•
•
•
•
ordentlich, den gegenüberliegenden Pin anlöten. Fassung wieder kontrollieren und
eventuell nachlöten. Erst wenn Sie mit der Lage der Fassung zufrieden sind, die
restlichen Pins anlöten.
Leuchtdioden D3, D4, D5, D6, D12 (je 3mm, gelb), D7, D9 (je 3mm, rot) und D8,
D11(je 3mm, grün): Achtung: Polarität beachten! Der längere Anschluss ist die
Anode (plus), der kürzere demnach die Kathode (minus).
Mini-Elkos C1, C4 (je 10µF/35V) und C15 (22µF/35V): Achtung: Polarität beachten
Stiftleiste für die Jumper und die JTAG-Schnittstelle
Spannungsregler IC10 (7805): Achtung: Polarität beachten!
Hebelschalter S1
Bild 8.2.: Bestückungsplan (Steuerplatine)
Anzeigeplatine:
Die Bauelemente entsprechend Bild 8.3. (Bestückungsplan), der folgenden
Reihenfolge, der Stückliste (Anhang B) und dem Schaltplan (Abschnitt 3) bestücken.
Die nach dem anlöten überstehenden Anschlüsse mit einem kleinen Seitenschneider
entfernen.
Reihenfolge zur Bestückung der Anzeigeplatine:
• Buchsenleiste für LD1 bis LD4 (je 2x5polig) und LD5 (2x9polig): Tipp: Bei
mehrpoligen Buchsenleisten zuerst den ersten Pin anlöten, Buchsenleiste
anschließend ausrichten, eventuell nachlöten, dann den letzten Pin anlöten,
Buchsenleiste eventuell ausrichten und/oder nachlöten. Erst danach die restlichen,
dazwischen liegenden Pins anlöten.
• Leuchtdioden D1 und D2 (je 5mm, rot): Achtung: Polarität beachten! Der längere
Anschluss ist die Anode (plus), der kürzere demnach die Kathode (minus).
Seite 57
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Bild 8.3.: Bestückungsplan (Anzeigeplatine)
Schritt 3: Test der Steuerplatine
•
•
•
•
•
•
ICs noch nicht in die Fassungen einsetzen, das DCF-Modul noch nicht montieren,
und auch die Betriebsspannung noch nicht anschließen.
Zuerst mit einem Multimeter prüfen, ob zwischen Betriebsspannung (+5V) und
Masse kein Kurzschluss herrscht. (Multimeter im Mode „Durchgangstester“ z.B. am
IC-Sockel für IC2 an den Pins 7 (GND) und 14 (+5V) messen. Diese Messung kann
auch am IC-Sockel für IC3 bis IC8 an den Pins 8 (GND) und 16 (+5V) oder an IC9
an den Pins 10 (GND) und 20 (+5V) durchgeführt werden. Multimeter nach wie vor
im Mode „Durchgangstester“. Eventuell festgestellte Kurzschlüsse müssen natürlich
aufgespürt und entfernt werden!
Alle Jumper stecken
Eine Spannungsquelle oder das Steckernetzteil mit einer Spannung von etwa 7,5V
anschließen und die DCF-Uhr mit dem Hebelschalter (S1) einschalten. Nun sollte
die grüne Leuchtdiode D11 leuchten. Leuchtet diese Leuchtdiode nicht, sofort
prüfen, ob der Spannungsregler heiß wird. Wird dieser heiß, so liegt ein Kurzschluss
vor, welcher natürlich aufgespürt und entfernt werden muss!
Leuchtet die grüne Leuchtdiode (D11), überprüfen, ob auch an den ICs die
Spannung an den entsprechenden Pins anliegt. Wird keine oder eine grob
abweichende Spannung als 5 Volt gemessen, so liegt ein Bestückungsfehler vor,
welcher unbedingt aufgespürt und beseitigt werden muss.
Ist die Spannung okay, entweder die Stromversorgung abschalten, oder die Platine
von der Stromversorgung trennen.
Schritt 4: DCF-Modul montieren und erste
Funktionskontrolle
•
DCF-Modul gemäß Bild 8.4. im ausgeschalteten Zustand montieren
Seite 58
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Zylinderkopfschraube M2,5x10 +
Kunststoff-Distanz 5mm + Mutter
M2,5
Kabelbinder
zur Fixierung
der Antenne
3 Anschlussdrähte
Bild 8.4.: DCF-Modul (Montage)
•
•
•
•
•
IC1 (EPM7128), IC2 (74HCU04) IC3 bis IC8 (74LS47) und IC9 (74HCT563) im
ausgeschalteten Zustand einsetzen. Achtung: Auf die Polarität achten!
Spannung wieder anlegen bzw. einschalten
Das CPLD (IC1) mit einem entsprechenden Downloadkabel programmieren (siehe
auch Abschnitt 7)
Ist das Programmieren nicht möglich, alle Leiterbahnen zwischen JTAG-Schnittstelle
und CPLD (IC1) überprüfen.
War das Programmieren erfolgreich, so kann nun eine erste Funktionskontrolle
erfolgen:
• DCF-Uhr ausschalten und Downloadkabel entfernen
• DCF-Uhr an einem Ort aufstellen, wo ein guter DCF-Empfang möglich ist.
• Nach dem Einschalten müssen zumindest die Leuchtdioden D11
(Einschaltkontrolle) und D7 („Fehler“) leuchten.
• Nach einer Weile muss auch die Leuchtdiode D12 zu „blinken“ beginnen,
wobei die Leuchtdiode länger leuchtet, und nur sehr kurz erlischt. Gleichzeitig
zeigen die Leuchtdioden D3 bis D5 an, ob ein Low (LO), High (HI) oder ein
ungültiges (?) Bit empfangen wurde. Letzteres sollte aber bei einem guten
DCF-Empfang nicht auftreten!
• Ist dies soweit erfolgreich, DCF-Uhr wieder ausschalten
Schritt 5: Steuer- und Anzeigeplatinen miteinander
verbinden und zweite Funktionskontrolle
•
•
•
•
•
•
Steuer- und Anzeigeplatine mit kurzen (ca. 2,5cm) langen isolierten Drähten
verbinden. Dazu eigenen sich ganz besonders die Drähte eine Flachbandkabels.
Aufsteckkühlkörper auf den Spannungsregler (IC10) aufsetzen.
7-Segment-Anzeigen im ausgeschalteten Zustand einsetzen. Achtung: Auf die
Polarität achten!
Spannung wieder anlegen bzw. einschalten
Nun müssen wieder zumindest die Leuchtdioden D11 (Einschaltkontrolle) und D7
(„Fehler“) leuchten. Nach einer Weile muss auch die Leuchtdiode D12 zu „blinken“
beginnen (so wie schon bei Schritt 4)
Die Leuchtdioden D3 bis D5 zeigen auch hier wieder an, ob ein Low (D3 leuchtet)
oder ein High (D4 leuchtet) empfangen wurde, oder ob es sich bei dem
empfangenen Daten um kein gültiges Bit gehandelt hat (D5 leuchtet).
Seite 59
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
•
•
Bei einem Minutenwechsel erlischt die „Fehler“-Leuchtdiode (D7). Diese
Leuchtdiode wird erst wieder zum Leuchten gebracht, wenn auch die Leuchtdiode
D5 kurz aufleuchtet, also wenn kein gültiges Bit empfangen wurde.
Wurde ein komplettes DCF-Telegramm fehlerfrei empfangen, so leuchtet die grüne
„SYNC“-Leuchtdiode (D6) auf. Gleichzeitig zeigen auch die 7-Segment-Anzeigen die
aktuelle Uhrzeit an, und die Leuchtdioden D1 und D2 blinken im Sekunden-Takt.
Schritt 6: „Befestigungswinkel“ und AcrylglasScheibe vorbereiten
•
2 Befestigungsstücke (z.B. aus Aluminium) gemäß Bild 8.5 vorbereiten
Bild 8.5.: Befestigungsstück
•
Frontplatte aus der roten Acrylglas-Scheibe (siehe Stückliste, Anhang B) gemäß Bild
8.6 vorbereiten. Zusätzlich die Bohrungen auf einer Seite Senken, so dass
Senkkopfschrauben eben abschließen.
Bild 8.6.: Frontplatte
Seite 60
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Schritt 7: Endmontage
•
Bild 8.7. zeigt wie Platinen und die Frotplatte zu montieren sind
Senkkopfschraube M3x10 –
Frontplatte 2 x Distanz M3x10 –
Steuerplatine –
Mutter M3
Senkkopfschraube M3x10 –
Frontplatte 2 x Distanz M3x10 –
Steuerplatine –
Befestigungsstück
Mutter M3 –
Steuerplatine –
Distanz M3x10
Bild 8.7.: Endmontage
•
Geschafft! Bild 8.8. zeigt die fertige DCF-Uhr im Betrieb.
Bild 8.8.: DCF-Uhr (im Betrieb)
Seite 61
Befestigungsstück –
Steuerplatine –
Distanz M3x10
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Anhang A: Layouts
Steuerplatine – Lötseite:
Steuerplatine – Bauteilseite:
Seite 62
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Anzeigeplatine
Seite 63
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Anhang B: Stückliste
Nr.
EPreis
0,11
1,50
100-Stück-Packung
Conrad 418218
Conrad 408166
0,14
1,50
100-Stück-Packung
3
1
1
Conrad 418374
Conrad 418498
Conrad 420450
0,14
0,14
0,14
Keramikkondensator
10pF
C3
Keramikkondensator
39pF
C8
Keramikkondensator
10nF
C5,C6,C12,C16 Keramikkondensator
100nF
C9-C11,
Keramikkondensator
C13,C14
220nF
C7
Tantal 1µF/35V
C1,C4
Elko 10µF/35V
C15
Elko 22µF/35V
1
Conrad 457124
0,12
RM2,54
1
Conrad 457191
0,12
RM2,54
1
Conrad 453323
0,23
RM5,08
4
Conrad 453358
0,21
RM5,08
5
Conrad 453366
0,35
RM5,08
1
2
1
Conrad 481670
Conrad 460532
Conrad 460575
0,54
0,13
0,13
RM2,54
RM2 Ø5x7mm
RM2 Ø5x7mm
D10
D3,D4,D8,D9,
D12
D5,D7
Diode 1N4001
LED 3mm Gelb lowcurrent
LED 3mm Rot lowcurrent
LED 3mm Grün lowcurrent
LED 5mm Rot lowcurrent
LED-Display 25,4mm
(SA10-21EWA)
LED-Display 2stellig,
14,2mm (HDSP-521E)
1
5
Conrad 162213
Conrad 145980
0,08
0,21
Typ: L-934LYD
2
Conrad 145998
0,21
Typ: L-934LD
2
Conrad 145971
0,21
Typ: L-934LGD
2
Conrad 146005
0,21
Typ: L 53 LD
4
Farnell
622-357
2,40
1
Farnell
325-4677
1,60
T1
Transistor BC547B
1
Conrad 155012
0,15
IC1
EPM7128SLC84-15
1
Farnell
300-5963
16,70
IC2
IC3-IC8
IC9
IC10
74HCU04
74LS47
74HCT563
7805
1
6
1
1
Farnell
Conrad
Conrad
Conrad
786-135
169196
151300
179205
0,41
0,96
0,96
0,54
X1
Quarz 32,768 kHz
1
Farnell
221-533
0,55
DCF1
DCF-Empfangsmodul
1
Conrad 641138
9,58
PLCC-Fassung 84pol
Präz. IC-Sockel 14pol
Präz. IC-Sockel 16pol
Präz. IC-Sockel 20pol
1
1
6
1
Conrad
Conrad
Conrad
Conrad
1,17
0,42
0,48
0,54
R5-R18,R21R34
R57
R4,R19,R20,
R35-R55
R1,R56,R58
R3
R2
Bezeichnung
St.
Widerstand 0 Ohm
Widerstand 220 Ohm
1
28
Lieferant
Conrad
Conrad
Widerstand 470 Ohm
Widerstand 1k
1
24
Widerstand 10k
Widerstand 100k
Widerstand 10M
C2
D6,D11
D1,D2
LD1-LD4
LD5
Seite 64
Bestell.
Nr.
403709
408085
189758
189618
189626
189839
Bemerkungen
Programmiert mit
dcf.pof
für IC1
für IC2
für IC3-IC8
für IC9
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
S1
Stiftleiste, 2reihig
1
Conrad 742007
1,45
36polig
Aufsteckkühlkörper
1
Conrad 188573
1,15
Kühlkörper für IC10
Rth = 18 K/W
Ein-Aus-Schalter
(Hebelschalter)
1
Conrad 701505
2,15
Buchse für Netzteil
Steckernetzteil PA500
unstabilisiert
1
1
Conrad 518318
6,95
Epoxydplatine 160x100
beidseitig
Epoxydplatine 160x100
einseitig
1
Conrad 529176
3,57
für Steuerplatine
1
Conrad 529249
2,71
für Anzeigeplatine
Acrylglas-Scheibe Rot
1
Conrad 530824
2,70
100 x 200 mm
Befestigungsstücke
2
Zylinderkopfschraube
M2,5x10
Senkkopfschraube
M3x10
2
Mutter M2,5
Mutter M3
2
4
Distanz M3x10
Distanzrolle 5mm
12
2
Kabelbinder
2
Alu, 10x10x6 mm
4
Seite 65
Entwickeln mit CPLDs (am Beispiel einer DCF-Uhr)
Anhang C: Quellen
•
•
•
•
•
•
•
•
Homepage zum Zeitzeichensender DCF77 (www.dcf77.com)
Homepage des Herstellers des hier verwendeten CPLDs (www.altera.com)
Datenblatt zum EPM7128 (www.altera.com)
Elektor, Ausgabe Mai/2004, Seite 12ff
Elektor, Ausgabe Juni/2004, Seite 58ff
Buch „Programmierbare Logik mit GAL und CPLD“ (ISBN: 3-486-24610-0, Autor:
Christian Ellwein)
Buch „Das FPGA-Kochbuch“ (ISBN: 3-8266-2712-1, Autor: Markus
Wannemacher)
Buch „306 Schaltungen“ (ISBN: 3-89576-022-6), Seite 399f
Seite 66