Forum: FPGA, VHDL & Co. Flash oder SDRAM am Nexys2


von Gustl B. (-gb-)


Lesenswert?

Hallo!

Mittlerweile habe ich ein Digilent Nexys2 mit dickerem Spartan3, RS232 
und deutlich mehr IO. Ich kann Spektren aufnehmen und diese per 
Tastendruck über die RS232 an den PC schicken und dort angucken.

So ein Spektrum besteht aus vielen Kanälen und je Kanal 4 Bytes, also 
ein 2D-Array.

Ich bekomme an die IOs ein Bitmuster das dann direkt der Kanalzahl 
entspricht und dort wird um eines nach oben gezählt. Bei derzeit 12 
Eingängen gibt das 4096 Kanäle und dann 16KBytes. Am Ende sollen das 
aber 4096 mal 256 Kanäle werden, also ein anderes Messgerät wird noch 
mit 8 Bit angeschlossen - das wird dann auch ein 2D Array, nur größer 
also 4MBytes.

Und das passt leider nicht mehr in den FPGA.

Jetzt habe ich da auf dem Board allerdings RAM und Flash. Bei dem SDRAM 
steht dabei:

When operated as an asynchronous SRAM, the Cellular RAM automatically 
refreshes its internal DRAM arrays, allowing for a simplified memory 
controller design (similar to any SRAM) in the FPGA.

Und an Einfachheit wäre mir sehr gelegen. Jedoch verstehe ich nicht was 
die ganzen Ports zu bedeuten haben.
Erstmal gibt es einen 24Bit Addressbus und einen 16Bit Datenbus - das 
wären doch dann wenn ich an jeder Addresse 2 Bytes schreiben kann 
(2^24)*2 Bytes oder 32MBytes ?! Laut Boardbeschreibung sind das aber nur 
16 Mbytes. Komisch bzw. verstehe ich nicht.
Dann gibt es MT-UB und MT-LB für das Upper Byte und das Lower Byte - ist 
das auf die 16 Bytes bezogen? Und ist das Upper-Byte dann im Datenbus 15 
downto 8 ?
ChipEnable ist klar, damit kann man zwischen Flash und RAM wechseln - 
aber was ist Output Enable und Write Enable? Bestimmt man damit ob man 
gerade schreibt oder liest?
Und dann gibt es noch MT-CLK, MT-WAIT, address valid (MT-ADV) and 
control register enable (MT_CRE). Wozu brauche ich die?

Ich möchte eigentlich dann jedem Kanal im Spektrum 2 Addressen im Ram 
geben, also 20 Bit habe ich für die Kanäle und da will ich dann beim 
Adressbus 20 downto 1 für den Kanal haben und die 0 ist dann ob es die 
ersten oder die letzten 2 Bytes sind von den 4. Chip Enable bleibt immer 
gleich und beim Schreiben eben WriteEnable und beim Lesen OutputEnable. 
Aber wann wrd denn genau gelesen und geschrieben? Ich würde den nämlich 
gerne wie SRAM betreiben was ja scheinbar geht. Dann brauche ich ja auch 
keinen festen Takt oder?

Also ich legen Adresse und Daten an und setze WriteEnable und 
ChipEnable, wann wird dann wirklich geschrieben? Wenn ich am Takt eine 
steigende Flanke habe oder wenn sie fällt oder sobald das WriteEnable 
gesetzt ist? Oder brauche ich einen Festen Takt? Ich würde nämlich gerne 
jeden neuen Messimpuls als Takt verwenden, also ich sehe in welchem 
Kanal hochgezählt werden muss, lese zuerst was an der Addresse steht, 
zähle eines dazu und schreibe wieder dorthin, oder muss ich das 
irgendwie ganz anders machen mit festem Takt?

Vielen Dank!

Gustl Buheitel

von Max (Gast)


Lesenswert?

Hi

Also zu dem PSRAM kann ich dir nur das Datenblatt ans Herz legen!
Es ist eig. sehr Gut und sacht dir alles was du Wissen willst.
Dazu ein Hinweis, falls du doch mit Bursts Arbeiten solltest, mehr als 
80 Mhz klappt auf jeden Fall nicht.

Für denn Fall das du Interesse daran hast könnte ich dir mal meinen 
Controller für den Ram Hochladen, vllt. Hilft es dir ja!

Gruß Max

von Gustl B. (-gb-)


Lesenswert?

Eigentlich will ich das schon selber bauen, habe aber leider kein 
Datenblatt gefunden.
Wir würde es aber ach reichen wenn mir jemand erklärt wie ich einmal 16 
Bit schreibe und wie ich 16 Bit lese, dann baue ich mir daraus den Rest 
zusammen, am liebsten wäre mir eben möglichst ohne festen Takt und schön 
einfach^^

Und was jetzt zwar total OT ist, aber mich sehr viel Zeit gekostet hat:
Wenn ich das Nexys2 per USB mit dem Rechner verbinde (nur für Strom, 
Bitstream ligt im ROM) und dann versuche über RS232 überzulesen geht 
sehr oft etwas schief und das Nexys2 übermittelt zu wenige Bytes. 
Schließe ich allerdings ein Netzteil an und kein USB für Strom, so 
funktioniert es immer super. Ich weiss nicht woran es liegt, aber es hat 
mich sehr irritiert weil ich dachte mein Modul sei schlecht (was es 
vielleicht auch trotzdem ist).

Gustl Buheitel

von Balduin T. (balduin)


Lesenswert?


von Gustl B. (-gb-)


Lesenswert?

Vielen Dank! Das auf Seite 11 sieht recht übersichtlich und 
unkompliziert aus.

Guten Rutsch nach 2011!

Gustl Buheitel

von Duke Scarring (Gast)


Lesenswert?

Gustl Buheitel schrieb:
> RS232 überzulesen geht
> sehr oft etwas schief und das Nexys2 übermittelt zu wenige Bytes.
> Schließe ich allerdings ein Netzteil an und kein USB für Strom, so
> funktioniert es immer super. Ich weiss nicht woran es liegt,

Das Board erzeugt möglicherweise die für RS232 nötigen negativer 
Spannungen nicht, wenn es nur über USB angeschlossen ist. Gewissheit 
schafft da ein Blick in den Schaltplan.

Duke

von Gustl B. (-gb-)


Lesenswert?

Wow, dieser RAM ist ziemlich einfach anzusprechen, gut vielleicht nicht 
besonders hybsch, aber wenn man nur Daten rein und rausbringen will, 
dass geht das erstaunlich einfach. Super!

Gustl Buheitel

von Maik F. (sabuty) Benutzerseite


Lesenswert?

Achtung bei der Verwendung des SDRAMs auf dem Nexys2, ich bin da 
schonmal reingefallen:

Es gibt im UCF-File den Anschluss MemAdr(0) nicht!

Kontext siehe: Beitrag "Re: ISE Schematic: nur ein Bit von UCF-Bus verwenden"

von Gustl B. (-gb-)


Lesenswert?

Danke! Wobei eigentlich ist das doch ok so.

Laut Beschreibung sind das 16 MBytes an RAM. Und wenn ich jetzt 24 Bit 
habe und an jede Addresse 2 Bytes speichern kann wären es doch (2^24)*2 
Bytes, und das dann durch 2^10 also 32 768 KBytes - also das Doppelte. 
Lässt man jetzt genau ein Addressbit weg, dann passt es?! Oder sehe ich 
da was falsch?
Gut ich brauche sowieso nur 21 Addressbits für die 4Mbytes.

Aber komisch, dass ich hier 24 Bit Addressen vergeben kann und das 
anstandslos funktioniert ...

Gustl Buheitel

von Gustl B. (-gb-)


Lesenswert?

So hallo nochmal, ich habe wieder ein Problem:

Ihc habe ja im Spektrum in jedem Kanal 32Bit, also 4Bytes und brauche 
dazu nun jeweis 2 Speicheraddressen.
Eine Funktion ist, dass während der Messung in dem jeweiligen Kanal zu 
dem der Impuls gehört um eines nach oben gezählt wird.
Also habe ich einen 32bit Puffer und zuerst werden die einen 16Bit in 
den Puffer (15 downto 0) gelesen, dann die anderen in (31 downto 16), 
dann wird Puffer <= Puffer + 1 gemacht und dann wird er wieder 
geschrieben.
Aber das will irgendwie nicht. Mit 16 Bit geht es problemlos, aber mit 
jeweils 2 Schreib und Lesezugriffen geht es nicht.
1
architecture Behavioral of ram is
2
3
signal c: integer range 0 to 10 := 10;
4
signal send: std_logic_vector(31 downto 0);
5
signal buff: std_logic_vector(31 downto 0);
6
7
begin
8
9
output <= send(7 downto 0);
10
11
process begin
12
    wait until rising_edge(clock);
13
   if c < 10 then
14
    c <= c + 1;
15
   elsif c = 10 and do = '1' then --do ist ein signal aus einer anderen Einheit, und immer wenn do mal kurz 1 war soll also um eines in der 32 bit zahl hochgezählt werden
16
     c <= 0;
17
   end if;
18
   
19
   if c = 0 then --1.takt lesen der 1. 16 bits
