Fre­quenz­zäh­ler, Teil 1

Hier kommt nun der erste Teil der Beschrei­bung des Fre­quenz­zäh­lers. Hier soll die Hard­ware bespro­chen wer­den, inklu­si­ve der Logik im ver­wen­de­ten CPLD und der Soft­ware des Controllers.

Eine kur­ze Erwäh­nung fand der Zäh­ler schon vor ein paar Wochen in der Über­sicht der aktu­el­len Pro­jek­te. Dort fin­det sich auch der Schalt­plan und die 3D-Ansicht, bei­des hier noch­mal zum direk­ten Zugriff:

Die Hard­ware

Der Fre­quenz­zäh­ler basiert wie­der auf dem ATME­GA644-CPU-Board mit RS485-Schnitt­stel­le, das sich inzwi­schen in unter­schied­li­chen Pro­jek­ten bewährt hat. Die­ses CPU-Board kom­mu­ni­ziert über eine syn­chro­ne seri­el­le Schnitt­stel­le mit dem in einem EPM240T100 imple­men­tier­ten Fre­quenz­zäh­ler. Die benö­tig­te Geschwin­dig­keit ist unkri­tisch und daher wird die­se Kom­mu­ni­ka­ti­on auf dem CPU-Board über I/O‑Pins imple­men­tiert („bit-ban­ging“). Da der EPM240 mit 3,3 V betrie­ben wer­den muß und kei­ne 5‑V-tole­ran­ten I/O‑Pins hat, wird auch das CPU-Board mit 3,3 V betrie­ben. Das schränkt die Betriebs­fre­quenz auf maxi­mal 10 MHz ein. Wegen der gerin­gen Anfor­de­run­gen an die Geschwin­dig­keit, wur­de ein 8 MHz Quarz eingebaut.

Der Schalt­plan zeigt unten die Span­nungs­ver­sor­gung und die Kon­troll-LEDs, dar­über zwei gleich­ar­ti­ge Breit­band-Ver­stär­ker in klas­si­scher Emit­ter-Schal­tung für den Ein­gangs­takt. Sie sind ein­gangs­sei­tig mit 50 Ω abge­schlos­sen und heben den Pegel von etwa 6 dBm (8 mA Trei­ber­stär­ke) auf den für die CPLD-Takt­ein­gän­ge benö­tig­ten Hub von 3.3 V an. Wegen der Schmitt-Trig­ger-Ein­gän­ge darf es auch etwas weni­ger sein. Acht LEDs und vier DIP-Schal­ter kön­nen optio­nal zur Sta­tus­an­zei­ge und zur Kon­fi­gu­ra­ti­on ver­wen­det wer­den. Außer­dem ist ein 100 MHz Quarz­os­zil­la­tor ein­ge­baut sowie jeweils eine JTAG-Pro­gram­mier­schnitt­stel­le für das CPU-Board und das CPLD.

Funk­ti­ons­wei­se

Zur digi­ta­len Bestim­mung einer Fre­quenz gibt es prin­zi­pi­ell zwei Metho­den: man zählt die Anzahl der Tak­te wäh­rend eines mög­lichst genau bekann­ten Inter­valls oder man misst die Zeit­dau­er zwi­schen zwei oder meh­re­ren Tak­ten. Die erste Metho­de wird nach­fol­gend als Nor­mal­be­trieb bezeich­net, die zwei­te Metho­de als Revers­be­trieb. Bei­de Ver­fah­ren benö­ti­gen eine mög­lichst prä­zi­se Referenzfrequenz.

Prin­zi­pi­ell sind bei­de Betriebs­ar­ten gleich­wer­tig, sie unter­schei­den sich aber in der Dau­er der Mes­sung. Die Auf­lö­sung im Nor­mal­be­trieb ist umge­kehrt pro­por­tio­nal zum Mess­in­ter­vall. Um eine Auf­lö­sung von 1 Hz zu errei­chen, muß man eine Sekun­de lang mes­sen, bei 0,1 Hz Auf­lö­sung schon zehn Sekun­den. Den 32 kHz Takt einer Uhr kann man auf die­se Wei­se in einer Sekun­de also nur auf etwa 30 ppm genau mes­sen (2-15).

