Verilog-Router-Design und beste Möglichkeit, Pakete mit variabler Größe in Verilog zu verarbeiten?

Ich habe eine Frage zum synthetisierbaren Verilog/logischen Design. Meine Frage ist logischer als Syntax.

Ich möchte eine Art Router implementieren, der drei Ein-/Ausgangsports von Vollduplex-UART RS232 hat, die Pakete aneinander senden.

Hauptpunkte des Designs:

  • Die Pakete haben eine variable Größe und enthalten die folgenden Felder: Quelle (1 Byte), Ziel (1 Byte), Nutzdatenlänge (2 Bytes), Nutzdaten.
  • Die Nutzdatenlänge ist zwischen 4 und 2000 Byte variabel.
  • Ich möchte eine Art Routing-Tabelle haben, "welches Ziel an welchen der UART-Ports weitergeleitet wird", und eine Art Firewall (der richtige Name ist nicht sicher), so etwas wie "welche Quellen Pakete an welche UART-Ports senden dürfen".
  • Loopback ist erlaubt (das Paket, das über denselben Port empfangen und gesendet wird)
  • Broadcasting ist erlaubt (möglicherweise Zieladresse, die an mehr als einen UART-Port weitergeleitet wird)
  • Das Modul muss generisch sein, damit ich es auf mehr als 4 Ports erweitern kann.

Ich denke, der schwierigste Teil ist, mit Paketen variabler Größe umzugehen. Wenn die Pakete eine feste Größe hätten und nicht zu groß wären, hätte ich für jeden UART-Port ein Eingangs-FIFO und ein Ausgangs-FIFO gehabt:

reg [Paketgröße-1:0] fifo[Anzahl_der_Pakete]

Jeder Eingangs-FIFO hätte in jedem FIFO [I] ein ganzes Paket gespeichert, das von der uart empfangen wurde, und ein Modul, das ganze Pakete von jedem Eingangs-FIFO liest, das Ziel jedes Pakets auf Quelle prüft und das Paket verwendet, um das Paket zu leiten Gewünschter Ausgangs-FIFO und von dort ein UART-Sender, der ein Paket nimmt und es Byte für Byte sendet. Das Problem ist, dass ein Paket wirklich sehr groß sein kann, also möchte ich kein Fifo mit 2000 Bytes in jeder Zelle halten ...

Damit stellt sich auch die Frage, wie die Pakete zwischen den internen Modulen übertragen werden? Wie gesagt, ein Paket kann sehr groß werden.

Mir ist klar, dass mein Beitrag viele Fragen enthält, aber ich würde mich über jede Hilfe freuen. Wenn es Referenzdesigns oder ähnliches gibt, die mir helfen können, werde ich es gerne überprüfen.

Danke für die Hilfe.

Ist ein Szenario möglich, in dem mehrere Eingangsports gleichzeitig ein massives 2k-Paket empfangen, das jeweils für denselben Ausgangsport bestimmt ist?

Antworten (3)

Angenommen, mehrere Eingangsports können gleichzeitig Daten empfangen, können Sie nicht garantieren, dass Sie in Echtzeit von einem Port zum anderen übertragen können. Weil zwei Ports gleichzeitig versuchen könnten, zum selben Ziel zu routen.

Daher benötigen Sie für jeden Eingangsport einen Paketpuffer.

Sie wollen sicherlich keinen 2000 Byte x N FIFO, weil das viel Speicher verschwenden würde.

Die Folge der Speicherverschwendung ist natürlich, dass Sie nicht so viele Pakete puffern können. In Situationen mit viel Datenverkehr kann dies zu verworfenen Paketen führen.

Anstatt einen FIFO zu verwenden, bei dem jedes Element ein Paket ist, verwenden Sie einen kreisförmigen Byte-Puffer. Auf diese Weise verschwenden Sie keinen Platz, wenn Sie kleinere Pakete aufbewahren.

Um den Ringpuffer zu implementieren, behalten Sie einfach ein paar Indizes bei.

Lassen Sie den Index P1 auf den Beginn des ersten Pakets im Puffer zeigen. Lassen Sie den Index P2 gerade über das Ende des letzten vollständigen Pakets im Puffer hinaus zeigen. Lassen Sie den Index P3 auf das letzte empfangene Byte zeigen.

Wenn die Pakete eintreffen, wird ihr Header in Echtzeit verarbeitet. Legen Sie sie nur in den Puffer, wenn Sie Platz haben (was aus P1, P2 und Ihrer Puffergröße berechnet werden kann).

Wenn Sie in das Paket passen, legen Sie seine Bytes in den Puffer, sobald sie eintreffen. P3 wird für jedes Byte inkrementiert.

Wenn ein Paket nur teilweise empfangen wird und ein Timeout auftritt, können Sie P3 auf P2 zurücksetzen.

Einfach ausgedrückt: "Worst-Case-Analyse", und in diesem Fall vermute ich, dass Sie wenig bis gar keine Leistungsanforderungen haben und nur Daten empfangen und übertragen möchten.

2kB ist nicht viel Speicher, aber die Präambel enthält anscheinend alle Informationen, die Sie benötigen, um "Echtzeit" zu übertragen. Sobald Sie wissen, wohin es geht (Ziel), und vorausgesetzt, Sie brauchen die Daten nicht zu interpretieren oder zu verarbeiten, müssen Sie nach dem Empfang der Präambel und dem Einrichten Ihres Senders nur noch ein Byte/Wort (was auch immer) sammeln Ihre Datengröße ist für die Nutzlast) und übertragen Sie sie immer wieder, bis Sie die Byte-Anzahl erreicht haben. Sie sollten dies mit einer "Ping-Pong-FIFO"-Architektur tun können ... wahrscheinlich mit einer Latenz nahe der Präambellänge (dh einer Pipeline-Verzögerung).

Der Mindestspeicher (Speicher und / oder Register) für das, was ich beschrieben habe, ist ~ (Anzahl der Bytes in der Präambel) + (2 * Anzahl der Bits für Daten)

Nun, Sie müssen FIFOs verwenden, aber sie speichern Bytes anstelle von Paketen, und Sie verwenden Zustandsmaschinen, um Übertragungen zu steuern, sodass für jedes Paket die richtige Anzahl von Bytes übertragen wird. Es ist auch möglich, den Header von den Nutzlasten zu trennen und sie in separaten FIFOs zu speichern, was je nach Anwendung nützlich sein kann oder nicht.

Aber ist das wirklich eine gute Anwendung für ein FPGA? UARTs sind normalerweise ziemlich langsam, und Sie können Mikrocontroller mit vielen Hardware-UARTs erhalten (z. B. Atmel xmega).