Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende ÜberarbeitungNächste ÜberarbeitungBeide Seiten der Revision | ||
fpga:beispielpciegpio:start [2013-07-15 15:09] – tinner | fpga:beispielpciegpio:start [2013-07-15 16:30] – tinner | ||
---|---|---|---|
Zeile 8: | Zeile 8: | ||
===== GPIO Block ===== | ===== GPIO Block ===== | ||
+ | \\ | ||
Als erstes soll genauer auf den GPIO Block eingegangen werden. | Als erstes soll genauer auf den GPIO Block eingegangen werden. | ||
Der Beispielcode kann {{: | Der Beispielcode kann {{: | ||
Zeile 19: | Zeile 20: | ||
oslv_avs_read_data : OUT STD_LOGIC_VECTOR(avs_data_width_gpio_if-1 DOWNTO 0); | oslv_avs_read_data : OUT STD_LOGIC_VECTOR(avs_data_width_gpio_if-1 DOWNTO 0); | ||
</ | </ | ||
- | Dabei bestimmt die Konstante avs_adress_width_gpio_if die Anzahl Register des Blocks die angesprochen werden können. In diesem Beispiel ist der Wert 1 also können 2 Register angesprochen werden. Wird die Adressweite auf 2 gesetzt könne 4 Register angesprochen werden etc. | + | Dabei bestimmt die Konstante avs_adress_width_gpio_if die Anzahl Register des Blocks die angesprochen werden können. In diesem Beispiel ist der Wert 1 also können 2 Register angesprochen werden. Wird die Adressweite auf 2 gesetzt könne 4 Register angesprochen werden etc.\\ |
+ | Die Konstante avs_data_width_gpio_if bestimmt die Breite der Register. Hier 64 Bit obwohl davon nur 16 verwendet werden. Dies erleichterst später den C-Code im Linux Treiber.\\ | ||
+ | Die Daten vom Bus werden im folgend Codeabschnitt geschrieben: | ||
+ | < | ||
+ | IF isl_avs_write = ' | ||
+ | CASE islv_avs_adress IS | ||
+ | WHEN gpio_val_reg_address => | ||
+ | gpio_val_reg <= islv_avs_write_data(nr_of_gpios-1 DOWNTO 0); | ||
+ | WHEN gpio_dir_reg_address => | ||
+ | gpio_dir_reg <= islv_avs_write_data(nr_of_gpios-1 DOWNTO 0); | ||
+ | WHEN OTHERS => null; | ||
+ | END CASE; | ||
+ | END IF; | ||
+ | </ | ||
+ | Wenn also das write Signal high ist können je nach Wert des Adress Signals die Daten vom write_data Signal in einem anderen Register gespeichert werden.\\ Der Read-Teil funktioniert Analog dazu. Mit den gegeben Definitionen werden folgende Register bereitgestellt: | ||
+ | \\ | ||
+ | ^ Offset: ^ Grösse(Bit): | ||
+ | | 0 | 16 |dir_reg | RW | 0x0000 | 1:GPIO Input, 0:GPIO Output| | ||
+ | | 1 | 16 |value_reg| RW | 0x0000 |1:GPIO High, 0:GPIO Low| | ||
+ | |||
+ | |||
+ | Danach müssen nur noch je nach Register Werten die Ausgänge gesetzt werden was mit folgendem Code gemacht werden kann:\\ | ||
+ | < | ||
+ | FOR i IN 0 TO nr_of_gpios-1 LOOP | ||
+ | IF gpio_dir_reg(i) = ' | ||
+ | oslv_gpios(i) <= gpio_val_reg(i); | ||
+ | ELSE --input | ||
+ | oslv_gpios(i) <= ' | ||
+ | gpio_val_reg(i) <= oslv_gpios(i); | ||
+ | END IF; | ||
+ | END LOOP; | ||
+ | </ | ||
+ | |||
+ | ===== GPIO Block in Qsys einbinden ===== | ||
+ | \\ | ||
+ | Damit der erstellte Block in [[ fpga: | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | Im sich öffnenden Fenster wählt man im Register //HDL Files// alle für den Block benötigten Files aus.\\ | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | Im Register //Signals// werden die vorhandenen Signal ihrer Funktion und ihrem Interface zugewiesen. Im hier beschriebenen Beispiele wird für das Signal isl_clk bei Interface //New Clock Input..//, für isl_reset_n //New Reset Input..// und für das Signal oslv_gpios //New Conduit..// ausgewählt. Für die übrigen Signale wählt man das bereits erstellt avalon_slave_0 aus. Danach muss noch die Spalte //Signal Type// ausgefüllt werden. Das ganze sollte dann so aussehen wie in der folgenden Abbildung: | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | Danach können mit einem klick auf //Remove Interfaces With No Signals// alle unnötigen Interfaces entfernt werden. Danach müssen beim avalon_slave_0 Interface die Clock und die Reset Quelle eingestellt werden. Ebenfalls bei der reset_sink muss ein Clock eingestellt werden. Damit sollten dann alle Fehlermeldungen unten im Fenster verschwunden sein. \\ | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | Im Register //Library Info// können noch einige Paramter eingestellt werden wie zum Beispiel der Name der Komponente.\\ | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | Mit Finish wird dann automatisch ein TCL Skript erstellt das im gleichen Ordner wie das Top File der Komponente abgelegt wird. Damit Qsys die erstellte Komponente beim erneuten Aufstarten wieder findet muss der Pfad unter // | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | ===== PCIe Block in Qsys erstellen ===== | ||
+ | \\ | ||
+ | Wird in Qsys ein Doppelklick auf den \\IP_Compiler for PCI Express\\ ausgeführt wird eine Komponente zum System hinzugefügt. Im erscheinenden Fenster wählt man folgende Einstellungen: | ||
+ | \\ | ||
+ | {{: | ||
+ | ===== System zusammenfügen ===== | ||
+ | \\ | ||
+ | Mit einem Doppelklick auf die selbst geschriebenen Komponenten kann auch sie eingefügt werden. Alle Anderen Komponenten ausser der PCIe und den nun erschienen GPIO Komponenten können gelöscht werden. Danach müssen noch Verbindungen gezogen und bestimmt werden welche Singale Exportiert werden. Dies geschieht mit einem Klick auf \\Click to Export\\. Das fertige System sollte dann folgendermassen aussehen: \\ | ||
+ | \\ | ||
+ | {{: | ||
+ | \\ | ||
+ | Wenn man nun unter // | ||
+ | |||
+ | ===== Einfügen des System in das Top Design ===== |