
Im
ersten Artikel des Zyklus wurde daher gesagt, dass es am besten ist, ein Prozessorsystem zur Steuerung unserer Geräte zu verwenden, die mithilfe von FPGAs für den Redd-Komplex implementiert wurden. Anschließend wurde im ersten und zweiten Artikel gezeigt, wie dieses System hergestellt wird. Nun, es ist geschafft, wir können sogar einige vorgefertigte Kernel aus der Liste auswählen, um sie in die Liste aufzunehmen, aber das ultimative Ziel ist es, unsere eigenen benutzerdefinierten Kernel zu verwalten. Es ist an der Zeit zu überlegen, wie ein beliebiger Kernel in das Prozessorsystem aufgenommen werden kann.
Alle Artikel des Zyklus:
Entwicklung der einfachsten „Firmware“ für in Redd installierte FPGAs und Debugging am Beispiel des SpeichertestsEntwicklung der einfachsten „Firmware“ für in Redd installierte FPGAs. Teil 2. ProgrammcodeUm die heutige Theorie zu verstehen, sollten Sie das Dokument mit den
Avalon-Schnittstellenspezifikationen finden und herunterladen, da der
Avalon- Bus der Basisbus für das NIOS II-System ist. Ich werde mich bei der Überarbeitung des Dokuments vom 26. September 2018 auf Abschnitte, Tabellen und Abbildungen beziehen.
Wir öffnen den Abschnitt 3, der Memory Mapped Interfaces gewidmet ist, oder besser - 3.2. In Tabelle 9 sind die Bussignale aufgeführt. Bitte beachten Sie, dass alle diese Signale optional sind. Ich habe kein einziges Signal mit "Ja" in der Spalte "Erforderlich" gefunden. Möglicherweise leiten wir dieses oder jenes Signal nicht an unser Gerät weiter. Daher ist der Bus im einfachsten Fall äußerst einfach zu implementieren. Der Anfang der Tabelle sieht folgendermaßen aus:

Wie Sie sehen können, sind alle Signale sehr gut beschrieben (außer dass dies auf Englisch erfolgt). Unten finden Sie die Zeitdiagramme für verschiedene Fälle. Der einfachste Fall wirft keine Fragen auf. Ich werde jetzt das Zeitdiagramm aus dem Dokument entnehmen und einige der Zeilen mit einer durchscheinenden Füllung abdecken (sie sind alle optional, wir haben das Recht, alle Überlegungen auszuschließen).

Beängstigend Aber alles ist einfach: Wir erhalten die Adresse und den Lesestrob, wir müssen die Daten auf dem Readdata-Bus einstellen. Und umgekehrt: Wir erhalten die Adresse, die Daten auf dem Writedata-Bus und den Write Strobe, und wir müssen die Daten abfangen. Es ist überhaupt nicht beängstigend, ein typischer Synchronbus.
Verdeckte byteenable Zeilen
werden für den Fall benötigt, dass der Speicherzugriff keine 32-Bit-Wörter umfasst. Dies ist äußerst wichtig, wenn wir universelle Kernel entwerfen. Aber wenn wir einen eintägigen Kern entwerfen, schreiben wir einfach in das Dokument über diesen Kern (ich bin ein Gegner der Marke in meinem Kopf, aber jemand kann es darauf beschränken), dass wir 32-Bit-Wörter verwenden müssen und das war's. Nun, und das
Antwortsignal ist sehr speziell und interessiert uns im Prinzip nicht.
Manchmal ist es wichtig, dass der Betrieb des Busses um mehrere Taktzyklen verzögert werden kann, wenn das Gerät nicht bereit ist. In diesem Fall sollte das
WaitRequest- Signal hinzugefügt werden. Das Zeitdiagramm ändert sich wie folgt:

