Forum: FPGA, VHDL & Co. parallele Prozesse konkurrieren um Peripherals


von Klaus S. (kschleisiek)


Lesenswert?

Ich hatte das Engineering-Model für eine Laserquelle mit genau 
definierter Frequenz, die ein methangefülltes Röhrchen als 
Absolutreferenz benutzt, mit microCore programmiert. Nur die I/O-Treiber 
und Busverwaltung waren VHDL, die Regelungsebene Forth. Das hat den 
Kunden glücklich gemacht.

Beim Flight-Model sollte aber auch die Regelungseben reines VHDL werden, 
um den Aufwand für die Prozessorverifikation zu sparen.

Und damit stellte sich die Frage nach der Resourcenverwaltung neu. Bei 
der Software ist es einfach: Es gibt einen Multitasker, der hat 
parallele Tasks (Prozesse), die die komplexe Regelung erledigen. Jede 
Peripherieeinheit hat ein "Busybit" und kann nur benutzt werden, wenn es 
nicht gesetzt ist, ansonsten aktiviert der Scheduler solange die nächste 
Task, bis das Busybit nicht mehr gesetzt ist. Das funktioniert nur 
deshalb, weil in der Software NIEMALS zwei Prozesse versuchen, 
gleichzeitig auf eine Resource zuzugreifen. Die Tasks sind nämlich gar 
keine parallelen Prozesse, sie sind nur pseudoparallel. In Wirklichkeit 
ist IMMER nur EIN Prozess aktiv.

Bei VHDL sieht es ganz anders aus: Jeder unabhängige Prozess ist 
prinzipiell vollparallel und läuft dauernd. Und deshalb kann es zu 
Konkurrenz zwischen mehreren Prozessen um eine Resource kommen. 
Klassischerweise löst man das mit einem priorisierten REQUEST/GRANT 
Handshake für jeden Prozess und seine benutzten Resourcen. Es ist also 
ein Kreuzprodukt von Prozesse*Resourcen und das auch noch *2 (REQUEST 
hin, GRANT her) und das auch manchmal quer durchs Chip.

Nun hatte ja die Softwarelösung bereits bewiesen, dass man aus 
Performancegründen keine volle Parallelität braucht, sondern die 
Regelungsaufgaben locker von einem Prozess sequentiell erledigt werden 
können.

Deshalb habe ich in VHDL den Multitasker modelliert: Es gibt insgesamt 
sechs (Regelungs)prozesse, die hintereinander aktiviert werden. Ist 
nichts mehr zu tun, wird die Kontrolle an den nächsten Prozess gegeben, 
und der letzte aktiviert wieder den ersten. Es wird sozusagen das 
Aktivierungstoken herumgereicht. Dadurch gibt es - wie bei der Software 
- jeweils nur einen Prozess, der auf eine Resource zugreifen möchte, und 
das Busybit, das von einer Resource an alle Prozesse verteilt wird, 
reicht für die Resourcenverwaltung völlig aus, ein Handshake ist gar 
nicht mehr erfoderlich.

Wir haben also den Aufwand von Prozesse*Resourcen*2 reduziert auf 
Resourcen.

Das hat natürlich Auswirkungen auf die Architektur. Sämtliches I/O wird 
über einen einzigen Bus angesteuert und der Bus wird über Multiplexer 
auf den gerade aktiven Prozess geschaltet. Zusätzlich hat jeder Prozess 
einen identischen Registerbereich, der auch gemultiplext wird. Sowohl 
Buszuteilung also auch Registerbereich lassen sich prima in einem Array 
verpacken, dessen Index der gerade laufenden Task entspricht.

Dann kann man sich einen Zoo von Procedures schreiben, die den Aktionen 
nachgebildet sind, die vorher in Software abgelaufen sind. Die 
Procedures sind sozusagen die Opcodes und jeder einzelne dieser Prozesse 
kann sich mit einem Zähler (aka Program Counter) durch ein großes 
CASE-Statement hangeln. Das hat den großen Vorteil, dass die Struktur 
der Software prinzipiell erhalten bleibt und man deshalb den ehemaligen 
Programmcode ohne viel Gehirnschmalz in entsprechendes VHDL umsetzen 
kann.

In VHDL kann man mehr machen, als mit einem beschränkten Opcode-Inventar 
und deshalb wird die VHDL-Lösung auf jeden Fall schneller sein und mit 
sehr viel weniger Jitter behaftet sein, als die Softwarelösung. Der 
Jitter der Softwarelösung lag bei 1 msec, bei VHDL wird das sicher auf 
wenige usec reduziert.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Klaus S. schrieb:
> Das funktioniert nur deshalb, weil in der Software NIEMALS zwei Prozesse
> versuchen, gleichzeitig auf eine Resource zuzugreifen

Welche Resourcen wären das denn ? I/O Pins kaum, sind ja angelötet, 
Timer und UART in VHDL ebenfalls nicht, es kann ja nur um volatile 
Variablen zur Steuerung gehen, da sehe ich bei uC auf der einen und VHDL 
Hardware auf der anderen kein Semaphorenproblem.

von weder Ochs noch Esel (Gast)


Lesenswert?

Klaus S. schrieb:
> Deshalb habe ich in VHDL den Multitasker modelliert: Es gibt insgesamt
> sechs (Regelungs)prozesse, die hintereinander aktiviert werden. Ist
> nichts mehr zu tun, wird die Kontrolle an den nächsten Prozess gegeben,
> und der letzte aktiviert wieder den ersten.

Das nennt der Hardware-experte Round-Robin-Arbiter. Den haste grade wie 
das sprichwörtliche Rad ein Zweites Mal erfunden.

https://fpgasite.wordpress.com/2016/04/15/vhdl-arbiter/

von Jonas B. (jibi)


Lesenswert?

Ich würde ja eher ein ProcessManager die Prozesse umschalten lassen, der 
auch ein Timeout für jeden Process kennt. Was passiert wenn das "Token" 
nicht weiter gegeben wird, weil auf ein nicht eintreffendes externes 
Ereignis gewartet wird etc...

von Christoph Z. (christophz)


Lesenswert?

1. Wo ist deine Frage?

2. Ich bin verwirrt. In 
Beitrag "Re: microCore, ein Echtzeitprozessor in VHDL für FPGAs" hast du 
geschrieben, dass microCore fliegt, also ging ich davon aus, dass er 
verifiziert ist. Aber jetzt schreibst du, dass sich euer Kunde die 
Verifikation "sparen" will von etwas das 20 Jahre erprobt ist?

Klaus S. schrieb:
> Ich hatte das Engineering-Model
[...]
> Beim Flight-Model sollte aber auch die Regelungseben reines VHDL werden,
> um den Aufwand für die Prozessorverifikation zu sparen.

Ich finde das gerade irgendwie unüblich, zwischen EM und FM noch so 
essentielle Dinge zu wechseln. Wo ist die Risikobewertung dazu?

Klaus S. schrieb:
> Der Jitter der Softwarelösung lag bei 1 msec, bei VHDL wird das sicher auf 
wenige usec reduziert.

Was sagen die Requirements? Reicht auch 1 s? Wird hier etwas vergoldet 
das schon gut genug ist?

Ein kleines unbekannteres RTOS (FemtoOS) hat einen pre-emptive Scheduler 
der es bei mir schafft auf einem 8 MHz AVR vier 7-Segment Anzeigen zu 
multiplexen ohne Jitter (bei 400 Hz, hab eine Oszilloskope Messung mit 
infinite persistance mal für ein paar Minuten laufen lassen). 
Multiplexing wird im  Task mit höchster Priorität gemacht und nutzt das 
Scheduler feature taskDelayFromWake (Delay the task a number of ticks, 
starting at the last wake time).

von Klaus S. (kschleisiek)


Lesenswert?

MaWin schrieb:
> Welche Resourcen wären das denn ?

10 12-bit DACs, 3 8-Kanal ADCs, 3 Laserswitches, 1 Wavemeter

Bei den ADCs (kompliziertester Fall) wird das busy-bit so gesteuert:

