Forum: FPGA, VHDL & Co. 64-Bit breites Datenwort via NIOS II auf Avalon schreiben?


von Largo (Gast)


Lesenswert?

Hallo!

ich möchte ein 64-Bit breites Datenwort vom Nios II auf externe VHDL 
Logik schreiben. Hierzu existiert ein Avalon Slave Modul (über das 
Template von Altera) im NIOS II. Bisher habe ich 32-Bit breite Worte 
genutzt, dies ist aber nicht länger ausreichend. Nun zu meinen Fragen.

1. Ist es möglich direkt auf den/einen Avalon Slave zu schreiben? Ist
1
IOWR32_DIRECT(Avalon Slave Basisadresse, Offset = 0, 32-bit breites Datenwort)
 der korrekte Aufruf hierfür?

2. Wie muss die Gegenseite hierzu aussehen? Reicht dies hier?
1
Externe Ports mit NIOS II Slave Modul und eigenem verbinden
2
Wenn Adresse = (Avalon Slave Basisadresse + Offset) UND Write = 1 dann:
3
Wait-Request = 1
4
switch abhängig vom Byte-Enable, dementsprechend Daten speichern
5
Daten in VHDL Modul = Avalon Write Data
6
Wait-Request = 0
7
Repeat "Wenn Adresse..." und merke dir welche Byte-Enables abgehandelt sind, wenn alle abgehandelt sind springe in nächsten FSM-State und "do foo"

3. Wie schnell muss das Wait-Request kommen? Muss es sofort anliegen 
oder darf/muss es getaktet sein?

4. Ich verstehe nicht wirklich die Syntax bzw. die Wirkungsweise des 
IORD/IOWR Befehls. Hier wird die Datenbreite nciht angegeben, aber die 
Adresse errechnet sich irgendwie anders. Kann mir hier jemand helfen?

5. Gibt es einen anderen Weg der ggfs. sinnvoller/einfacher ist um an 
das 64 Bit Datenwort zu kommen?

Ich komme irgendwie nicht richtig voran :(

von rev (Gast)


Lesenswert?

Da der NIOS II ein 32-bit Prozessor ist, ist es nicht möglich ein 64-bit 
Wort in einem Zyklus zu schreiben. Du musst schon 2 32-Bit Wörter 
hintereinander schreiben. Sowas wie IOWR64_DIRECT gibt es nicht.

von Largo (Gast)


Lesenswert?

Das ist bedauerlich. Mein Schreibvorgang reagiert auf einen eingehenden 
Interrupt. Ist die restliche Abfolge korrekt? Dann könnte ich den 2. 
Teil des Datenwortes einfach über eine weitere Adresse meiner Logik 
übergeben.
Damit entfallen die Fragen 4 und 5.
Gibt es eventuell weitere Tipps bzgl. der verbleibenden Punkte?

Vielen Dank im voraus :)

von rev (Gast)


Lesenswert?

Also:
Zu 1.: Genau so wird ein 32-bit Wort auf den Bus geschrieben. Eigentlich 
is dies nur ein C-Macro. Der Compiler/Assembler macht daraus den 
entsprechenden Store-Befehl.

Zu 2.: Ich verstehe nicht genau was du hier meinst. Um mit dem NIOS auf 
eigene Logik zugreifen zu können, braucht man einen Memory-Mapped 
Avalon-Slave (was du anscheinend auch gemacht hast.) Das Altera-Template 
ist eigentlich ziemlich gut dokumentiert, da kann man nicht viel falsch 
machen.

Zu 4.: Das macht der Compiler eigentlich automatisch anhand der 
Datentypen die gelesen/geschrieben werden, z.B.:
1
uint32* pAddr = 0x40000000;
2
*pAddr = 0x12345678;
schreibt das 32-bit Datenwort "0x12345678" an den Avalon-Slave mit der 
Adresse 0x40000000, Da der Pointer pAddr auf einen 32bit-Datentyp zeigt.

zu 5.: Ich glaube ein Avalon-Slave darf schon mehr als 32-bit Busbreite 
haben, allerdings braucht man dann auch einen entsprechenden 
Avalon-Master (auch hier gibt es ein Altera-Template).

von Largo (Gast)


Lesenswert?

Ich habe den Avalon Slave aus dem QSys Menü hinzugefügt, auf "meiner" 
Seite habe ich selbstgeschriebenen Code verwendet. Hier werde ich mir 
die von dir vorgeschlagenen Templates sowie die Doku nochmal näher 
ansehen. Danke!

von Largo (Gast)


Lesenswert?

Ich habe das ganze nun stark angepasst und vermute das mein Problem in 
der falschen Abfrage der Adresse liegt (manchmal ist es ganz hilfreich 
Warnings zu lesen...) Ich spendiere dem Template 8 Bit für die Adresse, 
der Code hierzu sieht so aus:
1
[Ports etc.]
2
clkd: process (clk, reset)
3
begin
4
  if (reset ='1') then
5
    data_buffer <= (others => '0');
6
    data_valid <= '0';
7
    state <= INIT;