Während
WaitRequest gespannt ist, weiß der Assistent, dass unser Gerät ausgelastet ist. Seien Sie vorsichtig, wenn dieses Signal nicht zurückgesetzt wird. Das gesamte System friert bei der Handhabung ein, sodass es nur durch einen Neustart des FPGA zurückgesetzt werden kann. JTAG hängt mit dem System. Das letzte Mal, dass ich dieses Phänomen beobachtete, war in der Vorbereitung dieses Artikels, daher sind die Erinnerungen immer noch lebendig.
Weiter im Unternehmensdokument werden produktivere Fälle von Daten-Pipelining und Batch-Transaktionen betrachtet, aber die Aufgabe des Artikels besteht nicht darin, alle möglichen Optionen zu berücksichtigen, sondern dem Leser die Arbeitsweise zu zeigen und zu betonen, dass dies alles überhaupt nicht beängstigend ist. Deshalb beschränken wir uns auf diese beiden einfachen Optionen.
Lassen Sie uns ein einfaches Gerät entwerfen, das in regelmäßigen Abständen im Bus nicht mehr verfügbar ist. Das erste, was mir in den Sinn kommt, ist die serielle Schnittstelle. Während der Übertragung wird das System warten. Und im Leben rate ich dringend davon ab: Der Prozessor stoppt bis zum Ende einer geschäftigen Transaktion, aber dies ist ein idealer Fall für einen Artikel, da der Implementierungscode verständlich und nicht sehr umständlich ist. Im Allgemeinen werden wir einen seriellen Sender herstellen, der Daten und Chipauswahlsignale an zwei Geräte senden kann.

Beginnen wir mit der einfachsten Reifenoption. Machen wir einen parallelen Ausgangsport, der die Signale der Wahl der Kristalle bildet.

Dazu werde ich das im vorherigen Artikel erhaltene Projekt übernehmen, aber um Verwirrung zu vermeiden, werde ich es in das Verzeichnis AVALON_DEMO stellen. Ich werde die Namen anderer Dateien nicht ändern. Erstellen
Sie in diesem Verzeichnis das Verzeichnis
my_cores . Der Verzeichnisname kann beliebig sein. Wir werden unsere Kerne darin aufbewahren. Es stimmt, heute wird es einer sein. Erstellen Sie eine
CrazySerial.sv- Datei mit den folgenden Inhalten:
module CrazySerial ( input clk, input reset, input [1:0] address, input write, input [31:0] writedata, output reg [1:0] cs ); always @(posedge clk, posedge reset) begin if (reset == 1) begin cs <= 0; end else begin if (write) case (address) 2'h00: cs <= writedata [1:0]; default:; endcase end end endmodule
Lass es uns richtig machen. Zunächst Schnittstellenleitungen.
clk und
reset sind die Takt- und Rücksetzleitungen. Die Namen der
Adressen ,
Schreib- und
Schreibdatenzeilen werden aus der Tabelle mit der Liste der Signale des Dokuments
Memory Mapped Interfaces entnommen.


Tatsächlich könnte ich beliebige Namen nennen. Das Verknüpfen logischer mit physischen Zeilen erfolgt später. Wenn Sie jedoch die Namen wie in der Tabelle angeben, werden sie von der Entwicklungsumgebung selbst verbunden. Daher ist es besser, die Namen aus der Tabelle zu übernehmen.
Nun,
cs sind die Kristallauswahllinien, die aus dem Chip kommen.
Die Implementierung selbst ist trivial. Beim Zurücksetzen werden die Ausgänge auf Null gesetzt. Und so prüfen wir bei jeder Messung, ob ein
Schreibsignal vorliegt. Wenn eine Adresse gleich Null ist, klicken Sie auf die Daten. Natürlich wäre es möglich, hier einen Decoder hinzuzufügen, der die Auswahl von zwei Geräten gleichzeitig verhindert, aber was im Leben gut ist, wird den Artikel überlasten. Der Artikel enthält nur die notwendigsten Schritte, es wird jedoch darauf hingewiesen, dass im Leben alles komplizierter gemacht werden kann.
Großartig. Wir sind bereit, diesen Code in das Prozessorsystem einzuführen. Wir gehen zu
Platform Designer und wählen als Eingabedatei das System aus, das wir in früheren Experimenten erstellt haben:

Wir machen auf das Element
Neue Komponente in der oberen linken Ecke aufmerksam:

Klicken Sie auf dieses Element, um Ihre Komponente hinzuzufügen. Füllen Sie im folgenden Dialogfeld die Felder aus. Geben Sie für den Artikel nur den Komponentennamen ein:

Gehen Sie nun zur Registerkarte
Dateien und klicken
Sie auf Datei hinzufügen :

Fügen Sie die zuvor erstellte Datei hinzu, wählen Sie sie in der Liste aus und klicken Sie auf
Synthesedatei analysieren :

