Forum: FPGA, VHDL & Co. spezielles Lesetiming - so realisierbar?


von Andreas B. (loopy83)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe folgendes Problem und wollte erst einmal die Machbarkeit 
überprüfen.
Im Anhang ist das Lesetiming eines PowerPCs mit Chipscope dargestellt.

Zu sehen sind die Adressen (im 2er-Inkrement wegen 16bit Zugriff), 
Chipselect und Ouput-enable.
Der Transfer wird geburstet, es werden also immerhalb von einem 
Lesezyklus 16x16bit Werte gelesen, also 32 Byte. Es sollen erst 32Byte 
auf Fifo1 gelesen werden und dann 32byte aus Fifo2... also immer im 
Wechsel (PADD Bit 22 wechselt ale 16 Lesezugriffe den Wert, also habe 
ich es daran festgemacht).

Der Sampletakt von Chipscope war der Lesetakt PCLK.

Nun kann man ja sehen, dass sich die Adressen mit dem ersten Lesetakt 
ändern, dann noch ein Takt Luft ist und sich dann die Adresse schon 
wieder ändert.

Leider kann mir mein Kommilitone, welcher den PPC konfiguriert, nicht 
sagen, auf welchem Takt der PPC die Daten liest, aber ich vermute auf 
dem zweiten Takt.

Der Lesetakt ist 83MHz.

Ist es mit dem FPGA möglich, die Adressänderung auf dem ersten Takt zu 
erkennen und auf dem zweiten Takt die Daten auf den Bus zu legen?

Ich habe es mit einer Statemachine versucht, bin aber bisher an den 
ganzen Bedingungen gescheitert, so dass die Werte nicht zuverlässig 
gelesen werden können.

Ist eine Statemachine anhand der Abbildung machbar, die die Aufgabe 
löst, oder sind es zu wenig Takte für jeden einzelnen Lesezugriff?

Hier mein derzeitiger Versuch:
1
process (PClk)
2
  begin
3
    if rising_edge(PClk) then
4
      if reset = '0' then
5
        cam_state1 <= WARTEN;
6
        read_en1 <= '0';
7
        read_en2 <= '0';
8
        PDATA <= (others => 'Z');
9
      else
10
        case cam_state1 is
11
        
12
          -- WARTEN
13
          when WARTEN =>
14
            read_en1 <= '0';
15
            read_en2 <= '0';
16
            PDATA <= (others => 'Z');
17
            if fifos_full = '1' then
18
              cam_state1 <= LESEN_0;
19
            end if;
20
21
          -- LESEN_0
22
          when LESEN_0 =>
23
            read_en1 <= '0';
24
            read_en2 <= '0';
25
            PDATA <= (others => 'Z');
26
            if (PCS1 = '0' and POEn = '0' and PRnW = '1' and PADD(22) = '0') then
27
                read_en1 <= '1';
28
                PDATA <= fifo1_out;
29
                cam_state1 <= LESEN_2;
30
            elsif PCS1 = '1' then
31
              cam_state1 <= WARTEN;
32
            else
33
              read_en1 <= '0';
34
              read_en2 <= '0';
35
              PDATA <= (others => 'Z');
36
              cam_state1 <= WARTEN;
37
            end if;
38
          
39
          --LESEN_2
40
          when LESEN_2 =>
41
            read_en1 <= '0';
42
            read_en2 <= '0';
43
            PDATA <= (others => 'Z');
44
            if (PCS1 = '0' and POEn = '0' and PRnW = '1' and PADD(22) = '1') then
45
                read_en2 <= '1';
46
                PDATA <= fifo2_out;
47
                cam_state1 <= LESEN_0;
48
            elsif PCS1 = '1' then
49
              cam_state1 <= WARTEN;
50
            else
51
              read_en1 <= '0';
52
              read_en2 <= '0';
53
              PDATA <= (others => 'Z');
54
              cam_state1 <= WARTEN;
55
            end if;
56
          
57
          --OTHERS
58
          when others =>
59
            read_en1 <= '0';
60
            read_en2 <= '0';
61
            PDATA <= (others => 'Z');
62
            cam_state1 <= WARTEN;
63
        end case;
64
      end if;
65
    end if;
66
  end process;

VIELEN DANK!
Andi

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Andreas B. schrieb:
> Leider kann mir mein Kommilitone, welcher den PPC konfiguriert, nicht
> sagen, auf welchem Takt der PPC die Daten liest, aber ich vermute auf
> dem zweiten Takt.
Steht bestimmt im Datenblatt des PPC bzw. dessen Speichercontrollers.

> Ich habe es mit einer Statemachine versucht, bin aber bisher an den
> ganzen Bedingungen gescheitert, so dass die Werte nicht zuverlässig
> gelesen werden können.
Versuch doch erstmal dir mit dem IP Generator einen beispielcore für den 
Bus zu generieren.
Beim FSL Bus wird es z.B. so gemacht das die Zustandübergänge in einer 
Statemachine geschehen, das legen auf die "Ports" geschieht dann 
asyncron mit dem aktuellen Zustand als Bedingung, so hat man je nach 
interner Laufzeit die Daten bei der nächsten Taktflanke anliegen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wie ist der Prozessor ans FPGA gekoppelt? Eingebaut im FPGA?

Sind die Takte für den Prozessor und das FPGA die selben (oder 
wenigstens synchron)?

>             PDATA <= (others => 'Z');
Weil es einen Tristate-Bus im FPGA nicht gibt, vermute ich, der PPC 
ist extern angeschlossen. Dann sollte die Treiberumschaltung aber nicht 
an den Takt gekoppelt sein, denn sonst bist du immer zu spät dran und 
hast jeweils einen Buskonflikt. Siehe den 
Beitrag "Re: FPGA, Datenbus & Register"

von Andreas B. (loopy83)


Lesenswert?

Hallo,

PPC und FPGA sind gleich getaktet. Also der Takt wird vom PPC vorgegeben 
und mit diesem Takt takte ich dann die Leseprozesse im FPGA. Somit 
sollte es synchron laufen.

Der PPC und der FPGA sind zwei physisch getrennte ICs. An dem Bus hängt 
nur noch ein NOR-Flash, auf den sehr selten zugegriffen wird. In meinen 
bisherigen Versuchen, gab es keine Konflikte.

Wie kann ich denn die Tristate-Treiberumschaltung ungetaktet 
realisieren?
Dieser Ansatz ist mir gänzlich neu und ich habe eine derartige 
Vorgehensweise auch noch in keinem Beispiel gefunden.

Die Geschichte mit dem IP Core muss ich mir mal durchdenken. Bisher habe 
ich hier nur eine DCM und einen Fifo verwendet. Dass man hier auch die 
Buskommunikation steuern kann, ist mir neu. Ich werde mal versuchen ein 
entsprechendes Beispiel zu finden.

Ich fasse zusammen:
Das Hauptproblem besteht darin, dass der PPC mit einer Taktflanke die 
Daten von Bus liest, ich aber mit der gleichen Taktflanke die Daten erst 
auf den Bus lege. Also muss ich die Sache irgendwie asynchon regeln, 
richtig?

Vielen Dank!
Andi

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Das Hauptproblem besteht darin, dass der PPC mit einer Taktflanke die
> Daten von Bus liest, ich aber mit der gleichen Taktflanke die Daten erst
> auf den Bus lege.
Ein alte Geschichte. Wenn du das nicht über einen Dummy-Read am Anfang 
eines Lese-Bursts abhandeln kannst, dann mußt du das Timing so 
gestalten, dass du die Adresse an deinen Fifo direkt anlegst.
> Also muss ich die Sache irgendwie asynchon regeln, richtig?
Du hast z.B. kein Problem, wenn dein Fifo von sich aus gleich nach dem 
Lesen schon die nächsten Daten ausgibt.


