Forum: FPGA, VHDL & Co. QUAD-SPI ARTY7 Developmentboard


von Erik M. (delay_lama)


Lesenswert?

Guten Morgen,

ich bin gerade dabei, ein Design auf dem Arty 7 Development Board zu
entwicklen. Ich arbeite mit VIVADO.
https://store.digilentinc.com/arty-a7-artix-7-fpga-development-board-for-makers-and-hobbyists/

Leider bruche ich nun etwas mehr Platz um Daten zu speichern und möchte
dazu per Quad-SPI auf den SPI Flash Memory zugreifen. Das Protokoll
selbst ist jetzt nicht so kompliziert. Zum testen wollte ich jetzt
erstmal ein kleines Design zum auslesen entwerfen.

Im Constraint File habe ich mich an dem Shematic des Boards orientiert
und ein Devault File verwendet.
https://reference.digilentinc.com/_media/reference/programmable-logic/arty-a7/arty_a7_sch.pdf

## Quad SPI Flash
 L13   = qspi_cs (ChipSelect)
 K17   = qspi_dq[0]
 K18   = qspi_dq[1]
 L14   = qspi_dq[2]
 M14   = qspi_dq[3]

 L16   = qspi_sclk

Den Port L16 hab ich selbst geschrieben, da er nicht im Default File
vorhanden war, ich aber (zumindes so wie ich das verstanden habe) einen
SPI_CLK anschluss brauche und keinen anderen im Shematic gefunden habe.
Vielleicht ist das auch der Falsche Port?

Auf Seite 6 des Shematics st der Quad-SPI Block beschrieben. Was ich
nicht verstanden habe ist der Kommentar zwischen den beiden
Specherblöcken auf der rechten Seite [Load either the MLP8 or theSOIC16
package, not both.] weiß da jemand was damit gemeint ist?

Hat jemand Erfahrung mit dem Board und Quad-SPI oder hat das selbst
schon ein mal ausprobiert? Ich weiß grade nicht mehr weiter.



Und

, ich weiß nicht ob es da einen Zusammenhang gibt, seit kurzem habe
ich das Problem, dass ich die erzeugten .bit Datein nicht mehr auf den
FPGA flashen kann. Es kommt eine Fehlermeldung, die sagt, dass die Datei
mit dem Chip inkompatibel sei.


Ich hoffe ihr könnt mir helfen, da ich gerade echt auf dem Schlauch
stehe.


Mit freundlichem Gruß
    Delay Lama

von Hannes (Gast)


Lesenswert?

Das heisst in diesem Fall, das nur einer der beiden Chips bestueckt 
gehoert (wahrscheinlich der untere). Dies kann mit einer einfachen 
Sichtkontrolle ueberprueft werden.

Ich verwende idR den AXI-QuadSPI-Core von Xilinx selbst. Der ist zwar 
nicht besonders schnell, funktioniert aber.
Bei diesem Board ist es noch etwas leichter, weil die Clock zusaetzlich 
an L16 angeschlossen ist und nicht nur an CCLK. Dann braeuchte man den 
STARTUPE2-Block.

Das reine Lesen/Schreiben ist mit dem Microblaze und o.g. Core ruckzuck 
gemacht - optimieren geht hinterher.

von Peter (Gast)


Lesenswert?

Erik M. schrieb:
> Auf Seite 6 des Shematics st der Quad-SPI Block beschrieben. Was ich
> nicht verstanden habe ist der Kommentar zwischen den beiden
> Specherblöcken auf der rechten Seite [Load either the MLP8 or theSOIC16
> package, not both.] weiß da jemand was damit gemeint ist?

Das bedeutet, dass nur einer bestückt werden darf, da beide parallel 
verbunden sind mehr nicht.
Entweder der IC3 oder IC4.

Ich würde ganz unten anfangen und mal sehen, ob die Signale aus dem FPGA 
zum Flash kommen.

Was den Bitstream angeht, den musst du doch ersteinmal konvertieren, 
damit man ihn "flashen" kann. Hast du das gemacht?

von Erik M. (delay_lama)


Lesenswert?

Hallo Hannes,

hast du da ein Beispiel?
Ich hab ewig lange online gesucht aber nichts in der Richtung gefunden 
und dann angefangen selbst rum zu basteln. (nicht das es heißt ich hätte 
nicht selbst gesucht oder so).