Im Revers­be­trieb teilt man den Takt der Uhr bei­spiels­wei­se durch 215 und bekommt so auch ein Inter­vall von einer Sekun­de. Zählt man in der Zeit die Tak­te einer 100 MHz Refe­renz, dann erreicht man auf eine Auf­lö­sung von 10 ns, was 0,01 ppm = 10 ppb entspricht.

Kurz zusam­men­ge­fasst: damit das Mess­in­ter­vall kurz gehal­ten wer­den kann, wählt man den Nor­mal­be­trieb am besten bei hohen Fre­quen­zen im Ver­gleich zur Refe­renz­fre­quenz, den Revers­be­trieb bei nied­ri­gen Frequenzen.

Das CPLD

Ein CPLD ist für die­se Art von Auf­ga­ben prä­de­sti­niert. Es besteht aus einer Anzahl Logik-Ele­men­te, in die­sem Fall 240 Blöcke, die weit­ge­hend frei ver­schal­tet wer­den kön­nen und über schnel­le Ver­bin­dun­gen zu den Pins ver­fü­gen. Anders als die mei­sten FPGAs, haben CPLDs nicht­flüch­ti­ge Spei­cher und müs­sen daher nicht bei jeden System­start neu kon­fi­gu­riert wer­den. Man benö­tigt aller­dings ein preis­wer­tes Werk­zeug, in die­sem (Intel/Al­te­ra-) Fall den soge­nann­ten USB-Bla­ster, um das CPLD in der Schal­tung zu pro­gram­mie­ren. Das kann man auch mehr­fach machen, aber die Anzahl der Pro­gram­mier­zy­klen ist auf etwa 100 beschränkt, wäh­rend der Flash-Spei­cher einer CPU nor­ma­ler­wei­se auch 10.000 bis 100.000-mal pro­gram­miert wer­den kann.

Die Logik wird in einer Pro­gram­mier­spra­che ähn­lich einer Soft­ware-Pro­gram­mier­spra­che ein­ge­ge­ben. Zwei Spra­chen haben sich eta­bliert, VHDL und Ver­i­log. Ver­i­log hat Ele­men­te der Pro­gram­mier­spra­che „C“ und ist für jeman­den, der die­se Spra­che kennt, rela­tiv leicht zu erler­nen. Der Unter­schied ist frei­lich, daß Soft­ware im wesent­li­chen sequen­zi­ell abge­ar­bei­tet wird, wäh­rend in Hard­ware vie­les gleich­zei­tig pas­siert. Wie auch bei der Soft­ware­pro­gram­mie­rung benö­tigt man Werk­zeu­ge, die den erstell­ten Quell­code in ein Binär­for­mat umwan­deln, das man in das CPLD laden kann. Die­se Werk­zeu­ge stellt der Her­stel­ler der Logik­bau­stei­ne, gege­be­nen­falls in einer abge­speck­ten Ver­si­on, kosten­los zur Ver­fü­gung. Im Fal­le Intels ist das die „Quartus“-Entwicklungsumgebung, die sogar eine ange­pass­te Ver­si­on des Men­tor Model­Sim Simu­la­tors ent­hält, der in der Voll­ver­si­on auch in der pro­fes­sio­nel­len Chip-Ent­wick­lung ver­wen­det wird.

Block­dia­gramm des Frequenzzählers

Genau wie beim Ent­wurf einer dis­kret auf­ge­bau­ten Schal­tung, soll­te man sich auch bei einem CPLD (oder FPGA) ein Block­dia­gramm erstel­len, das die Funk­ti­ons­blöcke dar­stellt. Die kön­nen dann bei Bedarf hier­ar­chisch wei­ter ver­fei­nert wer­den, was aber bei dem rela­tiv ein­fa­chen Zäh­ler hier nicht not­wen­dig ist.

Blockdiagramm des Frequenzzählers
Block­dia­gramm des Frequenzzählers

