Forum: FPGA, VHDL & Co. AXI4 in eigenes Design einbauen.


von Gustl B. (-gb-)


Lesenswert?

Hallo,

man findet jede Menge Beschreibungen und so wie man seine eigene IP mit 
einem AXI4 Interface versieht, also die dann als Slave an einen Master 
hängen kann.

Ich will das umgekehrte machen und Daten von einem AXI4-Lite Slave (dem 
XADC im Artix7) lesen. Was macht man da? AXI4-Lite oder AXI4-Stream? 
Dann sind da massig Anschlüsse, braucht man die alle? Ich will doch nur 
einen ADC-Wert lesen ...

von Christian R. (supachris)


Lesenswert?

Den XADC kannst du auch ohne Axi auslesen, und zwar mit dem DRP. Ist 
viel einfacher.

von unbekannt (Gast)


Lesenswert?

Hallo,

AXI4-Lite ist das richtige Interface
eigene State-Maschine implementieren, die etwa folgendes macht:

- Adresse des Registers mit ADC-Wert an araddr anlegen und
arvalid und rready auf high setzen
- warten bis slave arready high setzt, ist ggf. schon am Anfang high
- dann arvalid auf low setzen
- rdata (ADC-Wert) gültig, wenn Slave rvalid high setzt

von -gb- (Gast)


Lesenswert?

Ok, Danke!

Jetzt hab ich ein anderes Problem:

Für Vivado hab ich die XADC-Eingänge in der .xdc so beschrieben:
1
set_property PACKAGE_PIN A13 [get_ports XADC_p]        
2
set_property IOSTANDARD LVCMOS33 [get_ports XADC_p]
3
4
set_property PACKAGE_PIN A14 [get_ports XADC_n]        
5
set_property IOSTANDARD LVCMOS33 [get_ports XADC_n]

Original sind das mehrere, ich habe also einen rausgenommen, hier das 
Original:
1
#Pmod Header JXADC
2
#Bank = 15, Pin name = IO_L9P_T1_DQS_AD3P_15,        Sch name = XADC1_P -> XA1_P
3
set_property PACKAGE_PIN A13 [get_ports {JXADC[0]}]        
4
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}]
5
#Bank = 15, Pin name = IO_L8P_T1_AD10P_15,          Sch name = XADC2_P -> XA2_P
6
set_property PACKAGE_PIN A15 [get_ports {JXADC[1]}]        
7
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}]
8
#Bank = 15, Pin name = IO_L7P_T1_AD2P_15,          Sch name = XADC3_P -> XA3_P
9
set_property PACKAGE_PIN B16 [get_ports {JXADC[2]}]        
10
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}]
11
#Bank = 15, Pin name = IO_L10P_T1_AD11P_15,          Sch name = XADC4_P -> XA4_P
12
set_property PACKAGE_PIN B18 [get_ports {JXADC[3]}]        
13
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}]
14
#Bank = 15, Pin name = IO_L9N_T1_DQS_AD3N_15,        Sch name = XADC1_N -> XA1_N
15
set_property PACKAGE_PIN A14 [get_ports {JXADC[4]}]        
16
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}]
17
#Bank = 15, Pin name = IO_L8N_T1_AD10N_15,          Sch name = XADC2_N -> XA2_N
18
set_property PACKAGE_PIN A16 [get_ports {JXADC[5]}]        
19
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}]
20
#Bank = 15, Pin name = IO_L7N_T1_AD2N_15,          Sch name = XADC3_N -> XA3_N 
21
set_property PACKAGE_PIN B17 [get_ports {JXADC[6]}]        
22
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}]
23
#Bank = 15, Pin name = IO_L10N_T1_AD11N_15,          Sch name = XADC4_N -> XA4_N
24
set_property PACKAGE_PIN A18 [get_ports {JXADC[7]}]        
25
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}]

Eingebunden im VHDL habe ich das halt als STD_LOGIC:
1
XADC_p, XADC_n : in STD_LOGIC;

Und mit dem XADC verbunden:
1
vp_in => XADC_p, -- Dedicated Analog Input Pair
2
vn_in => XADC_n,