Es gibt ein internes ADC Register. Die Wandlung startet, wenn eine 
Kanalnummer in das Register geschrieben wird. Da gibt es zwei 
Möglichkeiten:
1) busy=0
Es wird busy gesetzt. Der ADC wird mit Wandlung beauftragt.
2) busy=1
Es wird der Folgeprozess aktiviert.

Das Ergebnis wird abgeholt, indem das Register gelesen wird. Wieder gibt 
es zwei Möglichkeiten:
1) busy=0
Der ADC ist fertig und wird ausgelesen. Busy wird rückgesetzt.
2) busy=1
Es wird der Folgeprozess aktiviert.

von Klaus S. (kschleisiek)


Lesenswert?

Jonas B. schrieb:
> Ich würde ja eher ein ProcessManager die Prozesse umschalten lassen, der
> auch ein Timeout für jeden Process kennt. Was passiert wenn das "Token"
> nicht weiter gegeben wird, weil auf ein nicht eintreffendes externes
> Ereignis gewartet wird etc...

Bei (noch) nicht eingetroffenem externen Ereignis, z.B. eine leere UART, 
wird sofort zum nächsten Prozess gesprungen. Und "verloren gehen" kann 
das Token auch nicht, weil die Aktivierung des nächsten Prozesses nichts 
anderes ist, als das Hochzählen eines Counters. Das System ist stabil. 
Ausnahmen wie immer Metastabilität und nukleare Strahlung.

von Klaus S. (kschleisiek)


Lesenswert?

Christoph Z. schrieb:
> 1. Wo ist deine Frage?
Das ist eine Anregung.

> jetzt schreibst du, dass sich euer Kunde die
> Verifikation "sparen" will von etwas das 20 Jahre erprobt ist?
Das war eine Entscheidung der Geschäftsleitung, alles Mechaniker, wenn 
auch lange im Raumfahrtgeschäft. Es war ja Technologie ohne Heritage, 
was ich da trieb.

> Was sagen die Requirements?
Jitter 5 msec hätte noch ins Timing gepasst.

von Duke Scarring (Gast)


Lesenswert?

Klaus S. schrieb:
> Es gibt ein internes ADC Register. Die Wandlung startet, wenn eine
> Kanalnummer in das Register geschrieben wird. Da gibt es zwei
> Möglichkeiten:
Bei einem Mehrkanal-ADC mache ich eine State-Machine, welche die Werte 
aller Kanäle kontinuierlich ausliest und dann alle Werte parallel zur 
Verfügung stellt. Dazu wird ein Flag getriggert und die Verarbeitung 
kann starten.
Alternativ holt sich eine CPU die Werte aus Registern, wenn sie der 
Meinung ist, neue Werte zu brauchen.

Bei Deiner Methode sehe ich nur mehr Aufwand, ohne mehr Nutzen. Oder 
habe ich etwas übersehen?

Duke

von Klaus S. (kschleisiek)


Lesenswert?

Duke Scarring schrieb:
> Bei Deiner Methode sehe ich nur mehr Aufwand, ohne mehr Nutzen. Oder
> habe ich etwas übersehen?

PLONK! - So machte das Brett vor meinem Kopf. Meine Güte, so einfach. 
Ein typischer Fall von, wie VHDL Strukturen davon beieiflusst sind, ob 
man von der Software oder der Hardware her denkt.

Eine völlige Entkopplung der I/O-Prozesse von den Regelungsprozessen 
wäre in dem Projekt locker mögliche gewesen. Und mit Registern gibt es 
dann kein Problem, parallel zuzugreifen. Und viel Sorge um 
Strahlungstoleranz muss man auch nicht haben, die Register werden ja 
zyklisch neu gesetzt.

Es gibt da 10 msec im Ablauf, bei denen zwei ADC-Kanäle während der 
Belichtungszeit des Wavemeters im Dauereinsatz sind, aber da könnte man 
einfach alle anderen I/Os ruhen lassen.

Wie gehst Du denn mit Speicher um, der von mehreren Prozessen genutzt 
wird?

von Jonas B. (jibi)


Lesenswert?

>Wie gehst Du denn mit Speicher um, der von mehreren Prozessen genutzt
>wird?

Mutex z.B.?

von Duke Scarring (Gast)


Lesenswert?

Klaus S. schrieb:
> Wie gehst Du denn mit Speicher um, der von mehreren Prozessen genutzt
> wird?
Bisher hab ich jedem Submodul, was Speicher benötigt hat einen eigenen 
Speicher gegönnt.

Hast Du evtl. ein Beispiel, wo man Speicher teilen möchte?

Und nur zum Verständnis: Wir reden hier nicht von Dual-Port-RAMs, wie 
man sie z.B. für FIFOs benötigt, oder?

Duke

von Klaus S. (kschleisiek)


Lesenswert?

Duke Scarring schrieb:
> Hast Du evtl. ein Beispiel, wo man Speicher teilen möchte?

Ein Dual-Port RAM, das an einem Port Spacewire angeschlossen hat, mit 
dem der Hostrechner sich die Werte anschauen kann zur Systemüberwachung 
und -optimierung. Am anderen Port sitzen vier parallele Prozesse, die 
die Daten generieren und das RAM auch als Speicher für Zustandsvariablen 
der Regelung nutzen.

von Christoph Z. (christophz)


Lesenswert?

Klaus S. schrieb:
> Am anderen Port sitzen vier parallele Prozesse, die
> die Daten generieren und das RAM auch als Speicher für Zustandsvariablen
> der Regelung nutzen.

Greifen diese schreibend auf die gleichen Adressen zu? Wenn ja, dann 
kommst du um einen Arbiter in irgendeiner Form und Mux nicht darum 
herum.

Wenn diese Prozesse von gleichen Adressen lesen, das ist ja schon mal 
alles gut.

Wenn diese Prozesse im Speicher komplett getrennte Adressbereiche haben 
(also der Speicher partitioniert ist), dann ist er ja gar nicht geteilt 
und ich würde 4 separate Dual-Port RAMs bauen und sie auf der Spacewire 
Seite logisch (simpler Adressdecoder) zu einem grossen zusammenfassen.

von Klaus S. (kschleisiek)


Lesenswert?

Christoph Z. schrieb:
> Greifen diese schreibend auf die gleichen Adressen zu? Wenn ja, dann
> kommst du um einen Arbiter in irgendeiner Form und Mux nicht darum
> herum.

Die greifen auf dieselben Adressbereiche zu, schreiben aber wenigstens 
niemals auf identische Adressen. Aber um eine Arbitration kommt man 
nicht herum, weil die Prozesse manchmal gleichzeitig den Speicher nutzen 
wollen.

Da sind wir dann wohl beim Request/Grant angekommen, oder?

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Evtl. koenntest du dir auch ueberlegen ein verbreitetes Bussystem, z.B. 
Wishbone (oder AXI wenns etwas aufwendiger sein soll) zu verwenden. Da 
gibts dann schon fertige Loesungen (oder zumindest Design Patterns) fuer 
entsprechende Arbitrierungen im Multimaster Betrieb.

Das ist allerdings nurmal so in Raum geworfen, keine Ahnung ob das fuer 
deine Prozessor Architektur praktikabel ist.

von Klaus S. (kschleisiek)


Lesenswert?

Wenn ich ein Prozessorinterface benutze, dann gibt es keine Arbitrierung 
um konkurrierende Prozesse, weil ein einzelner Prozessor niemals real 
parallel ist.  Mit einem Prozessor ist der Zugriff auf Memorybereiche 
IMMER unproblematisch, wenn das in einem Zyklus passiert.

Das war ja der Ausgangspunkt meiner Überlegungen hier (1. Posting). Und 
das fand Duke Scarring - zu Recht - zu umständlich, wenn es um's reine 
PeripherieIO geht.

Bei der Frage nach der Memoryarbitrierung geht es nicht um microCore, 
sondern um die flugfähige Version, die ohne Prozessor auskommen soll 
wegen der Verifikationskosten für den Prozessor.

: Bearbeitet durch User
von dfIas (Gast)


Lesenswert?

Christoph Z. schrieb:
> Ich finde das gerade irgendwie unüblich, zwischen EM und FM noch so
> essentielle Dinge zu wechseln. Wo ist die Risikobewertung dazu?
EMs (breadboards) müssen nur funktionell weitgehend passen. Ich vermisse 
hier aber mindestens einen Zwischenschritt. Üblich sind 
Qualifikationsmodelle (QM), Protoflight (PFM) und/oder letztens dann die 
FMs. Letztere aber allesamt vollständig "form fit & function" sowie 
gleiche qual-levels der Komponenten. Bei Änderungen zieht sich das durch 
alle Stufen. Nur bei low-budget geht es z. T. einfacher. Aber danach 
klingt das Ganze nicht.
Will man alles verifizieren, validieren, simulieren bis hin zu Coverage, 
Stress, WCAs, FMECAs, Radiation mit allem Drum und Dazu, TVac, EMC etc., 
schafft man den Sprung ohnehin nicht. Oder es kostet Jahre und der 
Aufwand für ein neues EM-Design geht darin unter. Heritage ist ebenfalls 
wichtig.
Ich würde mal auf die aktuelle Enwicklung der von der ESA forcierten 
LEON-Prozessorentwicklung (SPARC-V8-Design, inzwischen mit bis zu 4 
cores) schauen, da geht so einiges. Auch sind abseits vom Antifuse-RTAX 
bereits im Flug konfigurierbare PGAs im Einsatz, so dass man 
Designänderungen per TCs noch hinterherschicken kann.
Ich würde jedenfalls nochmal mit den Kollegen ein ausgewogenes 
Hardware-Software-Co-Design durchgehen, bevor ich mich für so einen 
Schritt entscheide. Notfalls den µC/die CPU gegen einen Baustein mit 
Heritage tauschen. Der LEON ist aktuell auch als µC in Entwicklung bzw. 
wurde schon angekündigt. Vlt. ist der Umstieg damit einfacher.

von Christoph Z. (christophz)


Lesenswert?

Klaus S. schrieb:
> Wenn ich ein Prozessorinterface benutze, dann gibt es keine Arbitrierung
> um konkurrierende Prozesse, weil ein einzelner Prozessor niemals real
> parallel ist.

Willkommen in der Neuzeit wo wir Systeme mit Muli-core Prozessoren und 
DMA bauen (DMA ist mittlerweile ein Feature das in 2$ STM32 drin ist). 
Nein, das ist keine Rocket-Science mehr, das ist deine Kompaktknipse, 
dein Fernseher, dein verstellbarer Rückspiegel am Auto etc.

Tobias B. schrieb:
> Da gibts dann schon fertige Loesungen (oder zumindest Design Patterns)
> fuer entsprechende Arbitrierungen im Multimaster Betrieb.

Klaus S. schrieb:
> Wenn ich ein Prozessorinterface benutze, dann gibt es keine Arbitrierung
> um konkurrierende Prozesse,

AXI und Whishbone sind keine "Prozessorinterfaces", das sind on-chip 
Bussysteme (Sie erfüllen den selben Zweck wie z. B. PCI auf 
Leiterplattenebene). Bei deren Entwicklung war schon lange klar das 
damit parallele Systeme gebaut werden sollen (jetzt halt mit Standard 
verglichen mit noch älteren Custom-systemen).

von Jonas B. (jibi)


Lesenswert?

>Die greifen auf dieselben Adressbereiche zu, schreiben aber wenigstens
>niemals auf identische Adressen.

Dann benutze halt ein Dualport-Ram und es gibt keine Probleme. Und bilde 
dich mal weiter, das kann man ja gar nicht mehr aushalten deine 
Steinzeitwissen.

von Klaus S. (kschleisiek)


Lesenswert?

dfIas schrieb:
> Will man alles verifizieren, validieren, simulieren bis hin zu Coverage,
> Stress, WCAs, FMECAs, Radiation mit allem Drum und Dazu ...

Danke für die Auflistung. Und da wollte man sich nicht auch noch einen 
Prozessorkern ohne Heritage ans Bein binden.

Ja, natürlich gibt es auch ein QM, aber das ist elektrisch identisch 
(außer ein paar Bufixes) zum FM.

> Ich würde mal auf die aktuelle Enwicklung der von der ESA forcierten
> LEON-Prozessorentwicklung (SPARC-V8-Design, inzwischen mit bis zu 4
> cores) schauen, da geht so einiges.

Damit hatte ich vor 7 Jahren zu tun, mein Quereinstieg in die Raumfahrt. 
Der SPARC im LEON2 ist Originalzustand mit Kommentaren, die in die 70er 
Jahre zurückreichen und der Code ist dank der seitdem gemachten 
Änderungen schwer durchschaubar. Da hilft es auch nicht, dass Jiri 
Gaisler schönen Code drumherum schreibt.

Die ganze Architektur mit den Parameterübergabepages ist ätzend, weil es 
letztlich immer wieder "nicht genug" sind und deshalb für Echtzeit das 
Paging weggeworfen werden muss. Vielleicht für Interruptprocessing, aber 
das wars. Die NASA war schlauer, die haben den ARM gepäppelt.

von Jonas B. (jibi)


Lesenswert?

>Die ganze Architektur mit den Parameterübergabepages ist ätzend, weil es
>letztlich immer wieder "nicht genug" sind und deshalb für Echtzeit das
>Paging weggeworfen werden muss. Vielleicht für Interruptprocessing, aber
>das wars. Die NASA war schlauer, die haben den ARM gepäppelt.

Bei

>Jitter 5 msec hätte noch ins Timing gepasst.

redest du von Echtzeit. Das Vitamin B das dich in den Job gebracht hat 
ist aber mächtig.

: Bearbeitet durch User
von Klaus S. (kschleisiek)


Angehängte Dateien:

Lesenswert?

Jonas B. schrieb:
> Dann benutze halt ein Dualport-Ram und es gibt keine Probleme.

Was nützt mir das, wenn ich mehr als zwei konkurrierende Prozesse habe?

Ich habe jetzt mal einen Arbitrator für 3 Prozesse gebaut. Eine 
vollständige Testbench als Datei, hier der Kern der Sache:
1
clk_en <= '0' WHEN  (req1 AND grant1) = '1'
2
                 OR (req2 AND grant2) = '1'
3
                 OR (req3 AND grant3) = '1'
4
           ELSE '1';
5
6
arbitrator: PROCESS (clk, reset)
7
BEGIN
8
   IF  reset = '1'  THEN
9
      grant1 <= '0';
10
      grant2 <= '0';
11
      grant3 <= '0';
12
   ELSIF  rising_edge(clk)  THEN
13
      IF  clk_en = '1'  THEN
14
         IF  req1 = '1'  THEN
15
            grant1 <= '1';
16
         ELSIF  req2 = '1'  THEN
17
            grant2 <= '1';
18
         ELSIF  req3 = '1'  THEN
19
            grant3 <= '1';
20
         END IF;
21
      END IF;
22
      IF  req1 = '0'  THEN  grant1 <= '0';  END IF;
23
      IF  req2 = '0'  THEN  grant2 <= '0';  END IF;
24
      IF  req3 = '0'  THEN  grant3 <= '0';  END IF;
25
   END IF;
26
END PROCESS arbitrator;
In der Simulation sieht man schön, dass REQ3 der gearschte Prozess ist, 
der bis zuletzt warten muss.

von Jonas B. (jibi)


Lesenswert?

Schön einen asynchronen Reset gebaut, aber Hauptsache irgendwelche 
Raumschiffe bauen...

von Klaus S. (kschleisiek)


Lesenswert?

PS: Aber jetzt muss jeder Prozess per Multiplexern aufs Memory 
geschaltet werden, wenn sein Grantsignal aktiv ist. Also im Prinzip das, 
was Duke Scarring weiter oben so qualifiziert hatte:
Beitrag "Re: parallele Prozesse konkurrieren um Peripherals"
> Bei Deiner Methode sehe ich nur mehr Aufwand, ohne mehr Nutzen. Oder habe
> ich etwas übersehen?

Da ich aber, wenn Memorybereiche zum IO dazugehören, sowieso multiplexen 
muss, kann ich auch gleich die ADCs und DACs auch als Memory mapped in 
diese erweiterte IO-Struktur einbeziehen, wie ich es im ersten Beitrag 
skizziert habe. Das hatte Duke übersehen, und mir ist es jetzt beim 
Koden der Arbitrierung klar geworden. Dann sticht der Vorteil meiner 
Idee: Arbitration ist nicht notwendig, es reicht ein "Busy" jeder 
Ressource, die mehr als einen Zyklus Verarbeitungszeit braucht.

: Bearbeitet durch User
von Jonas B. (jibi)


Lesenswert?

https://www.xilinx.com/support/documentation/application_notes/xapp228.pdf

Das lässt sich beliebig erweitern. Suche doch einfach mal, du bist doch 
nicht der erste der so Probleme hat.

von Jonas B. (jibi)


Lesenswert?

Ich empfehle dir dringend mal die Grundlagen zu lernen:

http://www.lothar-miller.de/s9y/categories/34-Getakteter-Prozess

"Wesentlich schlimmer als nur der zusätzliche Ressourcenverbrauch ist 
aber, dass ein asynchroner Reset zu undefiniertem Verhalten des Designs 
beim Verlassen des Resetzustands führen kann. Aufgrund unterschiedlicher 
Laufzeiten innerhalb des FPGAs sehen einzelne Register den Reset 
zeitverzögert weggehen. Wenn dann gerade ein Takt kommt, kann es sein, 
dass die eine Hälfte des FPGAs noch im Resetzustand ist, die andere 
Hälfte aber schon arbeitet."

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Klaus S. schrieb:
> In der Simulation sieht man schön, dass REQ3 der gearschte Prozess ist,
> der bis zuletzt warten muss.

Da gibt es unterschiedliche vorghensweisen, abhaengig von deinen 
Anforderungen.

Was du z.B. machen kannst, wenn alle Prozesse ungefaher gleich haeufig 
auf die Ressourcen zugreifen wollen, die Request in ein FIFO schreiben 
und dann nach und nach abarbeiten. Dann werden sie auch in der 
Reihenfolge bearbeiten in der die Zugriffe kommen.

Deine Methode ist dann wieder besser geeignet, wenn du kritische, aber 
selten auftretende Prozesse hast.

Ich bin da auch kein absoluter Fachmann, aber da muessten sich 
haufenweise Lesestoff finden lassen zum Thema Multiport Memory 
Controller in dem verschiedene Arbitrierungsarten diskutiert werden.

: Bearbeitet durch User
von Klaus S. (kschleisiek)


Lesenswert?

Lothar Miller wurde im Beitrag #6617310 Zitiert:
> "Wesentlich schlimmer als nur der zusätzliche Ressourcenverbrauch ist
> aber, dass ein asynchroner Reset zu undefiniertem Verhalten des Designs
> beim Verlassen des Resetzustands führen kann.

Also, weil Du keine Ruhe gibst: Die interne Logik muss mit synchronem 
Reset laufen, insofern habe ich den Arbitrator verhunzt. Aber die Pins 
müssen mit asynchronem Reset in den Safe State versetzt werden. Es kann 
nämlich auch der Oszillator ausfallen, und dann würden bei synchronem 
Reset die Pins im letzten Zustand herumhängen.

Beitrag #6617646 wurde von einem Moderator gelöscht.
Beitrag #6617674 wurde von einem Moderator gelöscht.
Beitrag #6617681 wurde von einem Moderator gelöscht.
von Christoph Z. (christophz)


Lesenswert?

Klaus S. schrieb:
> In der Simulation sieht man schön, dass REQ3 der gearschte Prozess ist,
> der bis zuletzt warten muss.

Ja, und genau so wie es Tobias geschrieben hat, gibt es viel Lesestoff 
zu Arbitrierung. In etwas so viel wie OS Scheduling Algorithmen, weil 
das sehr ähnlich bzw. aus mathematischer Sicht das selbe Problem ist 
(bitte korrigiert mich, falls ich das falsch interpretiert habe).

von Achim S. (Gast)


Lesenswert?

Christoph Z. schrieb:
> Ja, und genau so wie es Tobias geschrieben hat, gibt es viel Lesestoff
> zu Arbitrierung. In etwas so viel wie OS Scheduling Algorithmen, weil
> das sehr ähnlich bzw. aus mathematischer Sicht das selbe Problem ist
> (bitte korrigiert mich, falls ich das falsch interpretiert habe).

das interpretierst du schon richtig. Ein Aspekt ist aber: im Augenblick 
versucht Klaus die gesamte Arbitrierung in einem Taktzyklus 
durchzuführen. Wenn es bei dieser einfachen (und schnellen) 
Herangehensweise bleiben soll, ist die umsetzbare Komplexität der 
Verteilungsalgorithmen ziemlich eingeschränkt.

Aber Klaus schreibt auch, dass er sich Reaktionszeiten im µs-Bereich 
erhofft. Das lässt locker zu, dass z.B. bei jedem Request ein Prio-Liste 
durchsucht, der Zugriff danach vergeben und die Prio-Liste für den 
nächsten Request umsortiert wird. Für nur drei Teilnehmer könnte man das 
vielleicht noch sinnvoll in einen Taktzyklus reinquetschen, für viele 
Teilnehmer wäre es sinnvoll, das von einer FSM in mehreren Taktzyklen 
durcharbeiten zu lassen (und kann damit immer noch leicht im µs-Bereich 
bleiben).

von Klaus S. (kschleisiek)


Lesenswert?

Achim S. schrieb:
> Ein Aspekt ist aber: im Augenblick
> versucht Klaus die gesamte Arbitrierung in einem Taktzyklus
> durchzuführen. Wenn es bei dieser einfachen (und schnellen)
> Herangehensweise bleiben soll, ist die umsetzbare Komplexität der
> Verteilungsalgorithmen ziemlich eingeschränkt.

Das ist aber für meine Anwendung keine Einschränkung. Ausgangspunkt war 
ja, das die gesamte Regelung der Anwendung mit einem Prozessor 
(microCore) erledigt wurde mit nicht-präemptivem OS und fünf Tasks. Von 
daher war klar, dass die Regelungsebene nicht zeitkritisch ist, weil das 
alles pseudoparallel abgearbeitet werden konnte inklusive Overhead für 
den Scheduler. Und sämtliches IO war auch schon wie üblich 
Memory-mapped.

Eine Voll-VHDL Lösung ist auf jeden Fall schneller, weil der 
Scheduler-Overhead wegfällt. Zumal ja auch bei meiner vorgeschlagenen 
Methode, das Processor-OS in VHDL zu emulieren, so dass zu jeder Zeit 
nur ein einziger Regelungsprozess aktiv ist, gar keine Arbitration 
benötigt, sondern nur ein Busy-Signal der IOs, die mehr als einen 
Taktzyklus brauchen, um ein Ergebnis zu liefern.

Für ADCs kann man das mit Duke Scarrings Methode auf einen Zyklus 
reduzieren, indem die Ergebnisse dieser "Langläufer" von einem autonomen 
Modul zyklisch in Registern bereitgestellt werden. Dieses "Sampling" der 
ADCs wäre in meiner Anwendung auch kein Problem gewesen. Lediglich bei 
seriellen DACs sehe ich keinen Weg um das Busy herum. Aber das ist eine 
einzige Leitung je DAC, die an alle Prozesse geliefert wird, die es 
benötigen.

Ich wage die These, dass diese Methode für die meisten Regelungssysteme 
sinnvoll ist, in denen mehrere Prozesse auf Speicherbereiche zugreifen 
müssen. Denn: Die "High-Performance" Anwendungen mögen zwar mehr sexy 
sein, sie sind aber eher selten. Das Brot-und-Buttergeschäft sind sie 
eher nicht.

Auch in meiner Anwendung gibt es einen high-performance Teil, das 
Wavemeter, das so anspruchsvoll im Timing ist, das es eine eigene 
VHDL-Entity geworden ist, die sich von der Regelungsebene her als 
langsames, autonomes IO mit Busysignal darstellt. In der Struktur ist es 
auch trivial, eine zentrale Resource wie z.B. einen 27x27-bit 
Multiplizierer (wenn es keine DSP Einheiten gibt wie bei A3PE) allen 
Prozessen zur Verfügung zu stellen.

von Achim S. (Gast)


Lesenswert?

Klaus S. schrieb:
> Für ADCs kann man das mit Duke Scarrings Methode auf einen Zyklus
> reduzieren, indem die Ergebnisse dieser "Langläufer" von einem autonomen
> Modul zyklisch in Registern bereitgestellt werden.

sehe ich auch so.

Klaus S. schrieb:
> Lediglich bei
> seriellen DACs sehe ich keinen Weg um das Busy herum. Aber das ist eine
> einzige Leitung je DAC, die an alle Prozesse geliefert wird, die es
> benötigen.

warum funktioniert da sinngemäß nicht dasselbe wie bei den ADCs: deine 
verschiedenen Prozesse schreiben jeweils den aktuell gewünschten 
Spannungswerte in ein Register. Und ein Prozess läuft ständig alle 
DAC-Kanäle durch. Wo sich ein Registerwert geändert hat, gibt er den 
neuen Wert auf den gewünschten DAC aus, und geht dann zum nächsten 
DAC-Kanal weiter.

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Aus Interesse an dem Thema bin ich gestern auf ein Paper gestossen 
welches den Matrix Arbiter erklaert:

https://www.researchgate.net/publication/4079961_Low-Latency_Virtual-Channel_Routers_for_On-Chip_Networks

Seite 6, Abschnitt "Precomputing Arbitration Decisions".

Ist relativ einfach implementiert, allerdings skaliert das ziemlich 
schlecht (zumindest wenn man in jedem Zyklus eine Entscheidung vom 
Arbiter anstrebt). Hier mal was zur Inspiration:

https://gitlab.com/baumannt/matrix-arbiter

Die ganze XOR Verknuepfung in HDL zu machen, habe ich mir gespart. Macht 
der Synthesizer besser als ich das kann. ;-) Auch habe ich das leicht 
modifiziert und die Diagonalelemente alle 1 gesetzt und dabei den 
Reihen/Spalten Set/Reset vertauscht. Das macht die if Abfrage etwas 
nicer, vom Logikaufwand reduziert es allerdings nichts.

Performance Tests kann ich keine anbieten, mit 16 LUTs und 4 FFs (in 
einem Artix 7) bei 4 Arbiter Ports kann es aber nicht allzu langsam 
sein.

Keine Ahnung wie weitverbreitet die Idee des Matrix Arbiters ist, ich 
hab davon gestern zum ersten mal gelesen und finde die Idee sehr smart. 
Vielleicht interessiert sich ja noch jemand dafuer. :-D

von FPGA-Master (Gast)


Lesenswert?

Klaus S. schrieb:
> Ich wage die These, dass diese Methode für die meisten Regelungssysteme
> sinnvoll ist, in denen mehrere Prozesse auf Speicherbereiche zugreifen
> müssen.

Kommt drauf an. Ich habe solche Systeme dauernd am werkeln. Lösung:

Schatten-RAMs zum Lesen und verjüngende Anfragepipelines zum Schreiben, 
nach der Methode der "eingeschränkten Schreiberprio" mit 2-stufigem 
mutal exclusion. Damit ist determinierbar, wie lange ein Schreibzugriff 
maximal warten muss und das System kann skaliert werden. Braucht halt 
händische Semaphoren.

Ein Tipp noch: Du denkst zu sehr in Prozessen. Diese Abläufe, die da in 
SW formuliert sind, laufen nicht auf dem FPGA. Sie laufen in der 
Simulations- und Synthesesoftware. Du brauchts IMMER eine 
Vorrangschaltung oder eine Veroderung um Information 
zusammenlaufenzulassen. Das gilt für einfach LEDs, die von zwei 
Schaltungen gesteuert werden, wie auch komplette Motoren.

Als Beispiel aus der Regelung sei noch der Fall der Übernahme einer 
Regelung durch eine andere beschrieben, weil eine ausgefallen ist oder 
ihre Überwachung sagt, dass sie ausser Tritt ist. Dann musst du alle 
Ausgänge "analog" überblenden.

von Klaus S. (kschleisiek)


Lesenswert?

Jonas B. schrieb:

> Ich empfehle dir dringend mal die Grundlagen zu lernen:
> http://www.lothar-miller.de/s9y/categories/34-Getakteter-Prozess

Da habe ich mich erstmal ins Bockshorn jagen lassen :(

Auch Miller ist nicht ganz klar. Es gibt sozusagen zwei Sachen, die man 
asynchrones Reset nennen kann:

1.) Der Reset-Input von außen, bevor er, wie alle externen asynchronen 
Ereignisse, mit der Systemclock und zwei hintereinandergeschalteten FFs 
"einsynchronisiert" wird.

2.) Der vor allem bei Xilinx beliebte autonome Reset Eingang an jedem 
FF. Der Reset ist asynchron und wartet nicht auf die clock am 
FF-Eingang.

Wenn man einen asynchronen Reset gemäß 1. auf den asynchronen Reset 
Eingang gemäß 2. gibt, kann es zu Clockflankeninterferenz aka 
Metastabilität kommen. Das kann ein FPGA reichlich durcheinanderbringen 
und ich erinnere Situationen, in denen es nur noch durch Strom aus/Strom 
an wieder zurückgeholt werden konnte. Das gleiche gilt aber auch für ein 
per Logik erzeugtes synchrones Reset eines FF. Wenn da das Reset-Signal 
nicht einsynchronisiert war, kann es genauso böse enden.

Wenn man nun das Resetsignal ordentlich einsynchronisiert hat, kann man 
es ohne Gefahr sowohl auf den asychronen Reseteingang eines FFs geben, 
als auch dem FF per synthetisierter Logik unterjubeln. Das ist dann eine 
Frage der Resourcennutzung.

Ich glaube, dass man auch gegen ausfallenden Oszillator gewappnet ist, 
wenn das äußere Reset so einsynchronisiert wird:
1
-- reset_a kommt direkt vom Pin
2
SIGNAL reset, reset_1 : STD_LOGIC;
3
4
sync_reset : PROCESS (clk, reset_a)
5
BEGIN
6
   IF  reset_a = '1'  THEN
7
      reset_1 <= '1';
8
      reset <= '1';
9
   ELSIF  rising_edge(clk)  THEN
10
      reset_1 <= reset_a;
11
      reset <= reset_1;
12
   END IF;
13
END PROCESS sync_reset;
Mit dem reset müsste man jetzt sowohl die interne Logik als auch die 
Pins treiben können.

von FPGA-Master (Gast)


Lesenswert?

Klaus S. schrieb:
> 2.) Der vor allem bei Xilinx beliebte autonome Reset Eingang an jedem
> FF. Der Reset ist asynchron und wartet nicht auf die clock am
> FF-Eingang.

Wo gibt es bei Xilinx einen autonomen Reset Eingang?

Ungeachet dessen obliegt es dem designer, zu entscheiden, was er bauen 
möchte. Und wer asynchrone Resets braucht, der muss sich eben mit dessen 
Eigenschaften herumschlagen.

Ich verwende seit 15 Jahren keine mehr.

von FPGA-Master (Gast)


Lesenswert?

Klaus S. schrieb:
> sync_reset : PROCESS (clk, reset_a)
> BEGIN
>    IF  reset_a = '1'  THEN
>       reset_1 <= '1';
>       reset <= '1';
>    ELSIF  rising_edge(clk)  THEN
>       reset_1 <= reset_a;
>       reset <= reset_1;
>    END IF;
> END PROCESS sync_reset;

Das hier ist so eine Sache: Man sollte den letzten Reset völlig synchron 
betreiben, wenn man einen braucht, weil man sonst ein Problem mit dessen 
Loslassen bekommt.

Was ich dazu nur sagen kann: Finger weg davon! Gerade Xilinx nutzt 
überall hin- und her-gesychte Resets, die als "asynchron" auf andere 
Bausteine gehen, nur um sie dort nochmal einzusynchronisieren.

Das ist zwar technisch ok, führt jedoch zu einem völlig verworrenen 
Resetbaum im System, wo keiner mehr weiss, wer wann vor wem losgelassen 
wurde. Als Resultat hat man ein nichtvorhersagbares Anlaufverhalten und 
das ist das absoluti wichtigere, als der Vorteil alles schlagartig 
totlegen zu können.

Daher

1. RESET-EINGANG von extern auf ASYNCH-RESET der Master-PLL
2. LOCKED der Master-PLL invertiert auf alle anderen PLLs.
3. LOCKED aller PLLs einsynchronisieren und in der Master-Domain 
auswerten
4. Wenn alle gestartet, dann nacheinander in der richtigen Reihenfolge 
resets der Module loslassen und zwar so, dass ausreichend Taktflanken 
dazwischen sind.
5. Alle Module synchen diesen Reset ein und nutzen ihn lokal für ihre 
Schaltungen.
6. Module, die mehr als eine domain nutzen, brauchen alle Resets, mit 
denen sie ihre Schaltungsteile resetten und Signale einsynchen.

Das alles sind aber Grundlagen und lösen nicht das vom TE gestellte 
Problem der Multi-Zugriffe. Dazu lese man sich in die klassischen 
Methoden des Multi-Taskings ein. Dort sind alle erdenklichen Fälle 
behandelt und Lösungen publiziert.

von Klaus S. (kschleisiek)


Lesenswert?

FPGA-Master schrieb im Beitrag #6618323:
> Das hier ist so eine Sache: Man sollte den letzten Reset völlig synchron
> betreiben, wenn man einen braucht, weil man sonst ein Problem mit dessen
> Loslassen bekommt.

Verdammt, ja, der sync_reset Prozess ist dann zwar der einzig 
Verbliebene, der mit einem externen asynchronen Reset an seinem 
asynchronen Reseteingang belästigt wird, kann deshalb aber natürlich 
selbst aus dem Gleis geworfen werden. Mist.

Das mit dem "sofort alles schlagartig totlegen" ist ja tatsächlich nur 
für die Erzeugung eines Safe-States der Outputpins wichtig. Das muss 
auch dann funktionieren, wenn der Oszillator steht. Aber dafür kann man 
getrost den externen, asynchronen Reset nehmen, solange in den 
Outputpads keine FFs benutzt werden.

: Bearbeitet durch User
von Christoph Z. (christophz)


Lesenswert?

FPGA-Master schrieb im Beitrag #6618323:
> Das alles sind aber Grundlagen und lösen nicht das vom TE gestellte
> Problem der Multi-Zugriffe.

Genau, zu Reset Fragen gibt es hier im FPGA Forum viele Threads, da es 
immer wieder Diskussions- und Klarstellungsbedarf gibt (und geben wird). 
War ein Thema das in meinem Studium definitiv vernachlässigt wurde...

Klaus S. schrieb:
> Aber die Pins
> müssen mit asynchronem Reset in den Safe State versetzt werden. Es kann
> nämlich auch der Oszillator ausfallen, und dann würden bei synchronem
> Reset die Pins im letzten Zustand herumhängen.

Ja, diese Anforderung gibt es öfter in sicherheitskritischen 
Anwendungen. Typische Lösung dazu: Asynchroner Eintritt in den 
Resetzustand und synchroner Austritt. Genau weil sonst beim Austritt 
Metastabilität auftreten kann (oder schon mal die verschiedenen Blöcke 
zu unterschiedlichen Taktflanken zu arbeiten beginnen.)

von Tippgeber (Gast)


Lesenswert?

Christoph Z. schrieb:
> (oder schon mal die verschiedenen Blöcke
> zu unterschiedlichen Taktflanken zu arbeiten beginnen.)

Christoph Z. schrieb:
> Klaus S. schrieb:
>> Aber die Pins
>> müssen mit asynchronem Reset in den Safe State versetzt werden. Es kann
>> nämlich auch der Oszillator ausfallen, und dann würden bei synchronem
>> Reset die Pins im letzten Zustand herumhängen.

Soweit mir bekannt lassen sich die PLLs im FPGA so konfigurieren, dass 
sie weiterlaufen, wenn die externe PLL ausfällt. So einen 
Schaltungsblock haben wir hier auf der Basis eines SPARTAN6. Einmal 
getaktet, rennt der weiter mit ungefähr derselben Frequenz. Also eben 
die die voreingestellt ist. Wahrscheinlich geht das über die feedback 
PLL oder den zweiten Eingang.

von Christoph Z. (christophz)


Lesenswert?

Tippgeber schrieb:
> Soweit mir bekannt lassen sich die PLLs im FPGA so konfigurieren, dass
> sie weiterlaufen, wenn die externe PLL ausfällt. So einen
> Schaltungsblock haben wir hier auf der Basis eines SPARTAN6. Einmal
> getaktet, rennt der weiter mit ungefähr derselben Frequenz.

Auch interessant, ja.
Im Raumfahrtbusiness musst du den Kunden zuerst mal überzeugen um 
überhaupt mal eine PLL einsetzen zu dürfen. Aber dann ist das eine 
Variante.

Microchip/Microsemi/Actel hat einen Block in ihren FPGAs um Clocks 
glitch-frei umzuschalten, damit lässt sich eine Oszillator redundanz 
bauen.

von Klakx -. (klakx)


Lesenswert?

Noch ein paar Ergänzungen:

Klaus S. schrieb:
> Ich habe jetzt mal einen Arbitrator für 3 Prozesse gebaut [..]

Das ist ein ganz normaler Priority-Arbiter. Alternativ gibt es noch den 
Round-Robin-Arbiter für gleichverteiltem Zugriff. Ich finde diese zwei 
Typen reichen für die meisten Fälle aus. Selbst bei Xilinx kann man 
diese im Interconnect auswählen.

Der aktuelle ist fest auf 3 Eingänge ausgelegt. Schaut man jedoch bei 
den Herstellern in die IPs oder in der Literatur, dann reicht für das 
generische priority enconding wenige Operationen.
Der RR basiert auf dem gleichen Prinzip, hat jedoch zusätzlich einen 
laufenden Zähler als Basis, wodurch nach jedem Zugriff der nächste 
Teilnehmer bevorzugt wird.


Nochmal zum asynchronen Reset.
Verschiedene Standards zur funktionalen Sicherheit verlangen diesen. 
Auch bei der ESA wird dieser bevorzugt.
..und selbstverständlich ist der Reset-Release immer einsynchronisiert.

von Klaus S. (kschleisiek)


Lesenswert?

Klaus S. schrieb:
> Wenn man nun das Resetsignal ordentlich einsynchronisiert hat, kann man
> es ohne Gefahr sowohl auf den asychronen Reseteingang eines FFs geben,
> als auch dem FF per synthetisierter Logik unterjubeln. Das ist dann eine
> Frage der Resourcennutzung.

Ich habe jetzt microCore auf Lattice XP2 alternativ implementiert. (In 
beiden Fällen wird das externe Resetsignal erstmal über 2 FFs 
einsynchronisiert.) Sowohl Synplify als auch das Lattice P&R hatten 
einen Clock-Constraint von 25 MHz.

1.) Mit Reset in der Logik

3074 synthetisierte LUTs
31.7 MHz predicted Speed
2097 tatsächlich verbrauchte SLICES
26.3 MHz tatsächliche Speed

2.) Mit Reset am (asynchronen) Reset Eingang der FFs

3006 synthetisierte LUTs
32.5 MHz predicted Speed
2017 tatsächlich verbrauchte SLICES
26.3 MHz tatsächliche Speed

Man sieht deutlich, was zu erwarten war: Die Nutzung des separaten 
Reset-Eingangs vermindert die nötigen Logikresourcen und macht das 
Design ein kleines bischen schneller.

: Bearbeitet durch User
von Jonas B. (jibi)


Lesenswert?

Ein Softcore ohne gcc oder llvm frontend ist einfach unbrauchbar, viel 
zu exotisch. Aber das willst du ja nicht hören.

von Klaus S. (kschleisiek)


Lesenswert?

Jonas B. schrieb:
> Ein Softcore ohne gcc oder llvm frontend ist einfach unbrauchbar, viel
> zu exotisch. Aber das willst du ja nicht hören.

Du bist gerne eingeladen, das für microCore zu realisieren. Ich werde 
das nicht tun, weil ich nicht einsehe, warum ich freiwillig eine 
Zwangsjacke wie C anziehen soll. In den letzten 20 Jahren habe ich mit 
microCore acht eingebettete Projekte realisiert. Soviel zu 
"unbrauchbar".

Der C-compiler auf Basis LCC hat übrigens als Output Forth erzeugt. Dann 
hat der Crosscompiler zum Abschluss die Peephole-Optimierungen gemacht 
und die "Symboltabelle" für den Debugger aufgebaut. Dabei ist eines klar 
geworden: Wegen der Bytementalität von C sind Unions mit microCore nicht 
möglich, es sein denn, man beschränkt sich auf eine Version mit 16 oder 
32 bit Wortbreite und implementiert zusätzliche Byteoperationen per 
read-modify-write. Letztere bringen aber an Processingpower gar nichts.

Beitrag #6624855 wurde von einem Moderator gelöscht.
von Martin S. (strubi)


Lesenswert?

Klaus S. schrieb:
> Du bist gerne eingeladen, das für microCore zu realisieren. Ich werde
> das nicht tun, weil ich nicht einsehe, warum ich freiwillig eine
> Zwangsjacke wie C anziehen soll.

Naja, C ist Industriestandard. Gegenfrage: Warum sollte sich heute ein 
Ingenieur mit der Forth-Nische befassen?

Klaus S. schrieb:
> Der C-compiler auf Basis LCC hat übrigens als Output Forth erzeugt. Dann
> hat der Crosscompiler zum Abschluss die Peephole-Optimierungen gemacht
> und die "Symboltabelle" für den Debugger aufgebaut. Dabei ist eines klar
> geworden: Wegen der Bytementalität von C sind Unions mit microCore nicht
> möglich, es sein denn, man beschränkt sich auf eine Version mit 16 oder
> 32 bit Wortbreite und implementiert zusätzliche Byteoperationen per
> read-modify-write. Letztere bringen aber an Processingpower gar nichts.

Wie hier in div. anderen Threads schon nachzulesen ist, macht der LCC 
wegen seiner nicht-C99-compliance (u.a. designated initializers) eine 
sehr schlechte Nummer. Auch wenn die CPU-Power auf der Strecke bleibt 
und man die Multiplexer-Logik fuer Byte/Word-Zugriffe unbedingt sparen 
will, sollte man wenigstens Byte-Zugriffe emulieren. Es geht dabei vor 
allem darum, dass sich C-libs wiederverwerten lassen.

Dazu kann ich nur raten, die ZPU-Architektur eingehend zu studieren. Ist 
quasi State-of-the Art, was gut verifizierbare Stackmaschinen 
(Safety...) mit anstaendigem Compilersupport (GCC, LLVM) angeht.
Das Rad mit den Tools will man nicht neu erfinden..

von Tippgeber (Gast)


Lesenswert?

Klakx -. schrieb:
> Nochmal zum asynchronen Reset.
> Verschiedene Standards zur funktionalen Sicherheit verlangen diesen.
> Auch bei der ESA wird dieser bevorzugt.

Das funktioniert aber nur, wenn man den reset nicht einsynchronisiert. 
Die meisten designs sind aber so aufgezogen. Siehe hier:

Klaus S. schrieb:
> > beiden Fällen wird das externe Resetsignal erstmal über 2 FFs
> einsynchronisiert.)

von Duke Scarring (Gast)


Lesenswert?

Tippgeber schrieb:
> Klakx -. schrieb:
>> Nochmal zum asynchronen Reset.
>> Verschiedene Standards zur funktionalen Sicherheit verlangen diesen.
>> Auch bei der ESA wird dieser bevorzugt.
>
> Das funktioniert aber nur, wenn man den reset nicht einsynchronisiert.
> Die meisten designs sind aber so aufgezogen.

Wenn der Reset kommt -> asynchron,
wenn der Reset geht -> synchron.

Und nur für FF, die das wirklich brauchen. Ich mache keine Raumfahrt und 
keine ASICs, daher verzichte ich fast immer auf den Reset...

Duke

von Klaus S. (kschleisiek)


Lesenswert?

Duke Scarring schrieb:
>> Das funktioniert aber nur, wenn man den reset nicht einsynchronisiert.
>> Die meisten designs sind aber so aufgezogen.
>
> Wenn der Reset kommt -> asynchron,
> wenn der Reset geht -> synchron.

Also so, wenn reset_n vom Pin kommt:
1
reset_a <= NOT reset_n;
2
sync_reset: synchronize PORT MAP (clk, reset_a, reset_s);
3
reset <= reset_a OR reset_s;
Und DAS reset kann man metastabilitätsfrei sowohl an die Pins, an die 
Logik und die "asynchronen" reset Eingänge der FFs anlegen.

> Und nur für FF, die das wirklich brauchen. Ich mache keine Raumfahrt und
> keine ASICs, daher verzichte ich fast immer auf den Reset...

Wird auch dort so gehalten: Reset nur dann, wenn erforderlich.

von Klaus S. (kschleisiek)


Lesenswert?

Jonas B. schrieb:
> Ein Softcore ohne gcc oder llvm frontend ist einfach unbrauchbar, viel
> zu exotisch. Aber das willst du ja nicht hören.

JaJaJa. Ich hab's inzwischen kapiert, ist ja gut.

Ich suche jetzt nach einem Informatik-Masterstudenten, der das als 
Abschlussarbeit machen würde. Das wird mindestens 2 Jahre dauern, bis da 
was Brauchbares existiert. Solange kann microCore halt nur im Assembler 
programmiert werden. Und das Arduino-Board muss dann auch noch so lange 
warten.

Das gibt mir die Zeit, einen 10baseT-PHY im FPGA zu entwickeln und den 
Code für UDP zu portieren. Ich vermute mal, dass das mit deutlich 
weniger Strom auskommt, als ein externer 10/100baseT-PHY. Und dann wäre 
das geplante Arduinoboard IoT-fähig.

von Klaus S. (kschleisiek)


Lesenswert?

Martin S. schrieb:
> Dazu kann ich nur raten, die ZPU-Architektur eingehend zu studieren. Ist
> quasi State-of-the Art, was gut verifizierbare Stackmaschinen
> (Safety...) mit anstaendigem Compilersupport (GCC, LLVM) angeht.

Ja, aber wo finde ich eine Beschreibung und ein Bild der 
ZPU-Architektur?
Bisher habe ich bei meiner Suche nur Code gefunden.

von Duke Scarring (Gast)


Lesenswert?

Klaus S. schrieb:
> 10baseT-PHY im FPGA
Ganz rudimentär findet man das hier:
https://www.fpga4fun.com/10BASE-T0.html
Der Stromverbrauch bei Ethernet kommt m.E. wegen der Treiber. Man will 
ja nach 200 m Kabel noch Signal haben.

Klaus S. schrieb:
> Ja, aber wo finde ich eine Beschreibung und ein Bild der
> ZPU-Architektur?
Die Doku ist etwas versteckt:
https://github.com/zylin/zpu/tree/master/zpu/docs
Bilder gibt es glaube ich (noch) keine...

Hier hat jemand den praktischen Einsatz dokumentiert:
https://www.mikrocontroller.net/articles/ZPU:_Softcore_Implementierung_auf_Spartan-3_FPGA

Duke

von Martin S. (strubi)


Lesenswert?

Klaus S. schrieb:
> Ja, aber wo finde ich eine Beschreibung und ein Bild der
> ZPU-Architektur?

Noch eine Schnell-Referenz:

http://www.alvie.com/zpuino/zpu_instructions.html

Auch eine gute Quelle war die alte Mailing-Liste 
(http://zylin.com/pipermail/zylin-zpu_zylin.com/), die ist leider aber 
nicht mehr erreichbar. Der ZPU-Erfinder Oyvind Harboe ist auch seit 
Jahren nicht sonderlich aktiv an der Front.
Die Architektur ist so simpel, dass sie kaum dokumentiert werden muss, 
allerdings wuerde ich mir die 'Zealot'-Variante anschauen.
Ansonsten gabs noch bei papilio.cc etwas Community-Arduino-Bewegung.

Klaus S. schrieb:
> Ich suche jetzt nach einem Informatik-Masterstudenten, der das als
> Abschlussarbeit machen würde

Ich lese das mal als 'ironisch gemeint' :-)
Falls doch nicht: Es geistert auch noch ein LLVM-Backend zur ZPU(ng) 
herum, was man sich fuer Stack-Maschinen als Vorbild nehmen kann, 
allerdings muss deine CPU offset-Adressierung (relativ zum SP) koennen.
Von GCC wuerde ich persoenlich die Finger lassen, da das ganze 
GIMPLE/RTL-Geraffel auf registerbasierte Architekturen ausgerichtet ist. 
Und erst die Wartungsarbeit fuers Mainlining: Viel Gratis-Arbeit fuer 
die FSF angesagt und schlussendlich wird dein 'Copyright' entfernt.

von Klaus S. (kschleisiek)


Lesenswert?

Martin S. schrieb:
>
> http://www.alvie.com/zpuino/zpu_instructions.html

Wirklich sehr schlank. Unklar ist mir aber, ob die ZPU einen Return- und 
einen Datenstack hat, oder ob die Datenoperationen auch alle auf dem 
Returnstack stattfinden. Wieso kommen die dann nicht mit den 
Rücksprungadressen ins Gehege? Auf was operieren die NOT, AND, + usw. 
denn, und wo landet das Ergebnis? Was die Literale angeht: Das macht 
uCore genauso wie die ZPU.

> Ich lese das mal als 'ironisch gemeint' :-)

Nein nein, keineswegs, ich habe meine akademischen Kontakte schon 
angefunkt.

> Falls doch nicht: Es geistert auch noch ein LLVM-Backend zur ZPU(ng)
> herum, was man sich fuer Stack-Maschinen als Vorbild nehmen kann,
> allerdings muss deine CPU offset-Adressierung (relativ zum SP) koennen.

Auf llvm als bessere Alternative zu gcc haben mich andere auch schon 
aufmerksam gemacht. Und ja, microCore kann relativ zum Returnstack 
adressieren und der Returnstack liegt im Datenspeicher.

Zudem wurde für eine frühere uCore-Version bereits das Frontend des lcc 
modifiziert, so dass Stack- statt Registerallokation gemacht wird. Damit 
konnten fast alle Zugriffe auf lokale Variablen in Returnstackframes 
durch den Datenstack und allfällige "Umsortierungsoperationen" ersetzt 
werden. Kurz: uCore ist mit guter Stackallokation ein ziemlich 
effizienter C Prozessor.

Bleibt nur das blöde Thema Bytes. uCore hat eine konfigurierbare 
Datenwortbreite und in letzter Zeit benutze ich meist 27 Bits, weil:
1) 16 ist oft zu wenig.
2) 24 ist meist genug.
3) blockRAMs sind 9 Bits breit, warum da was wegwerfen? -> 27 Bits.

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Klaus S. schrieb:
>> Ich lese das mal als 'ironisch gemeint' :-)
>
> Nein nein, keineswegs, ich habe meine akademischen Kontakte schon
> angefunkt.

Dann halte ich es aber fuer bedenklich wenn du deinen microCore 
verkaufen moechtest. Oder stellst du en Studenten in der Zwischenzeit 
als an Werkstudent an und bezahlst ihn auch entsprechend?

von Klaus S. (kschleisiek)


Lesenswert?

Tobias B. schrieb:
> Dann halte ich es aber fuer bedenklich wenn du deinen microCore
> verkaufen moechtest.

Ja, finde ich auch.

Ich stelle mit dem nächsten Update auf git den VHDL-Code unter eine 
Public License, die im Prinzip wie BSD oder LGPL ist. "Nimm es und mach 
was draus."

Die Forth-Nische stellt schon sicher, dass ich nicht von 
Supportanforderungen überwältigt werde ;)

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Klaus S. schrieb:
> Ich stelle mit dem nächsten Update auf git den VHDL-Code unter eine
> Public License, die im Prinzip wie BSD oder LGPL ist. "Nimm es und mach
> was draus."

Very nice! :-D

von F. M. (foxmulder)


Lesenswert?

Klaus S. schrieb:
> Beim Flight-Model

Klaus S. schrieb:
> Ich suche jetzt nach einem Informatik-Masterstudenten, der das als
> Abschlussarbeit machen würde.

Klaus S. schrieb:
> das geplante Arduinoboard

Also verwendest du "Flight-Model" nur als coole Bezeichnung?
Das ist ja nicht wirklich etwas mit Luft&Raumfahrt?

mfg

von Klaus S. (kschleisiek)


Lesenswert?

A. K. schrieb:
> Also verwendest du "Flight-Model" nur als coole Bezeichnung?
> Das ist ja nicht wirklich etwas mit Luft&Raumfahrt?

Das sind zwei verschiedene Projekte:

Das letzte Projekt vor meiner Verrentung war die Steuerung der 
"Frequency Reference Unit" für das deutsch/französische MERLIN-Projekt. 
Damit wird der Methangehalt der Atmosphäre aus 400 km Höhe gemessen 
werden.

Das Zukunftsprojekt ist "Arduinoboard", das jetzt erstmal warten muss, 
bis eine traditionelle Entwicklungsumgebung für microCore steht.

: Bearbeitet durch User
von Martin S. (strubi)


Lesenswert?

Klaus S. schrieb:
> Wirklich sehr schlank. Unklar ist mir aber, ob die ZPU einen Return- und
> einen Datenstack hat, oder ob die Datenoperationen auch alle auf dem
> Returnstack stattfinden. Wieso kommen die dann nicht mit den
> Rücksprungadressen ins Gehege? Auf was operieren die NOT, AND, + usw.
> denn, und wo landet das Ergebnis? Was die Literale angeht: Das macht
> uCore genauso wie die ZPU.

Die ZPU kommt mit einem Stack aus, die Operationen laufen auf TOS/NOS, 
in der obigen ZPUino-Uebersicht ist das pro opcode in Pseudocode 
beschrieben, wer was wie macht. Etwas knapp, aber umsetzbar. Als 
Assembly-Hacker muss man halt das Stack-Unwinding im Blick haben, und 
der C-Compiler es richtig machen :-).

Klaus S. schrieb:
> Bleibt nur das blöde Thema Bytes. uCore hat eine konfigurierbare
> Datenwortbreite und in letzter Zeit benutze ich meist 27 Bits, weil:

Das Problem hat grundsaetzlich die abgespeckte ZPU-Variante auch, die 
emulierten Befehle (wenn nicht in HW implementiert, wird in den 
Emulation-'uCode'-Bereich gesprungen) sind dir bestimmt aufgefallen. 
Hier waeren das also LOADB/STOREB.
An der Stelle spare ich mir lieber verstopfende Logik und lasse den 
Byte-I/O die DMA-Engine erledigen. Vorbild hier: Blackfin-Architektur. 
Braucht dann auch kaum noch Interrupts, aber mindestens 
Dual-Port-Memory.

von chris_ (Gast)


Lesenswert?

>Das Zukunftsprojekt ist "Arduinoboard", das jetzt erstmal warten muss,
>bis eine traditionelle Entwicklungsumgebung für microCore steht.

Das scheint mir hier ganz passend:
https://www.eejournal.com/article/fpga-based-arduino-clones-on-steroids/

Die große Kunst ist ja, die Einfachheit der Arduinowelt auf ein FPGA zu 
übertragen. Das ist aber meiner Meinung nach Arduino selbst nicht 
gelungen:
https://store.arduino.cc/arduino-mkr-vidor-4000

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.