mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Erik M. (delay_lama)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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).
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity QSPI_TEST_DEVICE_2 is
    Port ( 
        --SYS_CLK     : in STD_LOGIC;
        
        SPI_CLK     : out STD_LOGIC;
        SPI_CS      : out STD_LOGIC;
        
        SPI_DQ      : inout STD_LOGIC_VECTOR(3 downto 0);
        
        PUSH_VEC    : in STD_LOGIC_VECTOR(3 downto 0);
        SWITCH_VEC  : in STD_LOGIC_VECTOR(3 downto 0);
        
        LED_VEC     : out STD_LOGIC_VECTOR(11 downto 0)
    );
end QSPI_TEST_DEVICE_2;

architecture Behavioral of QSPI_TEST_DEVICE_2 is

    
    signal I_COMMAND_READ       : STD_LOGIC_VECTOR( 7 downto 0 );
    signal I_ADDRESS            : STD_LOGIC_VECTOR( 23 downto 0 );
    
    signal STATE_MACHINE_NEXT   : STD_LOGIC_VECTOR( 25 downto 0 );
    signal STATE_MACHINE        : STD_LOGIC_VECTOR( 25 downto 0 );
    
    
    
    signal I_SPI_CLK_NEXT       : STD_LOGIC;
    signal I_SPI_CLK            : STD_LOGIC;
    
    signal I_SPI_CS_NEXT        : STD_LOGIC;
    signal I_SPI_CS             : STD_LOGIC;
    
    
    signal I_SPI_DQ_NEXT        : STD_LOGIC_VECTOR( 3 downto 0 );
    signal I_SPI_DQ             : STD_LOGIC_VECTOR( 3 downto 0 );
    
    --signal I_LED_VEC_NEXT       : STD_LOGIC_VECTOR( 11 downto 0 );
    signal I_LED_VEC            : STD_LOGIC_VECTOR( 11 downto 0 );
    
    
begin
    
    SPI_CLK     <= I_SPI_CLK;
    SPI_CS      <= I_SPI_CS;
    SPI_DQ      <= I_SPI_DQ;
    LED_VEC     <= I_LED_VEC;
    
    takten:process( PUSH_VEC, SWITCH_VEC )
    begin
        if SWITCH_VEC(0) = '1' then -- RESET
            STATE_MACHINE   <= (0 => '1', others => '0');
            I_SPI_CLK       <= '0';
            I_SPI_CS        <= '1';
            I_SPI_DQ        <= "ZZZZ";
        else
            if rising_edge(PUSH_VEC(0)) then
                STATE_MACHINE   <= STATE_MACHINE_NEXT;
                I_SPI_CLK       <= I_SPI_CLK_NEXT;
                I_SPI_CS        <= I_SPI_CS_NEXT;
                I_SPI_DQ        <= I_SPI_DQ_NEXT;
            end if;        
        end if;
    end process;

    calc_state_machine_next: process(STATE_MACHINE)
        variable VAR_STATE_MACHINE_NEXT     : STD_LOGIC_VECTOR( 25 downto 0 );       
    begin
        VAR_STATE_MACHINE_NEXT := (others => '0');
        for state in 0 to 25 loop
            if STATE_MACHINE(state) = '1' then
                if state < 25 then
                    VAR_STATE_MACHINE_NEXT(state+1) := '1';
                else
                    VAR_STATE_MACHINE_NEXT(state) := '1';
                end if;
            end if;
        end loop;
        STATE_MACHINE_NEXT <= VAR_STATE_MACHINE_NEXT;
    end process;
    
    calc_i_spi_clk_next: process(I_SPI_CLK)
    begin
        I_SPI_CLK_NEXT <= not I_SPI_CLK;    
    end process;
    
    calc_i_spi_cs_next: process(I_SPI_CS)
    begin
        I_SPI_CS_NEXT <= '0';
    end process;

    calc_i_spi_dq_next: process(STATE_MACHINE)
        variable VAR_I_SPI_DQ_NEXT  : STD_LOGIC_VECTOR( 3 downto 0);
    begin
        VAR_I_SPI_DQ_NEXT := (others => 'Z');    
    
        for state in 0 to STATE_MACHINE'LEFT loop
            if STATE_MACHINE(state) = '1' then
                -- command (8 Takte)
                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
                    VAR_I_SPI_DQ_NEXT(0) := I_COMMAND_READ(I_COMMAND_READ'LEFT-state);
                    VAR_I_SPI_DQ_NEXT(1) := 'Z';
                    VAR_I_SPI_DQ_NEXT(2) := 'Z';
                    VAR_I_SPI_DQ_NEXT(3) := '1';
                end if;
                -- Address (6 Takte) -> (je 4 Bit)
                if state = 8 or state = 9 or state = 10 or state = 11 or state = 12 or state = 13 then
                    VAR_I_SPI_DQ_NEXT(0) := I_ADDRESS( 20 - ( (state - 8) * 4 ) );
                    VAR_I_SPI_DQ_NEXT(1) := I_ADDRESS( 21 - ( (state - 8) * 4 ) );
                    VAR_I_SPI_DQ_NEXT(2) := I_ADDRESS( 22 - ( (state - 8) * 4 ) );
                    VAR_I_SPI_DQ_NEXT(3) := I_ADDRESS( 23 - ( (state - 8) * 4 ) );
                end if;
                -- dummy (10 Takte)
                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
                    VAR_I_SPI_DQ_NEXT(0) := 'Z';
                    VAR_I_SPI_DQ_NEXT(1) := 'Z';
                    VAR_I_SPI_DQ_NEXT(2) := 'Z';
                    VAR_I_SPI_DQ_NEXT(3) := 'Z';
                end if;
                -- read
                if state = 24 or state = 25 then
                    VAR_I_SPI_DQ_NEXT(0) := 'Z';
                    VAR_I_SPI_DQ_NEXT(1) := 'Z';
                    VAR_I_SPI_DQ_NEXT(2) := 'Z';
                    VAR_I_SPI_DQ_NEXT(3) := 'Z';
                end if;
            end if;
        end loop;
    
        I_SPI_DQ_NEXT <= VAR_I_SPI_DQ_NEXT;
    end process;
    
    
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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity blinky is
    port (        
        clk     : in    std_logic;                 
        led_1   : out   std_logic;
        led_2   : out   std_logic;
        led_3   : out   std_logic
    );
end entity blinky;

architecture rtl of blinky is
    
    signal count    : unsigned( 31 downto 0) := to_unsigned( 0, 32);

begin
    
    -------------------------------------------------- 
    -- processing
    count       <= count     + 1 when rising_edge( clk); 
    
    -------------------------------------------------- 
    -- outputs
    led_1   <= count( 26);
    led_2   <= count( 28); 
    led_3   <= count( 30); 

end architecture rtl;

Duke

von Delay_Lama (Gast)


Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.