Mein Test sieht momentan folgerndermaßen aus:
Ein Wrapper der das Modul mit der Hardware verbindet. der reicht im Kern 
die Signale einfach durch. Da ich testen wollte, ob das funktioniert 
wird der clk_spi über einen Button getriggert, der jetzt aber nur als 
ein komliziertes Enable für die Sys_CLK funktioniert. na ja.

das eigentliche Modul sieht folgendermaßen aus:
(Ist jetzt erstmal nur dafr da, um zu prüfen ob ich die Anschlüsse 
richtig getroffen habe, die echte QSPI-Schnittstelle kommt später, aber 
gerade mach vivado noch faxen).
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity QSPI_TEST_DEVICE_2 is
5
    Port ( 
6
        --SYS_CLK     : in STD_LOGIC;
7
        
8
        SPI_CLK     : out STD_LOGIC;
9
        SPI_CS      : out STD_LOGIC;
10
        
11
        SPI_DQ      : inout STD_LOGIC_VECTOR(3 downto 0);
12
        
13
        PUSH_VEC    : in STD_LOGIC_VECTOR(3 downto 0);
14
        SWITCH_VEC  : in STD_LOGIC_VECTOR(3 downto 0);
15
        
16
        LED_VEC     : out STD_LOGIC_VECTOR(11 downto 0)
17
    );
18
end QSPI_TEST_DEVICE_2;
19
20
architecture Behavioral of QSPI_TEST_DEVICE_2 is
21
22
    
23
    signal I_COMMAND_READ       : STD_LOGIC_VECTOR( 7 downto 0 );
24
    signal I_ADDRESS            : STD_LOGIC_VECTOR( 23 downto 0 );
25
    
26
    signal STATE_MACHINE_NEXT   : STD_LOGIC_VECTOR( 25 downto 0 );
27
    signal STATE_MACHINE        : STD_LOGIC_VECTOR( 25 downto 0 );
28
    
29
    
30
    
31
    signal I_SPI_CLK_NEXT       : STD_LOGIC;
32
    signal I_SPI_CLK            : STD_LOGIC;
33
    
34
    signal I_SPI_CS_NEXT        : STD_LOGIC;
35
    signal I_SPI_CS             : STD_LOGIC;
36
    
37
    
38
    signal I_SPI_DQ_NEXT        : STD_LOGIC_VECTOR( 3 downto 0 );
39
    signal I_SPI_DQ             : STD_LOGIC_VECTOR( 3 downto 0 );
40
    
41
    --signal I_LED_VEC_NEXT       : STD_LOGIC_VECTOR( 11 downto 0 );
42
    signal I_LED_VEC            : STD_LOGIC_VECTOR( 11 downto 0 );
43
    
44
    
45
begin
46
    
47
    SPI_CLK     <= I_SPI_CLK;
48
    SPI_CS      <= I_SPI_CS;
49
    SPI_DQ      <= I_SPI_DQ;
50
    LED_VEC     <= I_LED_VEC;
51
    
52
    takten:process( PUSH_VEC, SWITCH_VEC )
53
    begin
54
        if SWITCH_VEC(0) = '1' then -- RESET
55
            STATE_MACHINE   <= (0 => '1', others => '0');
56
            I_SPI_CLK       <= '0';
57
            I_SPI_CS        <= '1';
58
            I_SPI_DQ        <= "ZZZZ";
59
        else
60
            if rising_edge(PUSH_VEC(0)) then
61
                STATE_MACHINE   <= STATE_MACHINE_NEXT;
62
                I_SPI_CLK       <= I_SPI_CLK_NEXT;
63
                I_SPI_CS        <= I_SPI_CS_NEXT;
64
                I_SPI_DQ        <= I_SPI_DQ_NEXT;
65
            end if;        
66
        end if;
67
    end process;
68
69
    calc_state_machine_next: process(STATE_MACHINE)
70
        variable VAR_STATE_MACHINE_NEXT     : STD_LOGIC_VECTOR( 25 downto 0 );       
71
    begin
72
        VAR_STATE_MACHINE_NEXT := (others => '0');
73
        for state in 0 to 25 loop
74
            if STATE_MACHINE(state) = '1' then
75
                if state < 25 then
76
                    VAR_STATE_MACHINE_NEXT(state+1) := '1';
77
                else
78
                    VAR_STATE_MACHINE_NEXT(state) := '1';
79
                end if;
80
            end if;
81
        end loop;
82
        STATE_MACHINE_NEXT <= VAR_STATE_MACHINE_NEXT;
83
    end process;
84
    