Die­ses Dia­gramm zeigt nur die Logik des Zäh­lers, nicht das CPU-Inter­face. Zunächst gibt es die vier Takt­ein­gän­ge clk0 .. clk3, die über den Ein­gangs­mul­ti­ple­xer ver­teilt wer­den. clk1 und clk2 sind über die oben beschrie­be­nen Vor­ver­stär­ker mit den bei­den SMA-Buch­sen ver­bun­den und für den Refe­renz­takt und die zu mes­sen­de Fre­quenz vor­ge­se­hen. clk0 ist fest mit dem CPU-Takt ver­bun­den und clk3 wird von dem 100 MHz Quarz­os­zil­la­tor betrieben.

f_check ist die zu mes­sen­de Fre­quenz, die über einen optio­na­len Vor­tei­ler auf die Refe­renz­fre­quenz f_ref syn­chro­ni­siert wird. Daher muß die Refe­renz­fre­quenz min­de­stens dop­pelt so hoch sein, wie die ggf. her­un­ter­ge­teil­te zu mes­sen­de Fre­quenz. Der Ein­gangs­mul­ti­ple­xer bestimmt, wel­cher der vier Takt­ein­gän­ge auf f_check und f_ref geschal­tet wird. Es gibt hier kei­ne Ein­schrän­kun­gen, zu Test­zwecken kann auch der­sel­be Takt auf bei­de Signa­le geschal­tet werden.

Die Refe­renz­fre­quenz wird übli­cher­wei­se in der Grö­ßen­ord­nung von 50 bis 100 MHz lie­gen und wenn die zu mes­sen­de Fre­quenz mehr als halb so hoch ist, muß sie mit dem Pre­s­ca­ler her­un­ter­ge­teilt werden.

Der eigent­li­che Zäh­ler besteht aus einem 32-bit brei­ten Regi­ster, des­sen Inhalt von der CPU ein­ge­le­sen wer­den kann, sinn­vol­ler­wei­se nach­dem die Mes­sung been­det ist und der Wert sich nicht mehr ändert. Der eben­falls 32-bit brei­te pro­gram­mier­ba­re Tei­ler wird beim Start des Meß­zy­klus mit dem Wert des Timer-Rel­oad-Regi­sters gela­den und anschlie­ßend her­un­ter­ge­zählt. Er bestimmt damit die Tor­zeit, also wie lan­ge der Zäh­ler zäh­len soll. Der Meß­zy­klus wird been­det, sobald die­ser Timer null erreicht. Ein kom­plet­ter Meß­zy­klus besteht aus der Kon­fi­gu­ra­ti­on des Fre­quenz­zäh­lers (Wahl der Takt­ein­gän­ge, der Betriebs­art und Ein­stel­lung des Vor­tei­lers), Set­zen des Rel­oad-Regi­sters und Trig­gern der Mes­sung, womit gleich­zei­tig der Zäh­ler auf null gesetzt wird. Ein Sta­tus­flag zeigt an, wenn der Meß­zy­klus been­det ist und das Ergeb­nis aus­ge­le­sen wer­den kann.

Timer, Zäh­ler und Steu­er­lo­gik lie­gen in der Clock-Domä­ne des aus­ge­wähl­ten Refe­renz­si­gnals, wäh­rend die von der CPU geschrie­be­nen Kon­fi­gu­ra­ti­ons- und Sta­tus-Regi­ster in der Clock-Domä­ne des CPU-Boards lie­gen (clk0). Die Simu­la­ti­on ergibt eine maxi­ma­le Ein­gangs­fre­quenz von 120 MHz für die Takt­ein­gän­ge des Fre­quenz­zäh­lers und über 50 MHz für das CPU-Inter­face. Bei Betrieb mit 100 MHz ist man also auf der siche­ren Sei­te und die 32-bit Zäh­ler kön­nen dann über 80 Sekun­den zäh­len, ohne überzulaufen.

Im Nor­mal­be­trieb wird die Tor­zeit von der Refe­renz­fre­quenz bestimmt und die Anzahl der stei­gen­den Flan­ken von f_check wird in die­sem Inter­vall gezählt. Im Revers­be­trieb bestimmt f_check die Tor­zeit wäh­rend­des­sen die Anzahl von f_ref Flan­ken gezählt wird.

Ver­i­log Code