Es gibt keine Fehler beim Parsen von
SystemVerilog , aber es gibt mehrere konzeptionelle Fehler. Sie werden durch die Tatsache verursacht, dass einige Leitungen von der Entwicklungsumgebung falsch verbunden wurden. Wir gehen zur Registerkarte
Signale & Schnittstellen und achten hier:

Die
cs- Zeilen wurden der Schnittstelle
avalon_slave0 , dem
Readdata- Signal, falsch zugewiesen. Aber dann wurden alle anderen Zeilen korrekt erkannt, da wir ihnen Namen aus der Dokumententabelle gegeben haben. Aber was tun mit Problemlinien? Sie sollten einer Schnittstelle wie einem
Conduit zugewiesen werden. Klicken Sie dazu auf den Punkt „Schnittstelle hinzufügen“.

Wählen Sie im Dropdown-Menü die Option
Leitung :

Wir bekommen eine neue Schnittstelle:

Falls gewünscht, kann es umbenannt werden. Dies wird sicherlich notwendig sein, wenn wir mehrere externe Schnittstellen erstellen möchten. Als Teil des Artikels
belassen wir den Namen
Conduit_end . Jetzt haken wir die
cs- Linie mit der Maus ein und ziehen sie in diese Oberfläche. Wir müssen es schaffen, ein Signal unter die Zeile
Conduit_end zu werfen, dann dürfen wir dies tun. An anderen Stellen wird der Cursor als durchgestrichener Kreis angezeigt. Am Ende sollten wir Folgendes haben:

Ersetzen Sie den Signaltyp durch
Lesedaten ,
z . B. durch
Chipselect . Endgültiges Bild:

Aber die Fehler blieben. Dem
Avalon-Bus wird kein Rücksetzsignal zugewiesen. Wir wählen
avalon_slave_0 aus der Liste aus und sehen uns seine Eigenschaften an.

Ersetzen Sie
keine durch
Zurücksetzen . Gleichzeitig werden wir andere Schnittstelleneigenschaften untersuchen.

Es ist ersichtlich, dass die Adressierung in Worten erfolgt. Nun, eine Reihe anderer Dinge aus der Dokumentation sind hier konfiguriert. Welche Zeitdiagramme in diesem Fall erhalten werden, wird ganz unten in den Eigenschaften gezeichnet:

Eigentlich gibt es keine Fehler mehr. Sie können auf
Fertig stellen klicken. Unser erstelltes Modul wurde im Gerätebaum angezeigt:

Fügen Sie es dem Prozessorsystem hinzu, verbinden Sie Taktsignale und setzen Sie es zurück. Wir verbinden den Datenbus mit dem
Data Master- Prozessor. Doppelklicken Sie auf
Conduit_end und geben Sie dem externen Signal einen Namen, z. B.
Zeilen . Es stellt sich irgendwie so heraus:

Es ist wichtig, nicht zu vergessen, dass wir, da wir dem System einen Block hinzugefügt haben, sicherstellen müssen, dass er mit niemandem im Adressraum in Konflikt steht. In diesem speziellen Fall gibt es keine Konflikte in der Abbildung, aber ich werde trotzdem den Menüpunkt
System-> Basisadressen zuweisen auswählen.
Das ist alles. Der Block wird erstellt, konfiguriert und dem System hinzugefügt. Klicken Sie auf die Schaltfläche
HDL generieren und dann auf
Fertig stellen .
Wir machen einen groben Entwurf des Projekts, danach gehen wir zum
Pin-Planer und weisen die Beine zu. Es stellte sich so heraus:

Dies entspricht den Kontakten B22 und C22 des Schnittstellensteckers.
Wir machen die Endmontage, laden das Prozessorsystem in das FPGA. Jetzt müssen wir den Programmcode verfeinern. Starten Sie Eclipse.
Ich möchte Sie daran erinnern, dass ich derzeit mit einem Projekt arbeite, das sich in einem anderen Verzeichnis befindet als meine letzte Arbeit mit Redd. Um nicht verwirrt zu werden, werde ich alte Projekte aus dem Baum löschen (aber nur aus dem Baum, ohne die Dateien selbst zu löschen).

Als nächstes klicke ich mit der rechten Maustaste auf einen leeren Baum und wähle
Importieren aus dem Menü:

Weiter -
Allgemein-> Vorhandenes Projekt in Arbeitsbereich :

Und wählen Sie einfach das Verzeichnis aus, in dem die Projektdateien gespeichert sind:


Beide Projekte, die aus früheren Experimenten stammen, werden mit der Entwicklungsumgebung verbunden.

Ich werde den nächsten Punkt in einem Rahmen hervorheben:
Wählen Sie jedes Mal nach dem Ändern der Hardwarekonfiguration den Menüpunkt Nios II -> BSP generieren für das BSP-Projekt erneut aus.

Nach diesem Vorgang wurde tatsächlich ein neuer Block in der
Datei \ AVALON_DEMO \ software \ SDRAMtest_bsp \ system.h angezeigt :
/* * CrazySerial_0 configuration * */ #define ALT_MODULE_CLASS_CrazySerial_0 CrazySerial #define CRAZYSERIAL_0_BASE 0x4011020 #define CRAZYSERIAL_0_IRQ -1 #define CRAZYSERIAL_0_IRQ_INTERRUPT_CONTROLLER_ID -1 #define CRAZYSERIAL_0_NAME "/dev/CrazySerial_0" #define CRAZYSERIAL_0_SPAN 16 #define CRAZYSERIAL_0_TYPE "CrazySerial"
Zunächst interessiert uns die Konstante
CRAZYSERIAL_0_BASE .
Fügen Sie der
main () - Funktion den folgenden Code hinzu:
while (true) { IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x00); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x01); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x02); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x03); }
Wir beginnen mit dem Debuggen und betrachten den Inhalt der Zeilen mit einem Oszilloskop. Es muss inkrementeller Binärcode vorhanden sein. Er ist da.

Darüber hinaus ist die Häufigkeit des Zugangs zu den Häfen einfach wunderbar:

Ungefähr 25 MHz sind die Hälfte der Busfrequenz (2 Taktzyklen). Manchmal beträgt die Zugriffszeit nicht 2 Zyklen, sondern länger. Dies ist auf die Ausführung von Verzweigungsoperationen im Programm zurückzuführen. Im Allgemeinen funktioniert der einfachste Zugang zum Bus.
Es ist Zeit, zum Beispiel die Funktionalität der seriellen Schnittstelle hinzuzufügen.
Fügen Sie dazu das auf den Bus bezogene
Waitrequest- Schnittstellensignal und ein Paar serieller Port-Signale hinzu -
sck und
sdo . Insgesamt erhalten wir das folgende Codefragment auf
systemverilog :

