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