Hallo zusammen,
als Teil meiner Masterarbeit möchte ich einen diskreten Zustandsregler
für ein inverses Pendel implementieren. Das Ganze soll jedoch nicht auf
einem µController erfolgen, sondern auf einer FPGA-Platform auf der ich
einen Microblaze IPCore aufsetze.
Wie aus dem Titel ersichtlich handelt es sich um ein Nexys3 Board der
Firma Digilent, auf welchem ein Xilinx Spartan6 FPGA verbaut ist.
Ich arbeite somit mit der ISE Design Suite 14.7 mit Webpack Lizenz.
Bisher habe ich schon mehrfach erfolgreich das Microblaze MCS mit Hilfe
des IPCoreGenerators eingebuden und auch einfache Testprogramme
("HelloWorld" per UART) mit dem SDK erzeugt.
Leider findet man über die Programmierung des Microblaze nur sehr wenige
Informationen. Bisher waren meine beste Informationsquelle diverse
Problem-Threads aus dem Xilinx-Forum. Natürlich habe ich auch schon
etliche PDFs an Dokumentation über Microblaze durchsucht, leider ohne
großen Erfolg.
Ich habe das "HelloWorld"-Programm so modifiziert, dass immer bei einem
Tastendruck eine UART-Ausgabe erhalte. Dies läuft im Moment jedoch nur
über Polling. Als nächsten Schritt wollte ich mich mit Interrupts des
Microblaze beschäftigen, jedoch komme ich hierbei kein Stück weiter.
Zwar habe ich schon verschiedene Tutorials zum Microblaze gefunden,
allerdings wird hierbei in der Regel das EDK mit Xilinx Platform Studio
benutzt, wofür meine Webpack-Lizenz nicht auszureichen scheint, und
hören die Tutorials meistens nach dem Laden des "HelloWorld"-Programms
auf.
Ich bin für jeden Tipp dankbar!
Gruß,
Matthias
Matthias W. schrieb:> Das Ganze soll jedoch nicht auf einem µController erfolgen, sondern auf> einer FPGA-Platform auf der ich einen Microblaze IPCore aufsetze.
Und was (ausser dem signifikant höheren Preis) genau ist nun der
relevante Unterschied zwischen einem fertigen Softcore-uC im FPGA und
einem fertigen uC z.B. mit ARM Core? Richtig: eigentlich keiner.
Wenn du den Start und die Regelung direkt in VHDL machen würdest, das
wäre was...
Lothar M. schrieb:> Matthias W. schrieb:>> Das Ganze soll jedoch nicht auf einem µController erfolgen, sondern auf>> einer FPGA-Platform auf der ich einen Microblaze IPCore aufsetze.> Und was (ausser dem signifikant höheren Preis) genau ist nun der> relevante Unterschied zwischen einem fertigen Softcore-uC im FPGA und> einem fertigen uC z.B. mit ARM Core? Richtig: eigentlich keiner.>> Wenn du den Start und die Regelung direkt in VHDL machen würdest, das> wäre was...
Na ja, ausgesucht habe ich mir das nur bedingt... ;-)
Es geht vorallem darum, sich in den Microblaze einzuarbeiten und die
Information für zukünftige Projekte verfügbar zu machen. Als SoC könnte
man das Ganze ja noch um weitere Komponenten wie z.B. eine
Kommutierungslogik für BLDC Motoren erweiteren, die dann auch
tatsächlich von dem Geschwindigkeitsplus des FPGA profitieren.
Im Moment wäre es mir auch lieber, die Regelung auf einem Cortex-M4
umzusetzen. Hierfür finde ich wesentlich mehr Informationen.
Die Zustandsregelung in VHDL umzusetzen wäre tatsächlich mal eine
Aufgabe, jedoch bezweifel ich mit meinen beschränkten Kenntnissen, dass
das so ohne weiteres machbar ist. Ich lasse mich jedoch gerne eines
besseren belehren :-)
Matthias W. schrieb:> Es geht vorallem darum, sich in den Microblaze einzuarbeiten und die> Information für zukünftige Projekte verfügbar zu machen.
Der scheint zwischenzeitlich tatsächlich frei verfügbar zu sein. Ob es
allerdings ohne EDK "Spass" macht, damit zu arbeiten, sei dahingestellt.
Lothar M. schrieb:> Matthias W. schrieb:>> Es geht vorallem darum, sich in den Microblaze einzuarbeiten und die>> Information für zukünftige Projekte verfügbar zu machen.> Der scheint zwischenzeitlich tatsächlich frei verfügbar zu sein. Ob es> allerdings ohne EDK "Spass" macht, damit zu arbeiten, sei dahingestellt.
Also bisher kann ich sagen, dass sich der Spaß definitiv in Grenzen
hält.
Würde ich wenigstens einfache Beispiel-Projekte finden können, in denen
mal ein externes Interrupt oder ein Timer verwendet wird, wäre mir ja
schon ein ganzes Stück geholfen. Leider wirkt es so, als wäre ich der
erste, der diesen umständlichen Weg beschreitet. :-D
Mittlerweile habe ich ein Beispiel gefunden, bei dem ein Timer-Interrupt
verwendet wird. Ich habe also ein neues Projekt angelegt und den Code
übernommen, um die Initialisierung nachvollziehen zu können. Leider
bekomme ich jetzt beim Kompilieren des SDK-Projektes eine Fehlermeldung,
dass ich die Größe meines BlockRAMs um knapp 3kB überschritten hätte.
Ich kann mir das eigentlich kaum vorstellen, da ich den Microblaze mit
64kB Programmspeicher erstellt habe und das Programm wirklich kurz ist.
Es handelt sich eigentlich um ein "HelloWorld" mit einem
Timer-Interrupt.
Hier meine Quelle:
http://www.ibelimb.com/2014/03/30/generating-a-microblaze-soft-processor-with-ise-webpack-14-dot-7/
Matthias W. schrieb:> Leider> bekomme ich jetzt beim Kompilieren des SDK-Projektes eine Fehlermeldung,> dass ich die Größe meines BlockRAMs um knapp 3kB überschritten hätte.> Ich kann mir das eigentlich kaum vorstellen, da ich den Microblaze mit> 64kB Programmspeicher erstellt habe und das Programm wirklich kurz ist.
Die BRAMs werden in kiloBIT angegeben. Nicht kiloBYTE.
FPGAs haben zwar rattenschnellen Speicher, aber i.d.R. recht wenig.
Edit:
Evtl. hab ichs auch falsch gelesen - hast Du das schon erfolgreich mit
64KByte synthetisiert?
Mac G. schrieb:> Die BRAMs werden in kiloBIT angegeben. Nicht kiloBYTE.> FPGAs haben zwar rattenschnellen Speicher, aber i.d.R. recht wenig.>> Edit:> Evtl. hab ichs auch falsch gelesen - hast Du das schon erfolgreich mit> 64KByte synthetisiert?
Also die Synthese funktionierte bisher einwandfrei.
Ich habe mich zunächst gewundert, dass ich mittlerweile die kostenlose
Microblaze-Variante mit 64kB erstellen kann. Bis vor kurzem war hier
eine Grenze bei 16kB. Nach einem Update des IPCores wurde die Grenze
aber offenbar nach oben verschoben.
Da läuft irgendwas beim Linken oder mit den Bibliotheken schief.
Ein UART + Hello World sollte in unter 1 kByte passen.
Du kannst ja mal mit nm nachschauen, wo die Bytes verballert werden:
Duke Scarring schrieb:> Da läuft irgendwas beim Linken oder mit den Bibliotheken schief.> Ein UART + Hello World sollte in unter 1 kByte passen.>> Du kannst ja mal mit nm nachschauen, wo die Bytes verballert werden:>
1
> $ zpu-elf-nm --print-size --size-sort main.elf
2
> 00003f37 00000001 T __malloc_lock
3
> 00003f38 00000001 T __malloc_unlock
4
> 00005bfc 00000001 D char_count
5
> 000074b0 00000001 B command_number
6
> ...
7
>
>> Duke
Ok, ich glaube an dieser Stelle werden meine Kompetenzen
überschritten... :-D
Soll heißen, ich habe keine Ahnung wie ich das bewerkstellige.
Hm, auf Grund deines Hinweises bezüglich des Linkers, habe ich mir
gerade mal genauer das Linker Script angeschaut. Irgendwie sieht das
alles recht komisch aus. (Available Memory Regions:
ilmb_cntlr_dlmb_cntlr Base Adress: 0x00000050 Size: 0x00001FB0)
Wenn ich mir mit Hilfe des Xilinx Tools "Generate a linker script" ein
neues erzeugen möchte, ist beim Hardware Memory Map auch nur die Rede
von 8 kB Speicher?!
Wie es aussieht, habe ich beim Erstellen des Hardware Projects im SDK
das falsche BMM-File ausgewählt.
Ich kann mittlerweile die besagten Code kompilieren und ausführen. Auch
externe Interrupts habe ich mit Hilfe eines Buttons triggern können.
Jetzt versuche ich derzeit zwei externe Interrupts über zwei
verschiedene Buttons zu triggern.
Leider scheitere ich hierbei.
Ich initialisiere beide Buttons über XIOModule, da ich dies in der
xiomodule.h gelesen habe.
Nach dem Aufruf von XIOModule_Intialize, _Start, _Connect und _Enable
für beide XIOModule funktioniert jedoch immer nur eins.
Offenbar überschreibe ich den anderen immer wieder.
Offenbar funktioniert es so nicht. Vermutlich verstehe ich die Funktion
des XIOModules nicht. In der xiomodule.h habe ich gelesen, dass ich für
jedes IO-Device eine XIOModule-Variable anlegen muss. Leider scheine ich
die Initialisierung meines ersten Interrupts durch das zweite zu
überschreiben.
Leider ist mir nicht ganz klar wieso...
Hier mein Code: