Hallo, ich habe mir ein minimales Kommunikationsprotokoll zwischen verschiedenen Entities ausgedacht (Clock, Request, Adresse, Read- und Write-Daten, Acknowledgement). Das funktioniert auch. Jetzt möchte ich aber mehr als zwei Entities dort anschließen, aber ohne zentral die Adressen dekodieren zu müssen, also ein klassisches Bussystem aufbauen. Ein Master, drölfzig Slaves, die jeweils mit ihrer Basisadresse instantiiert werden und an sie gerichtete Anfragen beantworten. Wie kriege ich die Signale von den Slaves zum Master (also Acknowledgement und Read-Daten) hin? Tristate scheint es im FPGA nicht zu geben... Der Hintergrund ist, dass ich in einem Block einen Master habe, der auf Block-RAM und weitere Blöcke zugreifen soll. Außerdem gibt es eine Schnittstelle nach draußen, die das ebenfalls können soll. Das Block-RAM ist dualported, aber die anderen Blöcke sind es nicht und ich wollte ungern eine massive Crossbar in die Mitte klatschen, die ich jedesmal aufwändig anpassen muss, wenn ich einen neuen Block einklebe. Wie löst ihr solche Probleme normalerweise? Gruß, svenska
S. R. schrieb: > Wie kriege ich die Signale von den Slaves zum Master (also > Acknowledgement und Read-Daten) hin? Tristate scheint es im FPGA nicht > zu geben... Wenn's kein inout gibt, hat eben jedes Modul einen "in"- und einen "out"-Bus sowie ein zugehöriges "sel", das es aktiviert, wenn es sich als angesprochen erkannt hat. Die Busse werden auf dem Toplevel-Entity zusammengeführt und das bekommt einen Buscontroller, der die "out"-Signale des Moduls, das "sel" aktiviert hat, wieder auf den "in"-Bus legt. Dort wird dann auch die Tristate-Steuerung "nach draußen" implementiert. War das deine Frage?
:
Bearbeitet durch User
Markus F. schrieb: > S. R. schrieb: >> Wie kriege ich die Signale von den Slaves zum Master (also >> Acknowledgement und Read-Daten) hin? Tristate scheint es im FPGA nicht >> zu geben... > > Wenn's kein inout gibt, hat eben jedes Modul einen "in"- und einen > "out"-Bus sowie ein zugehöriges "sel", das es aktiviert, wenn es sich > als angesprochen erkannt hat. Die Busse werden auf dem Toplevel-Entity > zusammengeführt und das bekommt einen Buscontroller, der die > "out"-Signale des Moduls, das "sel" aktiviert hat, wieder auf den > "in"-Bus legt. Alternativ kann man alle von den Slaves weggehneden signale ver-ODER-n, das ist einfacher als der beschriebene Muxer für die ACK. Das geht auch halbwegs generisch, alle ack in einen bitvektor o.ä. stecken und mit bspw or_reduce immer den gesamten vector verdödeln. http://electronics.stackexchange.com/questions/85922/vhdl-or-ing-bits-of-a-vector-together Ansonsten schau mal in die Wishbone spec, da werden verschiedenen Bus-topologien auf ihre FPGA-tauglichkeit untersucht, bspw zentrale versus verteilter adressdecoder https://opencores.org/cdn/downloads/wbspec_b4.pdf S121 ff.
S. R. schrieb: > Tristate scheint es im FPGA nicht zu geben... Seit der Jahrtausendwende nicht mehr. Alle Busse müssen zu Multiplexern aufgelöst werden. > Wie löst ihr solche Probleme normalerweise? Über einen übergeorneten Arbiter. Denn dein "Master-Slave-Konzept" geht offenbar davon aus, dass auch die Slaves von sich aus was senden könnten. Das ist dann eben kein Master-Slave mehr, sondern ein Multimaster...
S. R. schrieb: > und ich wollte > ungern eine massive Crossbar in die Mitte klatschen, die ich jedesmal > aufwändig anpassen muss, wenn ich einen neuen Block einklebe. Vielleicht ist das dein Problem, man kann eine crossbar so schreiben das eine erweiterung mit ein paar wenigen Zeilen in einem Package erweitert ist. bspw. mit generate über einen index aller slaves.
Warum nicht ein bestehendes Bussystem nehmen? Wishbone, AXI, Avalon, AHB, APB, ... da gibt es einige. OR-Reduce Busse sind auch nett. Spätestens bei mehreren Mastern greife ich auf schon bestehende Spezifikationen. Das tolle daran ist auch die Wiederverwendbarkeit.
C. A. Rotwang schrieb: > und mit > bspw or_reduce immer den gesamten vector verdödeln. > http://electronics.stackexchange.com/questions/85922/vhdl-or-ing-bits-of-a-vector-together ich hab' mal wieder nicht verstanden, warum das or_reduce im Link so aussieht, wie's aussieht. Erscheint mir viel zu kompliziert, letztendlich ist das or_reduce() ja nichts anderes als ein Vergleich mit (others => '0):
1 | function or_reduce(V : std_logic_vector) return std_ulogic is |
2 | constant cmp : std_logic_vector(V'range) := (others => '0'); |
3 | begin
|
4 | if cmp = V then |
5 | return '0'; |
6 | else
|
7 | return '1'; |
8 | end if; |
9 | end function or_reduce; |
10 | |
11 | ?
|
Ich stand vor dem gleichen Problem und kam zu dem Ergebnis: Tristate gibt es nicht und inout ist unbrauchbar. Es gibt einen Busmaster und der hat die Kontrolle über den Bus. Diese Busmaster gibt das Handshaking aus mit welchen Slave komuniziert wird. Meine Definition habe ich sogar niedergeschrieben und komme damit sehr gut klar. http://www.dossmatik.de/mais/bus_spec.pdf Alle Signalnamen fangen mit B für Bus an, erhöht die Lesbarkeit des Codes. Die Daten vom Master zum Slave heißen BWDATA. (W steht für write) Jetzt die eigentliche Antwort zu deiner Urfrage: Die Daten vom Slave zum Master wird über eine eigene Datenleitung vom Slave zum Master übertragen. Bei mir heißt diese Leitung "BRDATA". R für read. Alle Daten habe ich je nach Datenrichtung in je ein Record zusammengefasst und binde diese mit einem package in meinem Code ein. Das erspart Schreibarbeit und macht die Sache sehr übersichtlich. Nur BCLK habe ich nicht mit in das Record gepackt. Da habe ich die Erfahrung gemacht der Fitter hat kommt zu besseren Ergebnissen. Problem tauchen erst wirder bei mehreren Busmastern aus. Das habe ich noch nicht gebraucht.
Markus F. schrieb: > Erscheint mir viel zu kompliziert, > letztendlich ist das or_reduce() ja nichts anderes als ein Vergleich mit > (others => '0): Weil ein vergleich type boolean liefert, aber ein Or-Gatter Typ Standard_ulogic o.ä liefert resp. liefern muß?!. Damit auch solche Fälle wie mehrere Gatterausgänge kurzgeschlossen abgefangen werden können. In echt, gibt es halt mehr Zustände als true und false, da gibt es noch die Untermenge "verboten".
Moin, guck mal in http://www.section5.ch/downloads/masocist-opensource-v0.10beta_eval.tgz, gen/soc_mmr_perio.vhdl. Da ist das mit einem Wishbone-Interface implementiert, allerdings wird der ganze ACK-Krempel für die einfache Ansteuerung der Peripherie nicht benötigt. In dieser Konfig ist allerdings Verstopfung bei viel Peripherie vorprogrammiert (da keine Delays). Wenn nicht unbedingt nötig, würde ich den Wishbone-Overhead nicht bis zu den untersten Core-Instanzen durchziehen, jeder überflüssige MUX macht Aua. Dein sekundärer Master klingt nach einem DMA-Controller. Beim DP-RAM würde ich den einfach durch die Hintertür mit einem zweiten dedizierten Bus aufsetzen, komplett an der top level Arbitrierung vorbei. So machen es einige DSP-Architekturen.
Markus F. schrieb: > War das deine Frage? Ja. C. A. Rotwang schrieb: > Alternativ kann man alle von den Slaves weggehneden signale ver-ODER-n, > das ist einfacher als der beschriebene Muxer für die ACK. Das ist mir beim Schreiben auch aufgefallen. Klingt für die Datenleitungen (N x 32 Bit) aber auch aufwändig... Lothar M. schrieb: > Über einen übergeorneten Arbiter. Denn dein "Master-Slave-Konzept" geht > offenbar davon aus, dass auch die Slaves von sich aus was senden > könnten. Das ist dann eben kein Master-Slave mehr, sondern ein > Multimaster... Nein, der Master treibt den Request (R/W), auf den der Slave antwortet. Slaves können selbst keine Requests auslösen. Es gibt allerdings zwei Master, s.u. Klakx schrieb: > Warum nicht ein bestehendes Bussystem nehmen? Das hatte sich so ergeben. Ursprünglich bestand das Konzept aus 3 Blöcken (2 Master und ein DP-RAM), die einfach miteinander verklebt wurden. Das fasert gerade auf, weil da zusätzliche Peripherie rein soll. Strubi schrieb: > Dein sekundärer Master klingt nach einem DMA-Controller. Beim DP-RAM > würde ich den einfach durch die Hintertür mit einem zweiten dedizierten > Bus aufsetzen, komplett an der top level Arbitrierung vorbei. So machen > es einige DSP-Architekturen. Ist ein NoC-Interface. Ja, für den BRAM sind zwei Master kein Problem (Adresskonflikte kann ich vermeiden), allerdings sollen beide Master auch auf die gleiche Peripherie zugreifen können. Ich wollte vermeiden, an mehreren Stellen die RAM-Größe festlegen zu müssen. Das wird einfach etwas haarig für meine Anfängerkenntnisse. René D. schrieb: > Ich stand vor dem gleichen Problem und kam zu dem Ergebnis: > http://www.dossmatik.de/mais/bus_spec.pdf Hmm. Im Prinzip so ähnlich wie mein Entwurf, nur etwas komplexer und dein Master dekodiert die Adressräume zentral. Wie schließt du die SPB_out-Records der einzelnen Blöcke zusammen? Über einen Muxer mit den Select-Signalen? Das scheint aber der sinnvollste Weg für mich zu sein.
S. R. schrieb: > Ja, für den BRAM sind zwei Master kein Problem (Adresskonflikte kann ich > vermeiden), allerdings sollen beide Master auch auf die gleiche > Peripherie zugreifen können. Ich wollte vermeiden, an mehreren Stellen > die RAM-Größe festlegen zu müssen. Wenn deine beiden Master CPUs sind, die 'stall'en können, würde ich konkurrierende Zugriffe auf die Peripherie nach Möglichkeit vermeiden. Das macht auch bei gut getesteten Architekturen teils echte Probleme. Lieber nen einigermassen asynchronen Transaction-Layer einbauen. Da gibt es übrigens einige nette Konzepte aus den 90ern, u.a. die MUSIC-Architektur von der ETH. Bei so komplexen Sachen empfiehlt sich allenfalls der IP-XACT Ansatz, die Komponenten zu generieren, aber da müsstest du ev. etwas Vorlaufzeit einplanen um die Tools in den Griff zu kriegen. Dafür sparst du viel Konfigurations-Gefuddel und VHDL-bedingten Overhead.
Strubi schrieb: > Wenn deine beiden Master CPUs sind, die 'stall'en können, würde ich > konkurrierende Zugriffe auf die Peripherie nach Möglichkeit vermeiden. Einer der Master ist eine CPU, der andere Master ist ein NoC-Interface. Fürs Debugging ist es äußerst nützlich, wenn ich die Peripherie auch von außen konfigurieren (oder zumindest reingucken) kann. Die CPU darf währenddessen gerne stallen. Ich werde wohl einen Arbitrator für Peripheriezugriffe bauen, der die Peripherieadressen zentral dekodiert und verteilt, und zwei Direktzugriffe in den RAM legen. Danke für die Ansätze.
Lothar M. schrieb: > Seit der Jahrtausendwende nicht mehr. Alle Busse müssen zu Multiplexern > aufgelöst werden. Gefühlt ist das schon 50 Jahre nicht mehr der Fall :-)
://www.dossmatik.de/mais/bus_spec.pdf > > Hmm. Im Prinzip so ähnlich wie mein Entwurf, nur etwas komplexer und > dein Master dekodiert die Adressräume zentral. Wie schließt du die > SPB_out-Records der einzelnen Blöcke zusammen? Über einen Muxer mit den > Select-Signalen? > Ja mit einem Muxer erschlagen, der sehr Pflegeleicht ist.
1 | ---BUS multiplexer
|
2 | BBUS_out <= slave(0) when BSEL(0)='1' else --DRAM |
3 | slave(1) when BSEL(2)='1' else --UART |
4 | slave(2); --Bus Dummy |
Für die Selektleitungen nutze ich die Adressbereiche und habe hier ein hex zu N Dekoder hinterlegt. Welche select Leitung der Slave nutzt gebe ich der Componente als generic mit.
1 | --SLAVE 1 -- UART
|
2 | HB_UART : SPB_UART generic map( |
3 | sim => sim, |
4 | BSEL => 2, |
5 | baudrate => 115200, |
6 | clk_freq => board_clk_frq) |
7 | |
8 | port map( |
9 | BCLK => board_clk, |
10 | BRESET => BRESET, |
11 | BBUS_in => BBUS_in, |
12 | BBUS_out => slave(1), |
13 | |
14 | uart_irq => IRQ_UART, |
15 | rx => rx, |
16 | tx => tx); |
Der Code ist aus der Mais CPU. http://www.dossmatik.de/mais-cpu.html
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.