> Wie kann ich denn die Tristate-Treiberumschaltung ungetaktet
> realisieren?
Beitrag "Re: spezielles Lesetiming - so realisierbar?"
Das hast du gelesen?

Dieser Tristate-Treiber hier legt abhängig vom oe und ce die Daten 
direkt auf den Bus:
1
d <= dat when oe = '0' and ce = '0' else (others => 'Z');
> Dieser Ansatz ist mir gänzlich neu und ich habe eine derartige
> Vorgehensweise auch noch in keinem Beispiel gefunden.
Uralte Technik. Das wird seit jeher mit jedem asynchronen Datenbus so 
gemacht.

von Andreas B. (loopy83)


Lesenswert?

Hallo,

jetzt verstehe ich die Tristategeschichte. Damit lege ich immer die 
Daten auf den Bus, wenn CE und OE = '0' sind... mit einem getakteten 
Prozess schreibe ich dann nur noch meine Ausgangsdaten in den Vector 
dat.

Ich habe zwei 16bit Fifos, die ich auslese. Abhängig von drei weiteren 
Eingängen entscheide ich, welche 8bit ich aus jedem Fifo auf den Bus 
lege, dass ich wieder auf meine 16bit Busbreite komme, aber keine Daten 
verliere bzw. ich immer entscheiden kann, welche der 16bit ich mir 
ansehen möchte.
Diese Entscheidung, geregelt über eine case Anweisung, muss ich ja 
takten. Aber wenn ich das recht überschaue kann ich ja dann in der case 
Anweisung den dat-Vector beschreiben... ja, das sollte gehen.

Ein Dummy Read am Anfang des Bursts ist leider nicht möglich, weil 
dieser über einen DMA-Tranfer geregelt wird. Da kann nach Aussage meines 
Kommilitonen der erste Read nicht verworfen werden, ohne dass das 
Adress-increment nicht auch mit aufgehoben wird.

Ich habe mir den Fifo als IP-Core implementiert. Ich habe da jetzt keine 
Möglichkeit gefunden, wie ich die Adressen direkt und die Bit-Selektion 
mit einbinden kann. Auch hat der Fifo-Speicher einen Lesetakt und es 
wird nur gelesen, wenn read_en aktiviert ist. Mir wäre neu, wenn die 
neuen Daten direkt am Ausgang anliegen würden, obwohl das read_en nicht 
gesetzt ist.

Vielen Dank!
Andi

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Ich habe mir den Fifo als IP-Core implementiert.
Schreib ihn selber und verwende Distributed RAM als Speicher:
http://www.lothar-miller.de/s9y/archives/21-FIFO.html

>Mir wäre neu, wenn die neuen Daten direkt am Ausgang anliegen würden,
Stichwort "fall thru"

von Andreas B. (loopy83)


Lesenswert?

Vielen Dank Lothar!
Ich werde mir die FiFo Sache nochmal genauer anschauen, aber den IP Core 
habe ich eigentlich als First-word-fall-throu konfiguriert.
Einen Fifo selber zu programmieren war mir bisher immer etwas zu 
komplex... zumal ich mit diesen memory-Sachen noch nie etwas zu tun 
hatte. Aber dein Code sieht ja an sich sehr übersichtlich aus... ich 
werde ihn mir mal genauer anschauen!

Fürs erste werde ich mir erst einmal damit behelfen, dass die Adressen 
bei meinem Bustiming nicht nur 2, sondern 3 Takte aktiv bleiben. So habe 
ich mir genau den weiteren Takt erschummelt, damit die Daten dann auch 
da sind, wenn sie gelesen werden. Damit sollte dann doch meine 
State-machine wieder funktionieren, oder?

Da muss ich aber glaube ich noch etwas Arbeit investieren, denn 
scheinbar läuft da noch etwas nicht ganz rund...

Vielen Dank!
Andi

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.