Der Fehler den ich bekomme:
[Vivado 12-1411] Cannot set LOC property of ports, Illegal to place 
instance xadc0/U0/AXI_XADC_CORE_I/XADC_INST on site ILOGIC_X0Y132. The 
location site type does not match the instance type. Instance 
xadc0/U0/AXI_XADC_CORE_I/XADC_INST belongs to a shape with reference 
instance XADC_p_IBUF_inst. Shape elements have relative placement 
respect to each other. The invalid location might results from a 
constraint on any of the instance in the shape. 
["D:/vhdl/nex_4_test0/nex_4_test0.srcs/constrs_1/imports/vhdl/Nexys4_Mas 
ter.xdc":326]

Man findet schon was wenn man nach Nexys4 XADC sucht, aber keine Lösung.
Das sind ja dedizierte Ports und hier
https://forums.xilinx.com/t5/3rd-Party-Other-Boards-and-Kits/What-IO-standard-is-necessary-to-use-JXADC-port-on-Nexys-4-Board/td-p/568600
schreibt jemand dass man da nix machen muss, also muss ich die in der 
.xdc/.ucf beschreiben? Und im VHDL, was verbinde ich dann im PORT MAP 
mit dem XADC? Dazu muss dfas doch schon im VHDL bekannt sein.

von Christian R. (supachris)


Lesenswert?

Da musst du wirklich nix selber machen. Also klar, die Ports musst du 
nach ganz außen ins Top Level führen, kannst auch nix abzweigen da für 
andere Sachen. Im xdc entweder ganz raus lassen, oder wenn du das Design 
nach Sythese oder Implement öffnest und in den Port-Editor gehst, dann 
füllt Vivado automatisch beim reinklicken alle verwendeten XADC Ports 
richtig in die Tabelle.

von Gustl B. (-gb-)


Lesenswert?

Ja ähm ... aber der generierte XADC mit AXI4-Anschluss hat eben vp_in 
und vn_in. Da muss ich doch im Port Map irgendwas anschließen?

von Gustl B. (-gb-)


Lesenswert?

So, jetzt in der .xdc nicht erwähnt und es baut trotzdem, habe nur in 
der Toplevel eben diese zwei Eingänge, hier xadcp und xadcn.

Nach der Implementation wurden die auch Pins zugeordnet und zwar K9 und 
J10.

Aber: Wohin sind diese Pins geführt?

Vom Boardhersteller (Digilent) habe ich das hier:
1
#Pmod Header JXADC
2
#Bank = 15, Pin name = IO_L9P_T1_DQS_AD3P_15,        Sch name = XADC1_P -> XA1_P
3
set_property PACKAGE_PIN A13 [get_ports {JXADC[0]}]        
4
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}]
5
#Bank = 15, Pin name = IO_L8P_T1_AD10P_15,          Sch name = XADC2_P -> XA2_P
6
set_property PACKAGE_PIN A15 [get_ports {JXADC[1]}]        
7
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}]
8
#Bank = 15, Pin name = IO_L7P_T1_AD2P_15,          Sch name = XADC3_P -> XA3_P
9
set_property PACKAGE_PIN B16 [get_ports {JXADC[2]}]        
10
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}]
11
#Bank = 15, Pin name = IO_L10P_T1_AD11P_15,          Sch name = XADC4_P -> XA4_P
12
set_property PACKAGE_PIN B18 [get_ports {JXADC[3]}]        
13
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}]
14
#Bank = 15, Pin name = IO_L9N_T1_DQS_AD3N_15,        Sch name = XADC1_N -> XA1_N
15
set_property PACKAGE_PIN A14 [get_ports {JXADC[4]}]        
16
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}]
17
#Bank = 15, Pin name = IO_L8N_T1_AD10N_15,          Sch name = XADC2_N -> XA2_N
18
set_property PACKAGE_PIN A16 [get_ports {JXADC[5]}]        
19
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}]
20
#Bank = 15, Pin name = IO_L7N_T1_AD2N_15,          Sch name = XADC3_N -> XA3_N 
21
set_property PACKAGE_PIN B17 [get_ports {JXADC[6]}]        
22
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}]
23
#Bank = 15, Pin name = IO_L10N_T1_AD11N_15,          Sch name = XADC4_N -> XA4_N
24
set_property PACKAGE_PIN A18 [get_ports {JXADC[7]}]        
25
  set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}]

Da sind die Pins nicht dabei. Also ist das eine alternative Beschreibung 
für den Fall wenn ich die Pins nicht mit dem XADC verwende?

Das mit der Statemachine hab ich so gebaut:
1
process begin
2
    wait until rising_edge(clk);
3
    if    xadc_fsm = 0 then
4
    -- Adresse des Registers mit ADC-Wert an araddr anlegen und arvalid und rready auf high setzen
5
        xadc_arvalid <= '1';
6
        xadc_rready <= '1';
7
        xadc_fsm <= 1;
8
    elsif xadc_fsm = 1 then
9
    -- warten bis slave arready high setzt, ist ggf. schon am Anfang high
10
        if xadc_arready = '1' then
11
        -- dann arvalid auf low setzen
12
            xadc_fsm <= 2;
13
            xadc_arvalid <= '0';
14
        end if;
15
    elsif xadc_fsm = 2 then
16
    -- rdata (ADC-Wert) gültig, wenn Slave rvalid high setzt
17
        if xadc_rvalid = '1' then
18
            xadc_data_out <= xadc_data;
19
            xadc_rready <= '0';
20
            xadc_fsm <= 0;
21
        end if;
22
    end if;
23
end process;

Aber ich bekomme keine Daten.

: Bearbeitet durch User
von Christian R. (supachris)


Lesenswert?

vp_in und vn_in sind sowieso völlig getrennte dedizierte Anschlüsse in 
Bank 0. Da kann man gar nix konfigurieren. Wo genau das hingeht, musst 
du im Schaltplan schauen. Die Anschlüsse die da im xdc stehen, sind ja 
die XADC Pins, die auch normale I/Os sein können. Alle XADC Eingänge die 
du im Core Generator aktiviert hast, musst du bis ganz hoch ins Top 
Level verdrahten. Also klar, in der port map mit einem STD_LOGIC oder 
STD_LOGIC_VECTOR (für AUX Eingänge).

von Gustl B. (-gb-)


Lesenswert?

Du scheinst das ja schonmal verwendet zu haben, kann ich da einfach aus 
einem Register, hier 0x20c lesen oder muss ich noch irgendwas machen 
oder dem xadc schicken damit der überhaupt anfängt zu arbeiten?

Die Statemachine läuft hier dauernd durch, also irgendwas passiert, aber 
das gelesene Register ist immer 0.

von Christian R. (supachris)


Angehängte Dateien:

Lesenswert?

Ja, ich verwende den XADC regelmäßig. Ich hab den so parametriert, dass 
er im Continous Modus durch den Channel Sequencer läuft, alle 
aktivierten Kanäle sampelt und mittelt. Da muss man nix weiter machen.
Ich verwende aber den DRP, das geht viel einfacher. Irgendwo im User 
Guide gibts dafür den Tipp, wie man das verschaltet, so dass sich das 
alles selber triggert:
1
--after each channel sampling is finished, read the result via DRP interface
2
  DADDR_IN <= "00" & CHANNEL_OUT;
3
  DEN_IN <= EOC_OUT;
4
  
5
  --store results in an array
6
  process(CLK)
7
  begin
8
    if rising_edge(CLK)then
9
      if DRDY_OUT = '1' then Results(to_integer(unsigned(CHANNEL_OUT))) <= DO_OUT;
10
      end if;
11
    end if;
12
  end process;
13
  
14
  TEMP_OUT     <= Results(0);
15
  VCCINT_OUT     <= Results(1);
16
  VCCAUX_OUT     <= Results(2);
17
  VPN_OUT       <= Results(3);
18
  VCCBRAM_OUT   <= Results(6);
19
  VAUX0_OUT     <= Results(16);
20
  VAUX1_OUT     <= Results(17);
21
  VAUX2_OUT     <= Results(18);
22
  VAUX3_OUT     <= Results(19);
23
  VAUX4_OUT     <= Results(20);
24
  VAUX5_OUT     <= Results(21);
25
  VAUX6_OUT     <= Results(22);
26
  VAUX7_OUT     <= Results(23);
27
  VAUX8_OUT     <= Results(24);
28
  VAUX9_OUT     <= Results(25);
29
  VAUX12_OUT     <= Results(28);
30
  VAUX13_OUT     <= Results(29);

Result ist 32x16 Array.

von Gustl B. (-gb-)


Lesenswert?

Ok, also ich hab das als Single Channel eingestellt mit AXI4Lite. Unter 
Anderem weil ich auch mal selbst was vom AXI lesen wollte, gibt ja noch 
mehr Zeug bei dem das Interface nützlich erscheint. Jetzt habe ich aber 
eine generelle Frage:

Wann verwendet man AXI oder wann ist es sinnvoll AXI zu benutzen?

Ich nutze keine CPU, also weder Microblace noch sonst was das AXI-Master 
hat, aber ich habe einige Hardware wie eben den XADC den man an AXI 
anschließen kann. Ausserdem sind auf dem Naxys4 Geräte verbaut die ein 
SPI oder I2C Interface haben, auch dafür gibt es AXI Bausteine.

Sollte ich das ohne AXI machen wenn ich keine CPU verwende? Wie geht man 
da vor wenn man Geräte an ein eigenes Design anschließen will? Bisher 
hab ich das halt selber in VHDL beschrieben, also einen UART z. B. aber 
gibt es halt auch fertig mit AXI, sprich wenn ich einmal AXI kann, spare 
ich mir dann in Zukunft Arbeit - so die Hoffnung.

