Hallo!
Da der andere Thread wohl ein irreführendes Topic hat frage ich hier
nochmal.
Also ich habe das Nexys2 mit SDRAM von Micron der sich auch als SRAM
betreiben lässt.
http://download.micron.com/pdf/datasheets/psram/128mb_burst_cr1_5_p26z.pdf
Und da ich ein Spektrum im SRAM speichere will ich auch gleich in den
einzelnen Kanälen des Spektrum im SRAM hochzählen.
Nun ist jedoch jeder Kanal 4Bytes groß und braucht so 2 Addressen im Ram
an denen jeweis dann 16 Bits stehen.
Wenn ich also in einem Kanal um eines nach oben zählen möchte, dann lese
ich zunächst beide Addressen in eine 32Bit Variable, erhöhe diese, und
schreibe danach diese Variable wieder in den RAM.
Das ist ein Leseteil der an einer Addresse 16 Bit liest:
1
ifc=0then--c ist ein zähler der von der clock hochgezählt wird
2
ce<='0';--chipenable
3
oe<='0';--outputenable
4
wr<='1';--writeenable
5
elsifc=1then
6
ce<='1';
7
oe<='1';
8
wr<='1';
9
addr<="00000000000000000010000";--hier noch mit einer festen addresse
10
buff(15downto0)<=data;--daten werden in buff gelesen
Und das geht auch, da wird nach je 10000 Takten an der Speicheraddresse
um eines hochgezählt:
Jedoch wenn ich jetzt jeweils zwei Lese und Schreibzugriffe mache, dann
ist in buff(31 downto 16) und in buff(15 downto 0) immer dasselbe
drinnen?! Bzw. was ich mir angucke also in send(31 downto 16) und in
send(15 downto 0).
1
processbegin
2
waituntilrising_edge(clock);
3
ifc<10000then
4
c<=c+1;
5
elsifc=10000then
6
c<=0;
7
endif;
8
9
ifc=0then
10
ce<='0';
11
oe<='0';
12
wr<='1';
13
elsifc=1then
14
ce<='1';
15
oe<='1';
16
wr<='1';
17
addr<="00000000000000000010000";
18
buff(15downto0)<=data;
19
elsifc=2then
20
ce<='0';
21
oe<='0';
22
wr<='1';
23
elsifc=3then
24
ce<='1';
25
oe<='1';
26
wr<='1';
27
addr<="00000000000000000001000";
28
buff(31downto16)<=data;
29
30
elsifc=5then
31
buff<=buff+1;--buff und send sind 32bit lang
32
33
elsifc=7then
34
send<=buff;--zum debuggen
35
ce<='0';
36
wr<='0';
37
elsifc=8then
38
ce<='1';
39
wr<='1';
40
addr<="00000000000000000001000";
41
data<=buff(31downto16);
42
elsifc=9then
43
ce<='0';
44
wr<='0';
45
elsifc=10then
46
ce<='1';
47
wr<='1';
48
addr<="00000000000000000010000";
49
data<=buff(15downto0);
50
elsifc=11then
51
buff<="00000000000000000000000000000000";
52
endif;
53
endprocess;
Das ist der Code der nicht geht - man kann es vielleicht auch so sehen,
dass in jeder der beiden Speicheraddressen synchron hochgezählt wird -
aber warum? Was mache ich falsch? Oder spreche ich den RAM falsch an?
Aber das mache ich eigentlich wie in dem PDF auf Seite 11 und es klappt
ja auch für jeweils einen Zugriff.
Nein - was ist das überhaupt? Bzw. ja vermutlich etwas wo man das dann
simuliert, das ging mit Altera Quartus recht einfach aber jetzt mit ISE
stehe ich da ziemlich ratlos in der Landschaft. Das Meiste geht zum
Glück ja auch so irgendwie.
Kann man denn so eine Testbench einfach machen oder ist das ein großer
Aufwand?
Edit:
Was hat es eigentlich mit inout zu tun? Bei mir sind die Daten zum und
vom RAM inout. Die werden beim Schreiben auch mit data <= buff(15 downto
0);
zugewiesen - muss man das vor dem Lesen irgendwie wieder Rückgängig
machen?
Denn scheinbar wird immer nur genau das gelesen (unabhängig der
Speicheraddresse) was ich zuletzt in den RAM geschrieben habe.
Gustl Buheitel
> Was hat es eigentlich mit inout zu tun? Bei mir sind die Daten zum und> vom RAM inout. Die werden beim Schreiben auch mit data <= buff(15 downto> 0); zugewiesen - muss man das vor dem Lesen irgendwie wieder Rückgängig> machen?> Denn scheinbar wird immer nur genau das gelesen (unabhängig der> Speicheraddresse) was ich zuletzt in den RAM geschrieben habe.
Uiuiui.... ja, das MUSS man unbedingt machen, und zwar indem man einen
dem Port einen Vektor von 16 z-Werten zuweist (z = "tristate", nur bei
inout gültig und bedeutet soviel wie "nichts ausgeben, sondern
reinlesen").
Machst du das nicht, dann gibtst du Werte auf die externe Leitung
während der RAM das auch macht. Intern im FPGA "siehst" du dann die
Werte, die du selbst ausgibst, genau wie du es beschreibst. Aber außen
raucht's: Wenn der FPGA und der RAM versuchen, auf einer Leitung
verschiedene Werte auszugeben (z.B. der FPGA eine 1, der RAM eine 0),
dann ist das ein elektrischer Kurzschluss, nur beschränkt durch den
Widerstand der Leitung und die Limits der I/O-Treiber.
Ich würde sagen: Prüf mal, ob die Chips dabei heiß werden. "Würde", wenn
ich dir nicht dringend davon abraten würde, die Schaltung so nochmal
anzuwerfen ;)
Gustl Buheitel schrieb:> Nein - was ist das überhaupt? Bzw. ja vermutlich etwas wo man das dann> simuliert,
Eine Testbench ist ein VHDL-Modul, das keinen Port nach aussen hat. In
dieses VHDL-Modul wird deine VHDL-Beschreibung als Komponenten
eingebunden. Und dann kannst du den Simulator laufen lassen und dir im
einfachsten Fall die Waveform ansehen.
Gustl Buheitel schrieb:> Kann man denn so eine Testbench einfach machen oder ist das ein großer> Aufwand?
Unter ISE ist das simpel:
Rechtsclick in den Project-Baum
dann "New Source" --> Testbench
und dann wird dir das Gerüst der TB schon mal angelegt.
Sieh dir dazu mal das an:
http://www.lothar-miller.de/s9y/archives/60-RS232-IO.html#extended
Darin findest du eine simple RS232-IO und die Testbench dazu. Damit
dürfte die Idee klar werden. Das schöne an der TB:
da darfst du endlich mal alle Sprachelemente von VHDL verwenden.
Insbesondere das "wait for xx ns"... ;-)
> z = "tristate"
Gerade hier ist VHDL ziemlich penibel und beharrt auf das große 'Z',
denn genauso ist der Typ std_logic definiert:
type STD_ LOGIC is (
'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- don’t care
);
Das dürfte dir evtl. weiterhelfen:
Beitrag "Wie erstelle ich in VHDL Bidirektionalen Datenbus?"
Vielen Dank erstmal, das mit dem Z ist einleuchtend und die
verschiedenen Zustände von STD_LOGIC kannte ich überhaupt nicht.
Diese Testbench also wie man die aufmacht und so habe ich jetzt auch
geschafft, allerdings kann er bei mir nicht simulieren und stolpert über
Dinge die sonst super funktionieren. Gibt es denn einen Trick wie ich
nur eine Entity simulieren kann? Also ohne dass die anderen überhaupt
angeguckt werden?
Genauer bricht er bei
x <= to_integer(unsigned(input));
ab - was allerdings sonst funktioniert.
Gustl Buheitel
Gustl Buheitel schrieb:> Genauer bricht er bei> x <= to_integer(unsigned(input));> ab - was allerdings sonst funktioniert.
Was stört ihn daran?
Hast du die numeric.std nicht eingebunden?
Gustl Buheitel schrieb:> Ähm ... muss ich mich eigentlich genau an das halten was hier> http://download.micron.com/pdf/datasheets/psram/12...> auf den Seiten 42/51 steht? weil ich hab das jetzt so wie auf Seite 11,> und da gibt es doch große Unterschiede.
Nein, eigentlich sind da keine Unterschiede.
Nur fehlt auf der Seite 11 jeglicher exakte Zeitbezug. Das ist quasi ein
"Übersichtsplan" für den Zugriff. Du solltest einfach mal die
Timingwerte genauer anschauen und du wirst sehen, dass die Seite 11
einfach nur idealisiert (und vereinfacht) dargestellt ist.
> Ähm ... muss ich mich eigentlich genau an das halten was hier> http://download.micron.com/pdf/datasheets/psram/12...> auf den Seiten 42/51 steht?
Ja.
Er schreibst:
Multiple declarations of unsigned included via multiple use clauses;
none are made directly visible
und ok gut ... dann wird das doch aufwändiger. Aber man kann das schon
so machen dass man das so seriell abarbeitet, also in 50 Takten oder so
und dann in jedem Takt genau schreibt was an den RAM geht?
Ist nur doof, weil ein Takt der 50MHZ Clock ist 20ns lang, und wenn ich
da jetzt Timing Sachen habe die drunter liegen, dann geht das nicht, und
auch, dass in der Timing Grafik das Wait vorkommt und UB/LB einmal '1'
sein muss finde ich komisch, aber ok, werde ich einbauen.
Gustl Buheitel
Gustl Buheitel schrieb:> Multiple declarations of unsigned included via multiple use clauses;> none are made directly visible
Welche libs sind am Anfang der TB eingebunden?
Da würde mich der Code der TB schon interessieren...
Ah! Ok also ich hatte bei der TB das ganze Projekt ausgewählt. Jetzt hab
ich mal nur die Entity RAM genommen und da geht es dann ... wunderbar!
Dann versuche ich also hier genau das Timingdiagramm nachzubilden.
Gustl Buheitel schrieb:> Dann versuche ich also hier genau das Timingdiagramm nachzubilden.
Nein, du solltest das nicht nachbilden sondern einfach nur
verstehen...
Bei manchen Signalen ist es schlicht egal, wann sie kommen, das siehst
du aber nicht in irgendeinem Bild, sondern nur, wenn du die
Zahlenwerte mit einbeziehst.
Ja ... aber ich will doch mit dem RAM reden können?! Klar dass manche
Signale Spielraum haben oder auch dauerhaft '0' sein können, aber
zumindest ungefähr muss ich das doch so nachbauen - die Toleranz gibt es
ja in der Timingtabelle. Oder geht das ganze deutlich einfacher? Also
so, dass man nur sehr wenig beachten muss?
Diese Simulation ist auch sowas, da sehe ich zwar jetzt die ganzen
Signale, aber die bleiben immer gleich weil sich meine Clock da nie
ändert?! Muss ich da irgendwie selbst einen Takt reinmalen oder wie
funktioniert das?
Gustl Buheitel schrieb:> Muss ich da irgendwie selbst einen Takt reinmalen oder wie> funktioniert das?
Nein, du mußt in der Testbench einen Takt generieren. Der Link vom
Beitrag "Re: 32Bit Zähler in SRAM" zeigt dir wie das
geht. Z.B. so:
Ok Danke! Also eigentlich sollte es simulieren, jedoch schnappt sich der
ISim erstmal recht schnell den kompletten RAM (2gb) und dann über eine
Stunde hinweg noch noch allmählich weitere 300MB und kratzt auf der
Platte rum wie verrückt um mir jetzt zu präsentieren:
The simulator has terminated in an unexpected manner.
Immerhin geht das SRAM anprechen so halbwegs, ich weiss zwar noch nicht
wie ich das richtig mache, aber mit vielen Schreib und Lesefehlern kann
man jetzt erkennen, dass da eine 32Bit Zahl hochzehählt wird (weil es
auf den niedrigeren Bits deutlich schneller blinkt wie auf den oberen).
So also es geht alles wie es soll.
Zuerst hate ich ja noch keinen RAM. Da hatte ich das Spektrum im FPGA
als Array und das war mangels Platz auch kleiner und ich konnte das über
RS232 rausschieben. Das war 4KByte und ich hatte erstmal Probleme das
komplett über RS232 rauszubekommen - bis ich dann das Board nicht über
USB sondern über Netzteil angeschlossen hatte.
So da war der RS232 am Rechner (weil der Laptop kein RS232 hat) ein USB
Adapter (USB-Serial CH340). Und mit dem hat das auch bei 4KBytes gut
geklappt.
Jetzt ist mein Spektrum größer (16Kbytes und nochmal 4Mbytes), der Code
für RS232 ist gleich geblieben. Und es ging nicht mehr, es fehlen dann
einfach einzelne Bytes.
Wenn ich das aber hier an einen alten Dell Optiplex Tower Rechner
anschließe mit richtiger RS232, dann geht alles super - auch 4MBytes
(dauert aber 8 Minuten).
Also wenn Jemand Probleme mit RS232 und vielen Daten hat dann kann auch
so ein USB Adapter schuld sein.
Gustl