Designbeispiel "Hammond Orgel" Parallele Prozesse im FPGA sequenzialisieren

Logikressourcen für die Tonerzeugung

Eine erste Abschätzung der Logikressourcen für die Tonerzeugung zeigt allerdings, dass hierfür schon ein mittelgroßes FPGA benötigt würde. Alleine die Vorteiler und die Zähler für die Drehwinkel der 100 Zahnräder und die davon abgeleiteten Sinuswerte würden gut 10.000 Logikelemente und 100 Block-RAMs belegen. Der Mischer würde weitere ca. 10.000 Logikelemente benötigen, um die 100 Sinuswerte abhängig von den gedrückten Tasten und Zugriegelstellungen zu addieren. Natürlich gibt es ­FPGAs mit genügend Ressourcen, um diese Logik zu realisieren, aber effizient ist ein solches Vorgehen nicht. Das geht besser, und zwar durch Sequenzialisierung.

Um die Designaufgabe von der mechanischen Aufgabenstellung eines Manuals zu entkoppeln, wird hier davon ausgegangen, dass ein Orgelmanual mit MIDI-Ausgang zur Verfügung steht. Über die MIDI-Schnittstelle werden Informationen wie „Taste x gedrückt“ und „Taste x losgelassen“ seriell übertragen.

Das Blockschaltbild des elektrischen Systems (Bild 1) ist unabhängig von der parallelen oder seriellen Konzeption des FPGA-Designs. Ein- und Ausgänge sowie Schnittstellenbausteine bleiben gleich.

Für die Abschätzung, ob eine Sequenzialisierung möglich ist, muss zunächst ein Zeitfaktor bestimmt werden. Dieser Faktor ist das Verhältnis der Arbeitsfrequenzen von FPGA-Design und System. Für die Audiosignalerzeugung kann man als Arbeitsfrequenz des Systems z.B. 48 kHz, die übliche Abtastrate von Studiosystemen, annehmen. Die Arbeitsfrequenz des FPGA-Designs kann man ohne Kenntnis des Designs nur grob abschätzen, aber 50 MHz sind auch mit kostengünstigen Low-Power-FPGAs leicht zu machen, sofern keine komplexe kombinatorische Logik verwendet wird. Der Zeitfaktor ist daher in diesem Fall vermutlich mindestens 1000.

Basierend auf diesem Zeitfaktor kann man ermitteln, welche Arbeitsschritte sequenzialisiert werden können. Eine Orgel mit einem Tonbereich von sechs Oktaven hat 73 Tasten, und wenn pro Taste, wie bei der Hammond-Orgel üblich, neun Tonfrequenzen gemischt werden sollen, dann benötigt man bei einer vollständig sequenziellen Addition etwa 660 Taktzyklen. Ok, das könnte funktionieren.

Das heißt im Klartext, dass im FPGA die aktuellen Werte der Wechselspannungen nicht parallel in Registern vorliegen müssen, aus denen sich der Mischer die Werte abholen kann. Es reicht aus, wenn die Werte in einem Block-RAM vorliegen, aus dem der Mischer dann jeweils einen Wert pro Takt ausliest und zu dem bereits akkumulierten Wert dazuzählt. Damit ist schon sehr viel gewonnen. Ein Block-RAM ersetzt ca. 1500 LUTs und die Addierstufe addiert nur zwei Werte und nicht 100.

Gleiches gilt für die Werte der Zugriegel. Auch diese müssen nicht ständig im Design zur Verfügung stehen. Da die aktuellen Abtastwerte aller Teiltöne nacheinander zusammengezählt werden, muss in jedem Takt auch nur ein Zugriegelwert vorliegen. Also kommen auch die Zugriegelwerte in ein RAM, was viele Ressourcen spart.

So weit, so gut. Aber wie kommen die 100 Abtastwerte der Wechselspannungen in das Block-RAM hinein bzw. wie lange dauert das? In Analogie zu den 100 unterschiedlich schnell an den Spulen vorbeilaufenden Zahnrädern braucht man ebenso viele unterschiedlich schnell laufende fraktionale Zähler plus nachgeschaltete Sinustabellen.

Unter der Annahme, dass in einem Block-RAM der Tiefe 1024 die Sinuswerte von 0 bis knapp unter 2∙π abgelegt sind, bräuchte man einen 10 bit breiten Binärzähler, der pro Sekunde diese Tabelle so oft durchläuft, wie es der zu erzeugenden Wechselspannung in Hertz entspricht. Im Falle des Kammertons a‘ (440 Hz) muss der Zähler also 440 ∙ 1024 = 450.560 Zählschritte pro Sekunde durchführen. Wieder angenommen, die Arbeitsfrequenz des FPGA läge bei 80 MHz, ergäbe das einen Teiler von etwa 178 vor dem eigentlichen binären 10-bit-Zähler. Da es aber so etwas wie „etwa 178“ in der binären Welt nicht gibt, würde der Teiler genau 178 sein und die resultierende Frequenz geringfügig von 440 Hertz abweichen.

Mittels fraktionaler Zähler kann man die Zielfrequenzen allerdings viel genauer erreichen. Zwar muss auch ein fraktionaler Zähler diese 440 ∙ 1024 Schritte pro Sekunde durchlaufen, aber dies wird durch eine sinnvolle Wahl von Nachkommastellen und Inkrementalwert erreicht.
Doch zurück zum Block-RAM, aus denen der Mischer die Abtastwerte der einzelnen Töne liest, denn vor dem Lesen müssen die 100 Abtastwerte ermittelt und in das RAM geschrieben werden. Dazu müssen viele Zähler viele Sinustabellen adressieren oder, durch einen Multiplexer zusammengefasst, nacheinander auf eine gemeinsame Sinustabelle zugreifen. Dafür wären ca. 100 Taktzyklen nötig, aber so viel Zeit ist auch noch zur Verfügung. Also sind keine 100 Block-RAMs nötig, sondern nur eines.

Durch die Sequenzialisierung reduziert sich der Ressourcenverbrauch von ca. 20.000 LUTs und über 100 Block-RAMs auf ca. 2500 LUTs und vier Block-RAMs. Und auch wenn die Arbeitsschritte sequenziell durchgeführt werden, so ist auch diese Orgel grenzenlos polyphon. Die Logik der gesamten Orgel inklusive MIDI-Schnittstelle und Ansteuerlogik für externe Digital/Analog-Wandler passt damit in ein kleines FPGA wie das MachXO2-4000 von Lattice. Ein solches FPGA befindet sich auf dem Evaluation-Board LXO2000 der Firma Trenz Electronics. Ein paar weitere Komponenten wie Stecker und D/A-Wandler müssen noch hinzugefügt werden, am besten mittels einer Aufsteckplatine. Dann braucht man noch ein Keyboard mit MIDI-Ausgang und einen Verstärker mit Lautsprecher, der das Audiosignal in hörbaren Schall wandelt. Nun steht dem Orgelspiel nichts mehr im Weg.