Oh und ... viele weitere Komponenten die man sich generieren lassen kann 
wie FIR-Filter haben natürlich auch AXI. Jedoch AXI4-Stream. Ist das 
Stream Interface einfacher? Das könnte ich auch beim XADC einstellen.

Danke!

: Bearbeitet durch User
von Christian R. (supachris)


Lesenswert?

Naja, ohne CPU ergibt für mich Axi keinen echten Sinn, da kann man 
lieber was Ressourcen schonenderes machen. Axi Stream ist recht simpel, 
das ist quasi ein Fifo Slave und ein Fifo Master.

von Gustl B. (-gb-)


Lesenswert?

Verwendest Du eine CPU? Wie macht man das ohne CPU wenn man Komponenten 
anschießen will die nur AXI bieten?

Gut ich gucke mir mal den AXI4-Stream an ...

von Christian R. (supachris)


Lesenswert?

Nee, bisher hatte ich noch nie den Fall, dass ich eine CPU im FPGA 
gebraucht hätte. Ohne CPU muss man die Ansteuerung halt ganz klassisch 
mit State Machines machen

von Gustl B. (-gb-)


Lesenswert?

Den Fall hatte ich bisher auch nicht. Gibt es irgendwo eine schöne 
Vorlage für eine FSM die einen AXI4Lite Slave bedient? Liefert Xilinx 
sowas?

von Besucher (Gast)


Lesenswert?

Gustl B. schrieb:
> Gibt es irgendwo eine schöne
> Vorlage für eine FSM die einen AXI4Lite Slave bedient? Liefert Xilinx
> sowas?

Ich kenne keine Vorlage für eine AXI4Lite FSM. Wenn man sich in Vivado 
jedoch einen eigenen IPCore mit AXI4Lite-Master Interface generiert, 
könnte man sich die generierte vhd-Datei anschauen. Leider ist die 
Implementierung von Xilinx eine Sammlung von kleinen Prozessen und keine 
FSM, die das AXI4-Protokoll implementiert.

Vielleicht ist auch das Xilinx Dokument PG161 "LogiCORE IP AXI Master 
Lite v3.0" interessant: "The LogiCORE™ IP AXI Master Lite core provides 
an interface between a user-created IP core and an AXI4-Lite interface"

von Gustl B. (-gb-)


Lesenswert?

Hallo,

den LogiCORE IP AXI Master
Lite v3.0 finde ich nicht in Vivado.

AXI-Stream bringt eine seltame Fehlermeldung bei der Synthese, dass der 
Reset irgendwie bedient werden muss damit der FIFO funktioniert aber das 
resetn hab ich auf '1' gelegt, seltsam. Ich lass das mit dem AXI vorerst 
wobei halt auch viele Mathe Cores das Interface haben.

von user (Gast)


Lesenswert?

Schau mal unter Language Templates, da sollte auch ein AXI-Master/Slave 
dabei sein

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

@ user: Da finde ich nix in VIVADO, jetzt verwende ich den DRP.

@ Christian R.: So jetzt mache ich das mit DRP wie von Dir angegeben. 
Das scheint auch zu klappen, also ich bekomme Werte vom ADC, aber ... 
ich will nix internes samplen sondern eine externe Spannung.

Habe das Nexys4 und da gibt es im Schaltplan
XADC1_p, XADC1_n
XADC2_p, XADC2_n
XADC3_p, XADC3_n
XADC4_p, XADC4_n

dabei geht

IO_L7P_T1_AD2P_15     an B16_XA3_P
IO_L7N_T1_AD2N_15     an B17_XA3_N
IO_L8P_T1_AD10P_15    an A15_XA2_P
IO_L8N_T1_AD10N_15    an A16_XA2_N
IO_L9P_T1_DQS_AD3P_15 an A13_XA1_P
IO_L9N_T1_DQS_AD3N_15 an A14_XA1_N
IO_L10P_T1_AD11P_15   an B18_XA4_P
IO_L10N_T1_AD11N_15   an A18_XA4_N

so, jetzt hab ich im VHDL folgendes:

Ich habe den XADC als Component eingebunden, der hat dann die Anschlüsse
vp_in und vn_in. Diese habe ich verbunden auf std_logic die ich am 
Topmodul rausführe also

xadc_p : in std_logic
xadc_n : in std_logic

das ist in der .xdc (Constraints) nicht erwähnt, wird aber trotzdem auf 
FPGA IOs gelegt. Wenn ich mir das Package angucke (siehe Bild), dann ist
xadc_p mit Pin J10
xadc_n mit Pin K9
verbunden.

