Hallo Leute, ich versuche an meine Spartan 3E StarterKit den M25P16 Speicher anzusteuern(lesen + schreiben) aber irgendwie will er nicht. Ich weiss nicht, ob es an meinem Code liegt oder sonst wo. Hat jemand von euch ein VHDL Modul geschrieben, um den M25P16 anzusteuern? Danke Patrik
Ich versuche folgendes: architecture Behavioral of M25P16 is type rdrs_fsm_type is(rdrs_wait_for_start, rdrs_cs, rdrs_w1, rdrs_pdw1, rdrs_w1b, rdrs_w2, rdrs_pdw2, rdrs_w2b, rdrs_w3, rdrs_pdw3, rdrs_w3b, rdrs_w4, rdrs_pdw4, rdrs_w4b, rdrs_w5, rdrs_pdw5, rdrs_w5b, rdrs_w6, rdrs_pdw6, rdrs_w6b, rdrs_w7, rdrs_pdw7, rdrs_w7b, rdrs_r0, rdrs_pdr0, rdrs_r0b, rdrs_r1, rdrs_pdr1, rdrs_r1b, rdrs_r2, rdrs_pdr2, rdrs_r2b, rdrs_r3, rdrs_pdr3, rdrs_r3b, rdrs_r4, rdrs_pdr4, rdrs_r4b, rdrs_r5, rdrs_pdr5, rdrs_r5b, rdrs_r6, rdrs_pdr6, rdrs_r6b, rdrs_r7, rdrs_pdr7, rdrs_r7b); signal rdrs_fsm : rdrs_fsm_type; CONSTANT RDID : std_logic_vector(7 downto 0) := x"9F"; begin process(reset, clk) begin if reset = '1' then rdrs_fsm <= rdrs_wait_for_start; clk_out <= '0'; elsif clk = '1' and clk'event then case rdrs_fsm is when rdrs_wait_for_start => if start = '1' then cs <= '0'; d <= RDID(7); rdrs_fsm <= rdrs_cs; else cs <= '1'; clk_out <= '0'; end if; when rdrs_cs => clk_out <= '1'; rdrs_fsm <= rdrs_w1; when rdrs_w1 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw1; when rdrs_pdw1 => d <= RDID(6); rdrs_fsm <= rdrs_w1b; when rdrs_w1b => clk_out <= '1'; rdrs_fsm <= rdrs_w2; when rdrs_w2 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw2; when rdrs_pdw2 => d <= RDID(5); rdrs_fsm <= rdrs_w2b; when rdrs_w2b => clk_out <= '1'; rdrs_fsm <= rdrs_w3; when rdrs_w3 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw3; when rdrs_pdw3 => d <= RDID(4); rdrs_fsm <= rdrs_w3b; when rdrs_w3b => clk_out <= '1'; rdrs_fsm <= rdrs_w4; when rdrs_w4 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw4; when rdrs_pdw4 => d <= RDID(3); rdrs_fsm <= rdrs_w4b; when rdrs_w4b => clk_out <= '1'; rdrs_fsm <= rdrs_w5; when rdrs_w5 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw5; when rdrs_pdw5 => d <= RDID(2); rdrs_fsm <= rdrs_w5b; when rdrs_w5b => clk_out <= '1'; rdrs_fsm <= rdrs_w6; when rdrs_w6 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw6; when rdrs_pdw6 => d <= RDID(1); rdrs_fsm <= rdrs_w6b; when rdrs_w6b => clk_out <= '1'; rdrs_fsm <= rdrs_w7; when rdrs_w7 => clk_out <= '0'; rdrs_fsm <= rdrs_pdw7; when rdrs_pdw7 => d <= RDID(0); rdrs_fsm <= rdrs_w7b; when rdrs_w7b => clk_out <= '1'; rdrs_fsm <= rdrs_r0; when rdrs_r0 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr0; when rdrs_pdr0 => data_out(7) <= q; rdrs_fsm <= rdrs_r0b; when rdrs_r0b => clk_out <= '1'; rdrs_fsm <= rdrs_r1; when rdrs_r1 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr1; when rdrs_pdr1 => data_out(6) <= q; rdrs_fsm <= rdrs_r1b; when rdrs_r1b => clk_out <= '1'; rdrs_fsm <= rdrs_r2; when rdrs_r2 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr2; when rdrs_pdr2 => data_out(5) <= q; rdrs_fsm <= rdrs_r2b; when rdrs_r2b => clk_out <= '1'; rdrs_fsm <= rdrs_r3; when rdrs_r3 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr3; when rdrs_pdr3 => data_out(4) <= q; rdrs_fsm <= rdrs_r3b; when rdrs_r3b => clk_out <= '1'; rdrs_fsm <= rdrs_r4; when rdrs_r4 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr4; when rdrs_pdr4 => data_out(3) <= q; rdrs_fsm <= rdrs_r4b; when rdrs_r4b => clk_out <= '1'; rdrs_fsm <= rdrs_r5; when rdrs_r5 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr5; when rdrs_pdr5 => data_out(2) <= q; rdrs_fsm <= rdrs_r5b; when rdrs_r5b => clk_out <= '1'; rdrs_fsm <= rdrs_r6; when rdrs_r6 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr6; when rdrs_pdr6 => data_out(1) <= q; rdrs_fsm <= rdrs_r6b; when rdrs_r6b => clk_out <= '1'; rdrs_fsm <= rdrs_r7; when rdrs_r7 => clk_out <= '0'; rdrs_fsm <= rdrs_pdr7; when rdrs_pdr7 => data_out(0) <= q; rdrs_fsm <= rdrs_r7b; when rdrs_r7b => clk_out <= '1'; rdrs_fsm <= rdrs_wait_for_start; end case; end if; end process; end Behavioral; Das ist nichts anderes, als den Befehl 0x9F zum Speicher zu schicken und damit das ID auszulesen. Ich bekomme aber nur Müll. Der Speicher an sich funktioniert, die Applikation 'Picoblaze SPI FLASH Programmer' vom Xilinx funktioniert einwandfrei. Wenn ich mir die Doku zu dieser Anwendung anschaue, dann macht mein Code das selbe(bzw. ich weiss nicht bei welcher Flanke ich anfangen soll zu lesen, aber das würde die Bits im Ergebniss nur um eine Stelle verschieben) aber es geht nicht :(
> dann macht mein Code das selbe hast du das Design schon mal simuliert? > bzw. ich weiss nicht bei welcher Flanke ich anfangen soll zu lesen Dazu gibt es das Datenblatt. Du kannst immer 2 deiner Zustände zusammenfassen, weil bei SPI nicht zwischen den Flanken vom Takt etwas passiert, sondern wegen (und damit an) den Flanken vom Takt. SPI ist nichts anderes als gekoppelte Schieberegister. Dein Code:
1 | when rdrs_pdw1 => |
2 | d <= RDID(6); |
3 | rdrs_fsm <= rdrs_w1b; |
4 | when rdrs_w1b => |
5 | clk_out <= '1'; |
6 | rdrs_fsm <= rdrs_w2; |
7 | when rdrs_w2 => |
8 | clk_out <= '0'; |
9 | rdrs_fsm <= rdrs_pdw2; |
10 | when rdrs_pdw2 => |
11 | d <= RDID(5); |
12 | rdrs_fsm <= rdrs_w2b; |
13 | when rdrs_w2b => |
14 | clk_out <= '1'; |
15 | rdrs_fsm <= rdrs_w3; |
16 | when rdrs_w3 => |
17 | clk_out <= '0'; |
18 | rdrs_fsm <= rdrs_pdw3; |
Kompakter:
1 | when rdrs_w1 => |
2 | clk_out <= '0'; -- gleichzeitig mit fallender Flanke |
3 | d <= RDID(6); -- Daten ändern |
4 | rdrs_fsm <= rdrs_w1b; |
5 | when rdrs_w1b => |
6 | clk_out <= '1'; |
7 | rdrs_fsm <= rdrs_w2; |
8 | when rdrs_w2 => |
9 | clk_out <= '0'; |
10 | d <= RDID(5); |
11 | rdrs_fsm <= rdrs_w2b; |
12 | when rdrs_w2b => |
13 | clk_out <= '1'; |
14 | rdrs_fsm <= rdrs_w3; |
15 | when rdrs_w3 => |
16 | clk_out <= '0'; |
17 | d <= RDID(4); |
18 | :
|
19 | :
|
20 | when rdrs_r2 => |
21 | clk_out <= '0'; |
22 | rdrs_fsm <= rdrs_pdr2; |
23 | when rdrs_pdr2 => |
24 | clk_out <= '1'; |
25 | data_out(5) <= q; -- mit der steigenden Flanke |
26 | rdrs_fsm <= rdrs_r3; -- die Daten einlesen |
27 | when rdrs_r3 => |
28 | clk_out <= '0'; |
29 | rdrs_fsm <= rdrs_pdr3; |
30 | when rdrs_pdr3 => |
31 | clk_out <= '1'; |
32 | data_out(4) <= q; |
33 | rdrs_fsm <= rdrs_r4; |
34 | when rdrs_r4 => |
35 | clk_out <= '0'; |
36 | rdrs_fsm <= rdrs_pdr4; |
Aber solche Copy-Paste-Statemachines sind Käse. Nicht skalierbar, voller Tippfehler (sag bloß nicht, da sei keiner dringewesen ;-) usw. Du solltest vorher überlegen, was du eigentlich brauchst. Für SPI: ein Schieberegister, nicht einen Multiplexer.
Ursprünglich habe ich das so gehabt wie du es vorgeschlagen hast. Dann habe ich mir das 'Picoblaze SPI FLASH Programmer' Beispiel angeschaut, und sie machen es so, dass die Daten gesetzt/gelesen werden, und dann generieren sie eine High-Low Flanke auf Clock signal. Um sicher zu gehen, habe ich das auch so implementiert, kein Erfolg. Simuliert habe ich das auch, bekomme genau das was im Datenblatt steht. Ich glaube langsam, der Fehler liegt nicht im Quellcode. Der SPI Bus auf dem Board wird mit anderen Bausteinen geteilt. Diese muss man 'deaktivieren' damit man auf den Flash ansteuern kann. Das habe ich zwar gemacht, aber möglicherweise nicht richtig. Ich glaube, ich kaufe mir einen solchen Speicher und versuche ihn so anzusteuern denn ich habe keine Idee mehr :( patrik
> 'Picoblaze SPI FLASH Programmer' Beispiel angeschaut, > und sie machen es so, dass die Daten gesetzt/gelesen werden, > und dann generieren sie eine High-Low Flanke auf Clock signal. Ja, klar. Dort ist es reine Software, deshalb wird es sequentiell gemacht. > Der SPI Bus auf dem Board wird mit anderen Bausteinen geteilt. > Diese muss man 'deaktivieren' damit man auf den Flash ansteuern kann. Die anderen Bausteine müssen natürlich alle deselektiert (inaktiv) sein. sonst gehts schief. Üblicherweise also auf den SS# eine '1' legen. Hast du schon mal am Bus und den anderen Bausteinen gemessen? Die Hardware ist ok, mit dem Picoblaze gehts ja.
Ich habe es nun an Oszi angeschlossen. Der Speicher bekommt das richtige Signal, liefert aus das richtige, aber eben High sind keine 3.3V sondern nur irgendwie 1.3V. Irgendetwas stört das MISO Signal. Ich habe die Constraints-Datei von dem 'Picoblaze SPI FLASH Programmer' Beispiel genommen, mit meiner verglichen und die Signale gemessen, alles gleich. Keine Idee mehr.
> Ich habe es nun an Oszi angeschlossen. Der Speicher bekommt das > richtige Signal, liefert aus das richtige, aber eben High sind > keine 3.3V sondern nur irgendwie 1.3V. > Irgendetwas stört das MISO Signal. Buskonflikt. Zwei Teilnehmer sind auf dem Bus, eine Pattsituation. Sind tatsächlich alle anderen SPI-Busteilnehmer korrekt deselektiert? Ist dein FPGA-Pin q als Eingang definiert (nicht z.B. inout)?
Hallo Leute, habe nun das Projekt wieder ausgegraben und nach langem Suchen festgestellt, dass das tatsächlich ein Buskonflikt war und zwar mit dem Platform Flash PROM. Der Signal FPGA_INIT_B muss auf 0 stehen, und nicht auf 1 wie es in der Doku auf Seite 102 steht. Naja, hoffe jemandem geholfen zu haben :-) Grüsse Patrik
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.