8
  elsif (clk = '1' and clk'event )
9
    state <= state_nxt;
10
    data_buffer <= data_buffer_nxt;
11
    data_valid <= data_valid_nxt;
12
  end if;
13
end process;
14
fsm : process ( avs_s0_write,state,data_buffer,data_valid,avs_s0_writedata)
15
begin
16
  avs_s0_waitrequest  <=  '0';
17
  avs_s0_readdata  <=  "00000000000000000000000000000000";
18
  avs_s0_readdatavalid  <=  '0';
19
  data_buffer_nxt <= data_buffer;
20
  data_valid_nxt <= data_valid;
21
  state_nxt <= state;
22
23
  case state is
24
    when INIT =>
25
    avs_s0_waitrequest  <=  '0';
26
    state_nxt <= IDLE;
27
28
    when IDLE =>
29
      if (avs_s0_write = '1') then
30
        if (avs_s0_address = 0x"01000000") then
31
        avs_s0_waitrequest <= '1';
32
        state_nxt <= READ;
33
        end if;
34
      end if;
35
    when READ =>
36
      avs_s0_waitrequest <= '1';
37
      data_buffer_nxt <= avs_s0_writedata;
38
      state_nxt <= READ_WAIT;
39
    when READ_WAIT =>
40
      avs_s0_waitrequest <= '0';
41
      state_nxt <= IDLE;
42
  end case;
43
end process;

Die Abfrage if (avs_s0_address = 0x01000000).. bereitet mir noch 
Kopfschmerzen. Das Adressmapping von QSys legt diese Adresse fest. Wie 
bereits oben erwähnt, spendiere ich dem Template ja aber nur 8Bit. Der 
Wert 0x01000000 passt nur in 32Bit. Wie kann ich diesen Wert gezielt 
abfragen? Oder reicht es 0x00 abzufragen da nur die unteren 8Bit 
relevant sind in diesem Fall? Ich möchte einfach nur in einem C Programm 
mit
1
IOWR32_DIRECT(0x01000000,0,data)
 Daten an mein externes Modul schicken! Wie kann ich sicherstellen das 
die richtigen Daten von meinem externen Modul übernommen werden? Ich 
steh vollkommen auf dem Schlauch :(

von rev (Gast)


Lesenswert?

Also, ich fasse nochmal zusammen:
Der Slave liegt im Addressbereich 0x0100000X <- nur die letzten 8 bit 
werden dekodiert.

Dann fehlt dir die Abfrage des Chip-Selects. Die Dekodierung der oberen 
Adressbits übernimmt eigentlich die Avalon-Switchmatrix.
Daraus wird ein chip-enable an den slave generiert. Eigentlich sollte 
das durch das avs_s0_write Signal gegeben sein.
Wie prüfst du momentan ob die daten in deinem Modul ankommen, wie 
wwerden sie weiterverarbeitet?

Tipp: Implementier ein Debug-Register, dass du mit dem NIOS wieder 
zurücklesen kannst.
ein Versions-Register, welches bei der Synthese auf einen festen 
reset-wert gesetzt wird udn read-only ist (z.b. mit dem Wert 
0x12345678), ist auch immer hilfreich, dann siehst du ob das auslesen 
funktioniert

von Largo (Gast)


Lesenswert?

Vielen Dank an dieser Stelle für die bisher gemachte Mühe :)

Genügt es das Chipselect und das avalon_write Signal zu verunden? Da 
muss ich wohl noch mal in die Avalon Spezifikations PDFs reinsehen.

Ich liefere meinem Modul ein Valid Signal, wird dieses Gesetzt darf die 
externe Logik die Daten übernehmen.
Entity Deklaration:
1
entity  Avalon_Bridge  is
2
        generic  (
3
                AUTO_CLOCK_CLOCK_RATE  :  string  :=  "-1"
4
                 );
5
        port  (
6
                avs_s0_address       :  in    std_logic_vector(7  downto  0)   :=  (others  =>  '0');  -- s0.address
7
                avs_s0_read          :  in    std_logic                        :=  '0';                -- .read
8
                avs_s0_readdata      :  out  std_logic_vector(31  downto  0);                          -- .readdata
9
                avs_s0_write         :  in    std_logic                        :=  '0';                -- .write
10
                avs_s0_writedata     :  in    std_logic_vector(31  downto  0)  :=  (others  =>  '0');  -- .writedata
11
                avs_s0_readdatavalid :  out  std_logic;                                                -- .readdatavalid
12
                avs_s0_waitrequest   :  out  std_logic;                                                -- .waitrequest
13
                clk                  :  in    std_logic                         :=  '0';               -- clock.clk
14
                reset                :  in    std_logic                         :=  '0';               -- reset.reset
15
                data_out       : out std_logic_vector(31 downto 0); --data to external logic
16
                data_out_valid       : out std_logic --data valid signal
17
              );
18
end  entity  Avalon_Bridge;

Den Tip mit dem Debugregister probiere ich heute gleich mal aus, dafür 
muss ich nur zuerst das Lesen auch implementieren (also eine State 
Machine basteln) :)

von Largo (Gast)


Lesenswert?

Ich habe gerade eben die Avalon Spezifikationen gelesen und bin über 
diesen Passus gestolpert:

"The chipselect signal is not necessary; Altera does not recommend using 
it."

Aus welchem Grund sollte es vermieden werden? Nach deiner Argumentation 
erschien mir die Verwedendung eigentlich sehr sinnvoll.

von rev (Gast)


Lesenswert?

Also das ist bei mir schon länger her, das mit dem chipselect wusste ich 
nicht. Wahrischenilich meint Altera damit, man soll das chipselect nicht 
mehr für neeu Designs verwenden (vielleicht weil es irgendwann mal 
abgeschafft wird).
Aber du hast ja das read und write Signal. Die Avalon-spec ist an dieser 
Stelle eigentlich recht ausführlich. Ein einfacher Slave (ohen Burst, 
etc.) ist nicht wirklich besonders aufwendig zu implementieren.

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.