Hier ist nun der Ver­i­log-Code des Fre­quenz­zäh­lers und die not­wen­di­gen Pro­jekt­da­tei­en für die Quar­tus-Ent­wick­lungs­um­ge­bung. Gege­be­nen­falls müs­sen Datei­pfa­de ange­passt werden.

Das eigent­li­che Design steckt in der Datei Datei FreqCntr.v, die hin­rei­chend gut kom­men­tiert sein soll­te. Zu beach­ten ist, daß die ursprüng­lich geplan­te Para­me­tri­sie­rung über die Para­me­ter COUNTERW, TIMERW und IOREGW nicht kon­se­quent ver­folgt wur­de. Sie soll­ten auf ihren Default-Wer­ten bleiben.

FreqCntr_EPM240.v instan­zi­iert den Fre­quenz­zäh­ler für das EPM240 CPLD auf dem Fre­quenz­zäh­ler-Board. Die bei­den wei­te­ren Ver­i­log Datei­en FreqCntr_tb_Counter.v und FreqCntr_tb_Serial_IO.v ent­hal­ten die Model­Sim-Test­be­n­ches für den Zäh­ler und die seri­el­le CPU-Schnitt­stel­le. Die zuge­hö­ri­gen Skrip­te tb_Counter.do und tb_Serial_IO.do wer­den in Model­Sim aus­ge­führt und star­ten den jewei­li­gen Test.

Nach­trag: Quar­tus Prime V21.1

Nach­dem ich mir vor ein paar Wochen einen neu­en Note­book gelei­stet habe (der alte war tat­säch­lich mitt­ler­wei­le neun Jah­re alt), habe ich die jeweils neue­sten Ver­sio­nen der Ent­wick­lungs­um­ge­bun­gen instal­liert, für CPLDs und FPGAs von Intel (frü­her Alte­ra) also Quar­tus V21.1. Die­ses Paket beinhal­tet nicht mehr Model­sim, son­dern des­sen Nach­fol­ger Que­sta (bei­de von Men­tor). Die Bedie­ner­ober­flä­che ist prak­tisch gleich geblie­ben, aber es ist nun eine 64-bit Ver­si­on und die Simu­la­ti­ons­ge­schwin­dig­keit ist beein­druckend (was teil­wei­se auch am neu­en Note­book lie­gen könn­te). Lei­der benö­tigt die­se Ver­si­on eine zeit­lich auf ein Jahr befri­ste­te Lizenz, die aber kosten­los ist und danach auch ver­län­gert wer­den kann.

Fol­gen­des ist zu beach­ten: die alten mit Model­sim erstell­ten Pro­jek­te soll­ten durch neue mit Que­sta erstell­te Pro­jek­te ersetzt wer­den. Die alten Pro­jekt­da­tei­en ent­hal­ten Abhän­gig­kei­ten, die mit Que­sta nicht mehr funk­tio­nie­ren. Außer­dem muß das „vsim“-Kommando einen Para­me­ter für den Opti­mi­zer ent­hal­ten (voptargs=“+acc=prn“), damit die Namen der Ports (p), Regi­ster (r) und Net­ze (n) als Debug­in­for­ma­tio­nen erhal­ten blei­ben. Das voll­stän­di­ge vsim-Kom­man­do lau­tet also bei­spiels­wei­se folgendermaßen:

vsim <testbench> -voptargs="+acc=prn" -t 1ns

Das soll­te dann in den Test­be­n­ches tb_*.do ent­spre­chend geän­dert werden.

ATME­GA644-Code

Die Soft­ware, die auf dem ATMEGA644 aus­ge­führt wird, kann hier als Refe­renz her­un­ter­ge­la­den werden.

Ich ver­wen­de Atmel Stu­dio 7.0 als Ent­wick­lungs­um­ge­bung, habe aber kei­ne Pro­jekt­da­tei­en dazu­ge­fügt. Ver­mut­lich hat sowie­so jeder sei­ne eige­ne Phi­lo­so­phie bezüg­lich der Pfa­de. Das 7z-Archiv ent­hält auch eine PDF-Datei mit wei­te­ren Beschreibungen.

Im kom­men­den zwei­ten Teil soll die PC-Soft­ware zur Bedie­nung des Fre­quenz­zäh­lers beschrie­ben werden.