Hi, ich knabbere immer noch an einem Projekt, bei dem ich Daten auf eine Compact-Flash-Karte schreiben muss. Ich kenne das CFA-Paper mittlerweile gut auswendig und habe jetzt zum zweiten Mal schön Schritt für Schritt eine Statemachine gebaut, die genau den Timings im Paper folgt. Die Vorgehensweise ist ja folgende: 1. Statusregister checken, ob Karte nicht busy ist und auch keine Daten will (halt Idle-Zustand) 2. Nötige Register und Kommandos für den Schreibvorgang beschreiben 3. Eigentlicher Schreibvorgang Probleme macht mir schon der erste Schritt. Ich habe hier zwei CF-Karten, eine 16Mb, eine 2Gb, beide FAT-formatiert und (unter Windows) voll funktionsfähig. Nachdem ich bei meinem ersten Versuch der Statemachine immer nur die einzelnen Bits für Busy und DRQ gecheckt habe, ließ ich mir nun die kompletten ausgelesenen 16bit mittels LEDs anzeigen. Hier sind einige Ergebnisse, ich hab dann mal variiert und verschiedene Register ausgelesen: featureregister: 1111 1110 1000 0100 - FE84 - klein featureregister: 0100 0000 0100 0000 - 4040 - groß Statusregister: 1111 1110 1000 0100 - FE84 - klein Statusregister: 0100 1000 0100 1000 - 4848 - groß LBA1: 0100 0000 0100 0000 - 4040 - groß 0100 1000 0100 1000 - 4848 - groß beim zweiten Mal anschalten LBA1: 1111 1110 1000 0100 - FE84 - klein Sektorcount: 0100 0000 0100 1000 - 4048 - groß Sektorcount: 0100 0000 0100 1100 - 404C - groß beim 2. Mal Sektorcount: 0000 0100 0000 0000 - 0400 - groß am nächsten Morgen Sektorcount: 0100 0000 0100 1100 - 0400 - groß am nächsten Morgen Sektorcount: 1111 1110 1000 0100 - FE84 - klein Offensichtlich kommen da immer ähnliche Sachen raus, die nichts mit dem vermutlichen Inhalt des Registers zu tun haben. Kann zufällig jemand an Hand der ausgegebenen Bits irgendwas sehen, was evtl. falsch laufen könnte? Kann bei Bedarf die SM auch posten, wenn das hilft.
@ Christian Peters (kron) >ich knabbere immer noch an einem Projekt, bei dem ich Daten auf eine >Compact-Flash-Karte schreiben muss. >Probleme macht mir schon der erste Schritt. Ich habe hier zwei Da bist du ja weit gekommen . . . ;-) >CF-Karten, eine 16Mb, eine 2Gb, beide FAT-formatiert und (unter Windows) >voll funktionsfähig. Ich würde fürs erste die Finger von der 2GB Karte lassen. >Kann bei Bedarf die SM auch posten, wenn das hilft. Das wäre nicht schlecht. Denn wie es scheint ist dein Lesezugiff eher ein Griff in die Lostrommel. MfG Falk
Ok, hier ist sie, hab ein wenig gekürzt, sonst wird's zuviel:
1 | constant addr_status_register: std_logic_vector (4 downto 0) := "10111";--Statusregister (R), Command (W) |
2 | |
3 | begin
|
4 | |
5 | data_in <= DATA; |
6 | DATA <= data_out when (rw_flag = '0') else (others => 'Z'); |
7 | |
8 | RESET_CF_N <= reset_reset AND reset_state; |
9 | |
10 | state_machine: process (CLK,reset_cf) |
11 | begin
|
12 | if (reset_cf = '1') then |
13 | IOWR_N <= '1'; |
14 | IORD_N <= '1'; |
15 | addr_temp <= "00000"; |
16 | state <= idle; |
17 | next_state <= idle; |
18 | data_in_buffer <= (others => '0'); |
19 | read_counter <= (others => '0'); |
20 | ADDR <= "11111"; |
21 | reset_state <= '0'; |
22 | elsif (falling_edge (CLK)) then |
23 | |
24 | case state is |
25 | |
26 | when idle => |
27 | IOWR_N <= '1'; |
28 | IORD_N <= '1'; |
29 | reset_state <= '1'; |
30 | if (START2 = '1' AND CD1_N = '0' AND CD2_N = '0') then--eigentlich START, Debugphase |
31 | addr_temp <= addr_status_register; |
32 | state <= read_1;--Lesevorgang fürs Statusregister |
33 | next_state <= check_status_register;--Als erstes soll das Statusregister gecheckt werden |
34 | else
|
35 | state <= idle; |
36 | end if; |
37 | |
38 | when check_status_register => |
39 | ADDR <= "11111"; |
40 | case (data_in_buffer (15 downto 14)) is |
41 | when "00" => |
42 | leds (5) <= '0'; |
43 | when "01" => |
44 | leds (5) <= blink_counter (25); |
45 | when "10" => |
46 | leds (5) <= blink_counter (22); |
47 | when "11" => |
48 | leds (5) <= '1'; |
49 | when others => |
50 | null; |
51 | end case; |
52 | ...--Gekürzt. Hier werden alle Bits angezeigt. |
53 | end case; |
54 | --------------------------------------------Beginn Lesevorgang
|
55 | when read_1 =>--ADDR valid |
56 | ADDR <= addr_temp; |
57 | read_counter <= read_counter +1; |
58 | if (read_counter = "0011") then |
59 | IORD_N <= '0';--IORD auf 0 ziehen |
60 | state <= read_5; |
61 | read_counter <= (others => '0'); |
62 | end if; |
63 | |
64 | when read_5 => |
65 | read_counter <= read_counter +1;--Warten auf t2 |
66 | if (read_counter = "0101") then |
67 | if (IORDY = '1') then |
68 | state <= read_6; |
69 | read_counter <= (others => '0'); |
70 | end if; |
71 | end if; |
72 | |
73 | when read_6 => |
74 | IORD_N <= '1'; |
75 | data_in_buffer <= data_in;--Hier wird gelesen |
76 | state <= read_9; |
77 | |
78 | when read_9 => |
79 | read_counter <= read_counter +1;--Warten auf t2 |
80 | if (read_counter = "1011") then |
81 | state <= read_10; |
82 | end if; |
83 | |
84 | when read_10 => |
85 | IORD_N <= '1'; |
86 | ADDR <= "11111"; |
87 | read_counter <= (others => '0'); |
88 | state <= next_state; |
89 | ---------------------------------------------Ende Lesevorgang
|
90 | |
91 | when others => |
92 | null; |
93 | end case; |
94 | end if; |
95 | end process state_machine; |
Na mal sehen, ob du (@Falk) oder irgendjemand mich erlösen kann. :)
@ Christian Peters (kron)
>Ok, hier ist sie, hab ein wenig gekürzt, sonst wird's zuviel:
Das ist schlecht! Dann man sieht dann nicht alle Zusammenhänge! Und
Quelltexte bitte als Anhang!
MfG
Falk
Un mach mal ne gescheite Formatierung. Das kann keine Sau vernünfig lesen.
@christian also die formatierung solltest du echt ändern. ist nicht wirklich schön zu lesen. was ich bisher sehe ist das du das data-in register nicht als flip-flop ausgelegt hast sondern als latch. mach mal in dem state (z.b. Read_10, aber auf jedenfall in einem state in dem die daten anliegen müssen) in dem du das daten wort lesen willst ein data_in <= DATA; dann wie sieht das mit dem takt aus ? da deine state-machine mit dem system-takt läuft kann das evtl. zu schnell für die kompaktblitz-karte sein. da solltest du auch mal nach schauen. noch eine frage : ist beim "rauskürzen" evtl die anweisung next_state <= read_1 irgenwie verschütt gegangen ? ansonsten macht deine statemachine nicht viel (außer im zustand check-register hängenzubleiben( gruß rene
Hallo Leute, vielen Dank erstmal für eure Antworten. @Formatierung: Als ich den Text mit meinen Tabs reinkopiert habe, sah er furchtbar aus, weil ich nur 2 Leerzeichen als Tab nehme, hier sinds aber vier, deshalb habe ich alle Tabs rausgemacht. Jetzt habe ich die Datei angefügt und es sollte hübscher aussehen. >was ich bisher sehe ist das du das data-in register nicht als flip-flop >ausgelegt hast sondern als latch. mach mal in dem state (z.b. Read_10, >aber auf jedenfall in einem state in dem die daten anliegen müssen) in >dem du das daten wort lesen willst ein data_in <= DATA; Also die Verbindung zur CF-Karte ist ja ein Bus, und den behandle ich in Zeile 89f tristatemäßig (jaja, ich weiß, tristates werden nicht als Tristates behandelt und sollen nur in die Top-Ebene, aber ich habe es schon bei mehreren Projekten umgebaut und bei manchen nicht, es geht beides, die ISE erkennt das schon und macht das Richtige daraus, also bitte keine Tristatevorträge ;) ). Data_in ist also praktisch der Eingang des Datenbus und den übernehme ich immer mit ebendiesen Zeilen. Die "eigentliche" Datenübernahme geschieht dann in Zeile 278, und zwar dann auch getaktet. >dann wie sieht das mit dem takt aus ? da deine state-machine mit dem >system-takt läuft kann das evtl. zu schnell für die kompaktblitz-karte >sein. Ja, die SM läuft mit dem Systemtakt von 40 MHz, was natürlich etwas schnell wäre für die Blitzkarte, aber wie in den Zeilen 261, 269 und 283 zu sehen ist, warte ich dort die entsprechenden Zeiten mittels eines Zählers. Die nötigen Timings habe ich aus dem CF-Paper entnommen, zur Absicherung habe ich erstmal PIO-Mode 0 angestrebt, da alle Zeiten min-Zeiten sind, und das langsamste muss dann auf alle Fälle gehen. Hier mal ein Bildchen mit ein paar wichtigen Zeiten: http://img442.imageshack.us/img442/2521/timingsgw1.png >noch eine frage : ist beim "rauskürzen" evtl die anweisung next_state <= >read_1 irgenwie verschütt gegangen ? ansonsten macht deine statemachine >nicht viel (außer im zustand check-register hängenzubleiben Also die SM geht so, es gibt zwei State-Signale, einmal "state", das ist das normale, welches auch in der case-Anweisung gecheckt wird. Und dann gibt es "next_state", was so wie ein Merker genutzt wird. In Zeile 132 und 133 sieht man das, state wird read_1 und next_state check_status_register. Das heißt, die SM geht auf read_1, und dann in Zeile 291 wird state auf next_state gesetzt. Der state check_status_register zeigt momentan nur die einzelnen Bits von data_in_buffer an, da ich nur 6 LEDs habe, musste ich die 16bit ein bißchen kodieren, deshalb die blinky-Geschichte. Danke schonmal fürs nochmal Draufschauen! :)
Im Quellcode ist übrigens ein kleiner Fehler bei der LED-Darstellung, das end if in Zeile 248 dürfte nicht auskommentiert sein, so schaltet es nicht auf den else-Zweig um. Aber das ist ja für die Hauptfunktion eher uninteressant. Hat jemand etwas gefunden?
Nein. Und danke für deinen Bericht. Aber ich hoffe dass nicht jeder der (bis jetzt) 12 Downloader, die nichts finden, schreibt, dass er nichts hat. Falls ich die Lösung finde, werde ich natürlich auch hier auflösen!
@ Christian Peters (kron) >Aber ich hoffe dass nicht jeder der (bis jetzt) 12 Downloader, >die nichts finden, schreibt, dass er nichts hat. Kleiner Tipp. Um das Ganze sinvoll zu debggen zu können, solltest du einen UART mit einbauen (gibts fertig bei Xilinx, xapp 233 glaub ich). Dann kanst du direkt grössere Datenmengen zum PC schicken un dort mit einem Terminalprogramm anzeigen lassen. Z.B. HTERM, das kann ASCI/Dezimal/Binär/HEX. Und dann sollstest du mal mehrere Register auslesen und schauen, ob da halbwegs plausible Daten rauskommen. MfG Falk
Wie schonmal gesagt ist das Board schon fix. Und verschiedene Register auslesen ist doch genau das, was ich mache?! Der Fehler liegt bestimmt nicht in der Weiterverarbeitung der erhaltenen Daten, ob ich die dann am PC oder über LEDs anzeigen lasse, ist schnuppe.
@ Christian Peters (kron) >Weiterverarbeitung der erhaltenen Daten, ob ich die dann >am PC oder über LEDs anzeigen lasse, ist schnuppe. Wenn du meinst so schlau zu sein, viel Spass bei Debuggen. MFg Falk
@Christian: Ich habe es mal kurz überflogen und verstehe es noch nicht ganz, aber wie kommt die SM aus dem Zustand "check_status_register" wieder raus?
Hallo Christian, mir sind auf die Schnelle folgende Sachen aufgefallen: 1) evetuell interpretierst Du t1 falsch. Aus dem Bild kann ich das auch nicht recht deuten - gib mal die Infos die in den Notes versteckt sind. Die Zeit bezieht sich auf die steigende Flanke IORD/IOWR und den Beginn der Änderung IORDY. 2) Du fragst in der Statemachine direkt das Signal IORDY ab, welches asynchron zu Deinem Takt ist. Synchronisiere das mal mit einem Flip-Flop ein. 3) State 10 kannst Du weglassen, die Adresse muss am Ende nicht auf '11111' gesetzt werden und IORD_N war ja eh schon '1'. 4) für den timer würde ich den Typ integer verwenden, da tut man sich beim Lesen leichter. 5) kann es sein dass die Karte nach dem Reset eine längere Zeit braucht, bis man darauf zugreifen kann? Falls ja, hast Du das sichergestellt? Dein CF-Reset hab ich noch nicht durchschaut
Hallo und danke für eure Antworten und Hinweise, @Falk: Warum so empfindlich? Fakt ist, das Board liegt hier und ich kriege keine UART oder irgendwas anderes drauf. >wie kommt die SM aus dem Zustand "check_status_register" wieder raus? In dieser Version gar nicht, das ist ja erstmal nur eine Testversion. Wenn die ausgelesenen Register nicht stimmen, bringt mir die komplette SM nichts. >evetuell interpretierst Du t1 falsch. t1 ist die Zeit von address valid bis IORD-setup, das stimmt schon. >Du fragst in der Statemachine direkt das Signal IORDY ab Ok, das habe ich geändert, hat aber leider nichts geändert. >State 10 kannst Du weglassen Von hier: http://www.compuphase.com/mbr_fat.htm habe ich diesen Tipp übernommen: Although this is optional, it is recommended that both /CS0 and /CS1 are inactivated at the end of the read or write cycle. Ich weiß, dass es nichts bringt, aber es schadet auch nicht. :) Da ich sowieso die langen Cycle-Times einhalten muss, habe ich genug Zeit für alle möglichen Absicherungen. >kann es sein dass die Karte nach dem Reset eine längere Zeit braucht, >bis man darauf zugreifen kann? Habe nichts darüber gefunden, aber es kann sein und ich habe jetzt ca. 30 Sekunden Wartezeit eingebaut, bevor irgendwas passiert. Hat wiederum leider nichts gebracht! :( Wirklich tausend Dank für eure Tips, auch wenn der erlösende (noch) nicht dabei war. Ich werde auf alle Fälle dranbleiben, obwohl ich ja hoffte, dass ihr mir einen Kardinalsfehler aufzeigt, der den Knoten platzen lässt. ;)
Wie wär's wenn du mal einen Testbench schreibst und dir die Timingdiagramme ansiehst?
Ja, das habe ich natürlich gemacht, die Timings sind wie aus dem Bilderbuch, alles sieht genau so aus, wie es laut Paper und Quellcode sein soll.
Hallo Christian, kannst Du mal einen Logic-Analyzer oder wenigstens ein 4-Kanal Digi-Scope an die Flash-Schnittstelle hängen und das Timing hier posten?
Vielleicht ist es ein elektro-mechanisches Problem ? Pin verbogen, kalte Lötstelle o.ä.
Hallo nochmal, also die Pins sehen erstmal alle gut aus, und da die Karte ja schon etwas von sich gibt, schließe ich erstmal auch 'ne kalte Lötstelle aus. Habe leider kein Digitaloszi, deshalb hier ein Ausdruckscan: http://img459.imageshack.us/img459/6071/osziscanik5.jpg Das ist einmal das IORD-Signal, und, stellvertretend für den Adressbus, das Signal CS0, welches bei Aktivität auf 0 ist und sonst auf 1. Die wichtigsten Zeiten habe ich mal mit dazugeschrieben, es sieht wirklich alles gut aus (leider). Ich habe außerdem noch IORD zusammen mit einem Signal des Datenbusses analysiert. Dabei fiel mir auf, dass das Signal "sofort" (20 ns danach) mit IORD auf 0 geht. Aber vielleicht ist die Karte halt schneller als der PIO-Modus 0, den ich momentan fahre. Wenn IORD weggenommen wird, kommt ca. 30ns später der Tristate und zieht das Datensignal wieder hoch. Ach, ich scanne das auch noch schnell, warum so viele Worte, hier: http://img262.imageshack.us/img262/7154/osziscan2vt0.jpg Ist es normal, dass das Signal so langsam von 0 hoch"kriecht"?
@ Christian Peters (kron)
>Ist es normal, dass das Signal so langsam von 0 hoch"kriecht"?
Sicher, der Ausgang geht auf Tristate und irgendwelche Pull-Ups ziehen
es auf HIGH.
MFg
Falk
Ja habe ich, bleibt immer auf 1, wird nicht negiert. Das gleiche gilt für IOCS16. Das ist eigentlich auch interessant, weil ja IOCS16 0-aktiv ist. Aber das Signal wird nur im PIO-Mode 1 und 2 genutzt, und vielleicht läuft die Karte in einem schnelleren Modus.
Da beide Karten von Sandisk sind und aber unterschiedlich antworten, kann es sein, dass es Sandisk nicht so genau nimmt mit den CF-Spezifikationen?
@ Christian Peters (kron) >kann es sein, dass es Sandisk nicht so genau nimmt mit den >CF-Spezifikationen? Kaum. Setz erstmal eine soldide Debugumgebung auf. MFg Falk
@ Christian Peters (kron)
>Was soll denn das heißen? (Ich meine jetzt nicht den Tipfehler)
Dass du erstmal eine solide Testumgebung brauchst, um überhaut was zu
sehen und vergleichen zu können. Im Moment bist du noch reichlich im
Blindflug unterwegs. Ich wiederhole mich . . .
MFg
Falk
@christian du solltest dir wirklich irgendwie überlegen/versuchen ob du nicht irgendwie 2 pins für eine serielle abgreifen/klauen kannst. das vereinfacht erheblich (vor allem bist du nicht auf one-shots angewiesen die sich nur durch reset wiederholen lassen) gruß rene
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.