Gleicher Text: module CrazySerial ( input clk, input reset, input [1:0] address, input write, input [31:0] writedata, output waitrequest, output reg [1:0] cs, output reg sck, output sdo );
Nach den Regeln der guten Form müssen Sie eine einfache Maschine herstellen, die Daten überträgt. Leider wird die unkomplizierteste Maschine im Artikel sehr schwierig aussehen. Wenn ich jedoch die Funktionalität der Maschine nicht erhöhe (und als Teil des Artikels werde ich dies nicht tun), hat sie nur zwei Zustände: Die Übertragung wird ausgeführt und die Übertragung wird nicht ausgeführt. Daher kann ich den Zustand mit einem einzigen Signal codieren:
reg send = 0;
Während der Übertragung benötige ich einen Bitzähler, einen Taktteiler (ich mache ein absichtlich langsames Gerät) und ein Schieberegister für die übertragenen Daten. Fügen Sie die entsprechenden Register hinzu:
reg [2:0] bit_cnt = 0; reg [3:0] clk_div = 0; reg [7:0] shifter = 0;
Ich werde die Frequenz durch 10 teilen (geleitet vom Prinzip "Warum nicht?"). Dementsprechend werde ich im fünften Schritt SCK spannen und im zehnten - diese Zeile fallen lassen, danach - zum nächsten Datenbit gehen. Erhöhen Sie bei allen anderen Maßnahmen einfach den Teilerzähler. Es ist wichtig, nicht zu vergessen, dass Sie beim vierten Takt auch den Zähler erhöhen müssen und beim neunten - Null. Wenn wir den Übergang zum nächsten Bit weglassen, sieht die angegebene Logik folgendermaßen aus:
if (sending) begin case (clk_div) 4: begin sck <= 1; clk_div <= clk_div + 1; end 9: begin sck <= 0; clk_div <= 0; // < > end default: clk_div <= clk_div + 1; endcase end else
Zum nächsten Stück zu gehen ist einfach. Sie haben das Schieberegister verschoben, und wenn das aktuelle Bit das siebte ist, haben sie aufgehört zu arbeiten, indem sie den Zustand der Maschine geändert haben, andernfalls haben sie den Bitzähler erhöht.
shifter <= {shifter[6:0],1'b0}; if (bit_cnt == 7) begin sending <= 0; end else begin bit_cnt <= bit_cnt + 1; end
Eigentlich ist das alles. Das Ausgangsbit wird immer aus dem hohen Bit des Schieberegisters entnommen:
assign sdo = shifter [7];
Und die wichtigste Zeile für die aktuelle Revision. Das
Warteanforderungssignal wird immer dann auf Eins gespannt, wenn serielle Daten übertragen werden. Das heißt, es ist eine Kopie des Sendesignals, die den Status der Maschine festlegt:
assign waitrequest = sending;
Nun, und wenn wir an Adresse 1 schreiben (ich erinnere mich, hier haben wir die Adressierung in 32-Bit-Wörtern), fangen wir die Daten in das Schieberegister ein, setzen die Zähler auf Null und starten den Übertragungsprozess:
if (write) //... 2'h01: begin bit_cnt <= 0; clk_div <= 0; sending <= 1; shifter <= writedata [7:0]; end default:; endcase end
Jetzt werde ich alle Fragmente als einen einzigen Text beschreiben: module CrazySerial ( input clk, input reset, input [1:0] address, input write, input [31:0] writedata, output waitrequest, output reg [1:0] cs, output reg sck, output sdo ); reg sending = 0; reg [2:0] bit_cnt = 0; reg [3:0] clk_div = 0; reg [7:0] shifter = 0; always @(posedge clk, posedge reset) begin if (reset == 1) begin cs <= 0; sck <= 0; sending <= 0; end else begin if (sending) begin case (clk_div) 4: begin sck <= 1; clk_div <= clk_div + 1; end 9: begin clk_div <= 0; shifter <= {shifter[6:0],1'b0}; sck <= 0; if (bit_cnt == 7) begin sending <= 0; end else begin bit_cnt <= bit_cnt + 1; end end default: clk_div <= clk_div + 1; endcase end else if (write) case (address) 2'h00: cs <= writedata [1:0]; 2'h01: begin bit_cnt <= 0; clk_div <= 0; sending <= 1; shifter <= writedata [7:0]; end default:; endcase end end assign sdo = shifter [7]; assign waitrequest = sending; endmodule
Wir beginnen, neuen Code in das System einzuführen. Eigentlich ist der Pfad der gleiche wie beim Erstellen der Komponente, aber einige der Schritte können bereits weggelassen werden. Jetzt werden wir uns nur noch mit dem Verfeinerungsprozess vertraut machen. Gehen Sie zu
Platform Designer . Wenn wir nur den Verilog-Code ändern würden, wäre es recht einfach, die Operation
HDL generieren für das fertige System auszuführen. Da das Modul jedoch neue Zeilen hat (dh die Schnittstelle hat sich geändert), muss es erneuert werden. Wählen Sie dazu im Baum aus, drücken Sie die rechte Maustaste und wählen Sie
Bearbeiten .

Wir bearbeiten ein bestehendes System. Gehen Sie einfach zur Registerkarte "
Dateien" und klicken Sie auf "
Sinthesis-Dateien analysieren" :

Vorhersehbar sind Fehler aufgetreten. Aber wir wissen bereits, dass die falschen Zeilen schuld sind. Daher gehen wir zur Registerkarte
Signale & Schnittstellen und ziehen
sck und
sdo entlang derselben Linie von der Schnittstelle
avalon_slave_0 zur Schnittstelle
Conduit_end :

Benennen Sie auch die Felder für den
Signaltyp für sie um. Das Ergebnis sollte wie folgt sein:

Eigentlich ist das alles. Klicken Sie auf
Fertig stellen , rufen
Sie HDL-Datei für das Prozessorsystem
generieren auf, entwerfen Sie das Projekt in Quartus und weisen Sie neue Abschnitte zu:

Dies sind die Kontakte A21 und A22 des Schnittstellenanschlusses, wir machen die Endmontage, füllen die "Firmware" im FPGA aus.
Eisen aktualisiert. Nun das Programm. Lass uns zu Eclipse gehen. Woran erinnern wir uns dort zu tun? Vergessen Sie nicht,
BSP generieren zu wählen.
Eigentlich ist das alles. Es bleibt noch, dem Programm Funktionen hinzuzufügen. Lassen Sie uns ein Paar Bytes an die serielle Schnittstelle übertragen, aber wir senden das erste Byte an das Gerät, das durch die Zeile
cs [0] und das zweite Byte -
cs [1] ausgewählt wurde .
IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x01); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE+4,0x12); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x02); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE+4,0x34); IOWR_ALTERA_AVALON_PIO_DATA (CRAZYSERIAL_0_BASE,0x00);
Bitte beachten Sie, dass dort keine Verfügbarkeitsprüfungen stattfinden. Pakete gehen nacheinander. Trotzdem stellte sich auf dem Oszilloskop alles als ziemlich konsequent heraus

