Abend.
Ich habe "dual port dual clock" RAM als FIFO zwischen den SDRAM(133MHZ)
und VGA-Anzeige(49.5 MHZ).
---process 1, getaktet mit 133Mhz
Solange der FIFO nicht voll und bereit ist, werden die Daten von SDRAM
abgerufen. Dabei erhöhe ich FULL_Pointer um 1. Der Full_Pointer ist
immer um 1 höher als die ADDR1.
Solange die Daten verfügbar sind werden die Daten in FIFO geschrieben,
und die Schreibadresse (ADDR1) wird erhöht.
Der SDRAM liefert so viel Daten wie ich abfrage(bestätigt in SignalTap),
also darf hier ADDR1 nicht überlaufen.
----process 2, getaktet mit 49.5 Mhz
Solange der FIFO nicht Leer ist, werden die Daten ausgegeben, sonst wird
ein roter Pixel angezeigt
Nun hat das Bild ziemlich viele rote Pixel, die sich periodisch
wiederholen.
Das Bild ist ziemlich stark verzerrt. Also tippe ich auf FIFO Überlauf.
Mögliche Ursachen wären: Die Voll-Bedienung(FULL_pointer=ADDR2) wird
nicht richtig erkannt, und es werden mehr Daten abgefragt, als es in
den FIFO rein passen, so läuft die adresse1 über,die voll-Bedienung wird
ignoriert,kurz erscheint die Empty-Bedienung (wegen ADDR1=ADDR2) und
der FIFO wird neu überschrieben.
Leider funktioniert die Simulation an dieser Stelle ohne Probleme.
Kann es sein dass das Problem wegen zwei Clock-Domänen erscheint?
Die ADDR1 wird in 133Mhz-Process gesteuert, ADDR2 in 49,5Mhz-Process.
Die Empty/Voll Bedienung wird außerhalb des Prozesses abgefragt.
Mache ic was falsch hier?
Hier ist der Code:
Lesen @133Mhz
1 | SDRAM_WE_N<='1';
|
2 | RAM2WE2<='0';
|
3 | IF(RAM2FULL='0')THEN---------fill output buffer
|
4 | SDRAM_RE_N<='0';
|
5 | IF(SDRAM_WAIT='0' AND SDRAM_RE_N='0')THEN
|
6 | IF(RAM2FULL_POINTER<511)then-----move full pointer
|
7 | RAM2FULL_POINTER<=RAM2FULL_POINTER+1;
|
8 | else
|
9 | RAM2FULL_POINTER<=0;
|
10 | end if;
|
11 | SDRAM_ADDR<=std_logic_vector(unsigned(SDRAM_ADDR)+1);
|
12 | END IF;
|
13 | ELSE
|
14 | SDRAM_RE_N<='1';
|
15 | END IF;
|
16 |
|
17 | ---RAM2WE1<=SDRAM_RDVAL;
|
18 | IF(SDRAM_RDVAL='1')then------------while data is avalable, write to buffer RAM
|
19 | RAM2IN1<=SDRAM_READDATA(7 downto 0);
|
20 |
|
21 | IF(RAM2ADDR1<511)then
|
22 | RAM2ADDR1<=RAM2ADDR1+1;
|
23 | else
|
24 | RAM2ADDR1<=0;
|
25 | end if;
|
26 |
|
27 | END IF;
|
VGA @49.5 Mhz
1 | IF( RAM2EMPTY='0')then
|
2 | IF(RAM2ADDR2<511)then
|
3 | RAM2ADDR2<=RAM2ADDR2+1;
|
4 | else
|
5 | RAM2ADDR2<=0;
|
6 | end if;
|
7 | RED<=RAM2OUT2;
|
8 | GREEN<=RAM2OUT2;
|
9 | BLUE<=RAM2OUT2;
|
10 | ELSIF( RAM2EMPTY='1')THEN
|
11 |
|
12 | RED<=(others=>'1');
|
13 | BLUE<=(others=>'0');
|
14 | GREEN<=(OTHERS=>'0');
|
15 | END IF;
|
Und außerhalb des Prozesses steht einfach:
RAM2FULL<='1' WHEN RAM2ADDR2=RAM2FULL_POINTER ELSE '0';
RAM2EMPTY<='1' WHEN RAM2ADDR1=RAM2ADDR2 ELSE '0';