20
    ce <= '0';
21
    oe <= '0';
22
    wr <= '1';
23
   elsif c = 1 then --2.takt lesen der 1. 16 bits
24
    ce <= '1';
25
    oe <= '1';
26
    wr <= '1';
27
    addr <= "00000000000000000001000"; --zum testen mit festen addressen
28
    buff(15 downto 0) <= data; --1. 16 bits werden in buff gelesen
29
  -- elsif c = 2 then --1.takt lesen der 2. 16 bits
30
  --  ce <= '0';
31
  --  oe <= '0';
32
  --  wr <= '1';
33
  -- elsif c = 3 then --2.takt lesen der 2. 16 bits
34
  --  ce <= '1';
35
  --  oe <= '1';
36
  --  wr <= '1';
37
  --  addr <= "00000000000000000000100";
38
  --   buff(31 downto 16) <= data; --2. 16 bits werden in buff gelesen
39
   elsif c = 4 then
40
    buff <= buff + 1;
41
   elsif c = 5 then --1.takt schreibens der 1. 16 bits
42
    send <= buff; --nur zum debuggen gebe ich hier noch buff an send und send auf die leds vom board
43
    ce <= '0';
44
    wr <= '0';
45
   elsif c = 6 then --2.takt schreibens der 1. 16 bits
46
    ce <= '1';
47
    wr <= '1';
48
    addr <= "00000000000000000001000";
49
    data <= buff(15 downto 0); --1. 16 bits werden von buff in ram geschrieben
50
  -- elsif c = 7 then --1.takt schreibens der 2. 16 bits
51
  --  ce <= '0';
52
  --  wr <= '0';
53
  -- elsif c = 8 then --2.takt schreibens der 2. 16 bits
54
  --  ce <= '1';
55
  --  wr <= '1';
56
  --  addr <= "00000000000000000000100";
57
  --  data <= buff(31 downto 16); --2. 16 bits werden von buff in ram geschrieben
58
   elsif c = 9 then
59
     buff <= "00000000000000000000000000000000"; --buff null setzen
60
   end if;
61
end process;
62
63
end Behavioral;

Ja so wie das da ist geht es auch, nur wenn ich das Auskommentierte 
nicht auskommentiere, also jeweils 2 Lese und Schreibzugriffe habe, dann 
geht es nicht mehr - warum?

Gustl Buheitel

von Gustl B. (-gb-)


Lesenswert?

So ich bin etwas weiter:

Jetzt wird alle 10000 Takte um 1 hochgezählt.
1
process begin
2
    wait until rising_edge(clock);
3
   if c < 10000 then
4
    c <= c + 1;
5
   elsif c = 10000 then
6
     c <= 0;
7
   end if;
8
    
9
   if c = 0 then
10
    ce <= '0';
11
    oe <= '0';
12
    wr <= '1';
13
   elsif c = 1 then
14
    ce <= '1';
15
    oe <= '1';
16
    wr <= '1';
17
    addr <= "00000000000000000010000";
18
    buff(15 downto 0) <= data;
19
   elsif c = 2 then
20
    ce <= '0';
21
    oe <= '0';
22
    wr <= '1';
23
   elsif c = 3 then
24
    ce <= '1';
25
    oe <= '1';
26
    wr <= '1';
27
    addr <= "00000000000000000001000";
28
     buff(31 downto 16) <= data;
29
    
30
   elsif c = 5 then
31
    buff <= buff + 1; --buff und send sind 32bit lang
32
    
33
   elsif c = 7 then
34
    send <= buff; --zum debuggen
35
    ce <= '0';
36
    wr <= '0';
37
   elsif c = 8 then
38
    ce <= '1';
39
    wr <= '1';
40
    addr <= "00000000000000000001000";
41
    data <= buff(31 downto 16);
42
   elsif c = 9 then
43
    ce <= '0';
44
    wr <= '0';
45
   elsif c = 10 then
46
    ce <= '1';
47
    wr <= '1';
48
    addr <= "00000000000000000010000";
49
    data <= buff(15 downto 0);
50
   elsif c = 11 then
51
    buff <= "00000000000000000000000000000000";
52
   end if;
53
end process;

Aber: jetzt ist in den oberen 16 Bits von send immer das Selbe wie in 
den unteren?! Ich finde das sehr komisch, weil es sind unterschiedliche 
Speicheraddressen und außerdem wird bei buff <= buff + 1 doch der ganze 
buff also die 32 bit Zahl um 1 hochgezählt. Und nicht zweimal in den 
oberen und unteren 16 bits.
Oder geht das eleganter oder wie überhaupt dass es funktioniert?

Gustl Buheitel

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.