Die kommen aber irgendwie nicht am XADC-PMOD-Header auf dem Nexys4 an?! 
Wo sehe ich was da wie verbunden ist?

Vielen Dank!

von Gustl B. (-gb-)


Lesenswert?

Argh! Ich musste natürlich vauxp3 und vauxn3 verwenden ... jetzt passt 
alles.

von Gustl B. (-gb-)


Lesenswert?

Hallo, ich habe schon wieder eine Frage (gelöst):

Also wenn ich den XADC Block mit dem Zauberer erzeugen lasse, dann kann 
ich auch einstellen was bei der Simulation verwendet wird. Ich habe 
dafür einen Sinus gewählt und es wird auch eine Datei mit vielen Werten 
generiert.

Jetzt habe ich ein Design in dem auch der XADC als component vorkommt. 
Die Anschlüsse vom XADC werden in der .ucf/.xdc nicht erwähnt, sind aber 
in der Portbeschreibung der Toplevel entity drinnen.

Nun will ich eine Testbench schreiben und das ganze da einbinden. Was 
mache ich mit den XADC Eingängen? Das sind ja analoge Drähte, wo 
schließe ich die in der Testbench an?

Edit:
Ich bekomme sogar eine Fehlermeldung:
1
Warning: *** Warning: The analog data file for XADC was not found. Use the SIM_MONITOR_FILE generic to specify the input analog data file name or use default name: design.txt. 
2
Time: 0 ps  Iteration: 0  Process: /nexys4_xadc_minimal_bench/xadc0/xadc/U0/READFILE_P  File: /wrk/2015.3/nightly/2015_09_28_1368829/data/vhdl/src/unisims/primitive/XADC.vhd

Also das Verzeichnis 
/wrk/2015.3/nightly/2015_09_28_1368829/data/vhdl/src/unisims/primitive 
gibt es bei mir nicht.

In der xadc_wiz_0.vhd steht
SIM_MONITOR_FILE => "design.txt"
und die existiert auch in
D:\projekt\projekt.srcs\sources_1\ip\xadc_wiz_0\xadc_wiz_0\simulation\ti 
ming\design.txt
da stehen aber nur recht wenige Sachen drinnen:
1
TIME    TEMP   VCCINT   VCCBRAM   VCCAUX   VP     VN    VAUXP[0]   VAUXN[0]   VAUXP[1]   VAUXN[1]   VAUXP[2]   VAUXN[2]   VAUXP[3]   VAUXN[3]   VAUXP[4]   VAUXN[4]   VAUXP[5]   VAUXN[5]   VAUXP[6]   VAUXN[6]   VAUXP[7]   VAUXN[7]   VAUXP[8]   VAUXN[8]   VAUXP[9]   VAUXN[9]   VAUXP[10]   VAUXN[10]   VAUXP[11]   VAUXN[11]   VAUXP[12]   VAUXN[12]   VAUXP[13]   VAUXN[13]   VAUXP[14]   VAUXN[14]   VAUXP[15]   VAUXN[15]
2
0    63.0  1.02  1.02  1.8  0.5  0.0  0.5  0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0 //
3
                                                                                               
4
1250  88.0  1.08  1.08  1.94  0.3  0.0  0.50  0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0 //
5
2290  53.0  0.92  0.92  1.7  0.9  0.0  0.51  0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0

Deutlich mehr steht in
D:\projekt\projekt.srcs\sources_1\ip\xadc_wiz_0\design.txt
Muss ich das in die Testbench irgendwie einbinden oder sollte das 
innerhalb der XADC component stehen?

Noch mehr Edit:
Jetzt hab ich die Datei samt Pfad angegeben in der xadc_wiz_0.vhd, statt
SIM_MONITOR_FILE => "design.txt"
staht da jetzt:
SIM_MONITOR_FILE => 
"D:\projekt\projekt.srcs\sources_1\ip\xadc_wiz_0\design.txt"

Und es kommt auch keine Fehlermeldung mehr und der XADC scheint "was zu 
machen", zumindest wackelt das drdy_xadc.
So, jetzt hab ich immernoch das Problem mit den analogen Eingängen in 
der Testbench, wenn ich die open mache, gibt es Probleme, wenn ich die 
auf '0' lege ist das Ergebnis natürlich Null aber es läuft. Ich will, 
dass da die Werte aus der angegebenen Datei verwendet werden.

Und ein letztes Edit:
Hab jetzt mal 'Z' ausprobiert und ... es funktioniert! Juhu!

Vielen Dank!

: Bearbeitet durch User
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.