85
    calc_i_spi_clk_next: process(I_SPI_CLK)
86
    begin
87
        I_SPI_CLK_NEXT <= not I_SPI_CLK;    
88
    end process;
89
    
90
    calc_i_spi_cs_next: process(I_SPI_CS)
91
    begin
92
        I_SPI_CS_NEXT <= '0';
93
    end process;
94
95
    calc_i_spi_dq_next: process(STATE_MACHINE)
96
        variable VAR_I_SPI_DQ_NEXT  : STD_LOGIC_VECTOR( 3 downto 0);
97
    begin
98
        VAR_I_SPI_DQ_NEXT := (others => 'Z');    
99
    
100
        for state in 0 to STATE_MACHINE'LEFT loop
101
            if STATE_MACHINE(state) = '1' then
102
                -- command (8 Takte)
103
                if state = 0 or  state = 1 or state = 2 or state = 3 or state = 4 or state = 5 or state = 6 or state = 7 then
104
                    VAR_I_SPI_DQ_NEXT(0) := I_COMMAND_READ(I_COMMAND_READ'LEFT-state);
105
                    VAR_I_SPI_DQ_NEXT(1) := 'Z';
106
                    VAR_I_SPI_DQ_NEXT(2) := 'Z';
107
                    VAR_I_SPI_DQ_NEXT(3) := '1';
108
                end if;
109
                -- Address (6 Takte) -> (je 4 Bit)
110
                if state = 8 or state = 9 or state = 10 or state = 11 or state = 12 or state = 13 then
111
                    VAR_I_SPI_DQ_NEXT(0) := I_ADDRESS( 20 - ( (state - 8) * 4 ) );
112
                    VAR_I_SPI_DQ_NEXT(1) := I_ADDRESS( 21 - ( (state - 8) * 4 ) );
113
                    VAR_I_SPI_DQ_NEXT(2) := I_ADDRESS( 22 - ( (state - 8) * 4 ) );
114
                    VAR_I_SPI_DQ_NEXT(3) := I_ADDRESS( 23 - ( (state - 8) * 4 ) );
115
                end if;
116
                -- dummy (10 Takte)
117
                if  state = 14 or state = 15 or state = 16 or state = 17 or state = 18 or state = 19 or state = 20 or state = 21 or state = 22 or state = 23 then
118
                    VAR_I_SPI_DQ_NEXT(0) := 'Z';
119
                    VAR_I_SPI_DQ_NEXT(1) := 'Z';
120
                    VAR_I_SPI_DQ_NEXT(2) := 'Z';
121
                    VAR_I_SPI_DQ_NEXT(3) := 'Z';
122
                end if;
123
                -- read
124
                if state = 24 or state = 25 then
125
                    VAR_I_SPI_DQ_NEXT(0) := 'Z';
126
                    VAR_I_SPI_DQ_NEXT(1) := 'Z';
127
                    VAR_I_SPI_DQ_NEXT(2) := 'Z';
128
                    VAR_I_SPI_DQ_NEXT(3) := 'Z';
129
                end if;
130
            end if;
131
        end loop;
132
    
133
        I_SPI_DQ_NEXT <= VAR_I_SPI_DQ_NEXT;
134
    end process;
135
    
136
    
137
end Behavioral;

//ignoriert bitte erstmal die gröbste noobigkeit, auch wenn ich immer 
interessiert daran bin was zu lernen.
// Es gibt noch einen Prozess, der einige Signale auf LEDs maped aber 
den hab ich jetzt einfach mal rausgelassen.

Der Plan war es erstmal irgendwas aus zu lesen und dann weiter zu 
entwicklen, später wird das ganze dann vernünpftig gebaut.


Und zum schluss dann natürlich die Constraints:

## Quad SPI Flash
set_property -dict { PACKAGE_PIN L13   IOSTANDARD LVCMOS33 } [get_ports 
{ qspi_cs }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_cs
set_property -dict { PACKAGE_PIN K17   IOSTANDARD LVCMOS33 } [get_ports 
{ qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0]
set_property -dict { PACKAGE_PIN K18   IOSTANDARD LVCMOS33 } [get_ports 
{ qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1]
set_property -dict { PACKAGE_PIN L14   IOSTANDARD LVCMOS33 } [get_ports 
{ qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2]
set_property -dict { PACKAGE_PIN M14   IOSTANDARD LVCMOS33 } [get_ports 
{ qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3]

set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports 
{ qspi_sclk }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3]


Da macht mir das L16 etwas sorge, da dies nicht im dem Default 
contraintfile auftaucht, ich hab das einfach mal eingefügt, da ich 
dachte, ich brauch ja ein SPI_CLK. Vielleicht ist das der Fehler?


Ich werd ansonnsten noch mal weiter gucken.

von Erik M. (delay_lama)


Lesenswert?

Peter schrieb:
> Was den Bitstream angeht, den musst du doch ersteinmal konvertieren,
> damit man ihn "flashen" kann. Hast du das gemacht?

Ja das kann sein, das es was damit zu tun hat. Womöglich hab ich 
versehentlich irgendwo eine einstellung verbaselt. Denn seitdem gehen 
auch andere Projekte, oder andere Hauptmodule nicht mehr.

Vielleicht hat es auch was damit zu tun, das ich das Board aus der Hand 
gegeben habe. Kann es sein, das da vielleicht irgendwo ein Jumper 
umgesteckt wurde, was ich übersehen habe, was einen solche Effekt hat?


Danke für die Antworten.

von Erik M. (delay_lama)


Lesenswert?

Hallo

Der Program Device Prozess bricht mit folgender Fehlermeldung ab.

set_property PROBES.FILE {} [get_hw_devices xc7a35t_0]
set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0]
set_property PROGRAM.FILE { **PATH/FILE**.bin} [get_hw_devices 
xc7a35t_0]
program_hw_devices [get_hw_devices xc7a35t_0]
ERROR: [Labtools 27-3165] End of startup status: LOW
program_hw_devices: Time (s): cpu = 00:00:06 ; elapsed = 00:00:07 . 
Memory (MB): peak = 1750.832 ; gain = 0.000
ERROR: [Common 17-39] 'program_hw_devices' failed due to earlier errors.

Es scheint was mit dwem PIN L15 zu tun zu haben.
https://forums.xilinx.com/t5/Other-FPGA-Architecture/JTAG-without-PUDC-B/td-p/634728

merkwürdig ist, das sich der Fehler nun durch alle Projekte durchzieht 
und das ich den Pin nicht in meinen Costraints verwende. Hat da jemand 
eine Idee wo ich weitergucken kann oder das selbst schon mal bei sich 
erlebt?

Gruß
 Delay_Lama

: Bearbeitet durch User
von Duke Scarring (Gast)


Lesenswert?

Vielleicht ist auch was mit der USB-Verbindung bzw. dem Programmer nicht 
in Ordnung.
Im Zweifelsfall lege ich ein neues Projekt an und schreibe ein einfaches 
Blinky um die wichtigsten Schritte der Toolchain und die grundlegende 
Hardware zu testen:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity blinky is
6
    port (        
7
        clk     : in    std_logic;                 
8
        led_1   : out   std_logic;
9
        led_2   : out   std_logic;
10
        led_3   : out   std_logic
11
    );
12
end entity blinky;
13
14
architecture rtl of blinky is
15
    
16
    signal count    : unsigned( 31 downto 0) := to_unsigned( 0, 32);
17
18
begin
19
    
20
    -------------------------------------------------- 
21
    -- processing
22
    count       <= count     + 1 when rising_edge( clk); 
23
    
24
    -------------------------------------------------- 
25
    -- outputs
26
    led_1   <= count( 26);
27
    led_2   <= count( 28); 
28
    led_3   <= count( 30); 
29
30
end architecture rtl;

Duke

von Delay_Lama (Gast)


Lesenswert?

Hi Duke,

ja das kingt vernünftig. Ich hab ein kleines Programm geschrieben, das 
einen Button auf eine LED maped, keine CLK kein Nichts.

Fehler besteht weiterhin.

Ein Kollege meinte gerade, das dem Board irgendwie, der Strom wegbricht. 
Er hatte selbst ein vergleichbares problem. Das würde sich zumindest 
damit Decken was ich in den anderen Foren gelesen habe (PUDC_B).
Der Verdacht ist, dass der SPI zum flashen (ist der JTAG, wen ich das 
richtig verstanden habe) nicht antwortet, weil ihm da irgendwie der 
Strom wegbricht.

Wenn Du oder jemand anders, bestimmte Infos brauchen um das Problem ein 
zu grenzen, dann sagt es bitte. Ich wrde das gerne verstehen und lösen.

Ich melde mich wenn ich neue Infos habe oder sich hier noch was ergibt.

Mit besten Gruß
    Delay_Lama

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.