Der gelbe Strahl ist
cs [0] , der grüne
Strahl ist
sdo , der violette
Strahl ist
sck und der blaue
Strahl ist
cs [1] . Es ist ersichtlich, dass der 0x12-Code an das erste Gerät ging, 0x34 an das zweite.
Das Lesen erfolgt ähnlich, aber ich kann mir kein schönes Beispiel einfallen lassen, außer dem banalen Lesen des Inhalts des Anschlussfußes. Aber dieses Beispiel ist so entartet, dass es nicht einmal interessant ist, es zu tun. Hier ist jedoch zu beachten, dass beim Lesen dieser Buseinstellung äußerst wichtig sein kann:

Wenn eine
Lesezeile vorhanden ist, wird im Einstellungsdialog ein Lesezeitdiagramm angezeigt. Und es wird den Einfluss dieses Parameters zeigen. Wenn Sie die Beine des Anschlusses lesen, fällt dies immer noch nicht auf, aber wenn Sie aus demselben FIFO oder RAM lesen - vollständig. Der Arbeitsspeicher kann so konfiguriert werden, dass Daten unmittelbar nach der Übermittlung der Adresse ausgegeben werden, oder er kann synchron ausgegeben werden. Im zweiten Fall wird die Latenz hinzugefügt. Immerhin hat der Bus die Adresse eingestellt, den Blitz eingestellt ... Aber es gibt keine Daten zur nächsten Flanke des Taktsignals. Sie werden nach dieser Front angezeigt ... Das heißt, das System hat eine Latenz von einer Latenz. Und es muss nur durch Einstellen dieses Parameters berücksichtigt werden. Kurz gesagt, wenn Sie nicht lesen, was erwartet wurde, prüfen Sie zunächst, ob Sie die Latenz konfigurieren müssen. Das restliche Lesen unterscheidet sich nicht vom Schreiben.
Nun, ich möchte Sie noch einmal daran erinnern, dass es besser ist, die Busbereitschaft für den Langzeitbetrieb nicht zu entfernen, da es sonst durchaus möglich ist, die Systemleistung drastisch zu reduzieren. Das Bereitschaftssignal ist gut, um die Transaktion für ein paar Taktzyklen zu halten, und nicht für bis zu 80 Taktzyklen, wie in meinem Beispiel. Aber erstens wäre jedes andere Beispiel für den Artikel unpraktisch, und zweitens ist dies für eintägige Kernel durchaus akzeptabel. Sie sind sich Ihrer Handlungen voll bewusst und vermeiden Situationen, in denen der Bus blockiert ist. Wenn der Kern die ihm zugewiesene Zeit überlebt, kann eine solche Annahme das Leben in der Zukunft verderben, wenn jeder sie vergisst und alles verlangsamt. Aber es wird später sein.
Trotzdem haben wir gelernt, dass der Prozessorkern unsere Kerne steuert. Mit der adressierbaren Welt ist alles klar, jetzt ist es Zeit, sich mit der Streaming-Welt zu befassen. Aber wir werden dies im nächsten Artikel und möglicherweise sogar in mehreren Artikeln tun.
Fazit
Der Artikel zeigt, wie ein beliebiger Verilog-Kernel zur Steuerung des Nios II-Prozessorsystems angeschlossen werden kann. Die Optionen für die einfachste Verbindung zum Avalon-Bus sowie die Verbindung, in der sich der Bus in einem besetzten Zustand befinden kann, werden angezeigt. Es werden Links zu Literatur gegeben, aus der andere Avalon-Bus-Betriebsmodi im Memory Mapped-Modus zu finden sind.
Das resultierende Projekt kann hier heruntergeladen
werden .