www.mikrocontroller.net

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


Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Balduin T. (balduin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank! Das auf Seite 11 sieht recht übersichtlich und 
unkompliziert aus.

Guten Rutsch nach 2011!

Gustl Buheitel

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Maik Fox (sabuty) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht 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.
architecture Behavioral of ram is

signal c: integer range 0 to 10 := 10;
signal send: std_logic_vector(31 downto 0);
signal buff: std_logic_vector(31 downto 0);

begin

output <= send(7 downto 0);

process begin
    wait until rising_edge(clock);
   if c < 10 then
    c <= c + 1;
   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
     c <= 0;
   end if;
   
   if c = 0 then --1.takt lesen der 1. 16 bits
    ce <= '0';
    oe <= '0';
    wr <= '1';
   elsif c = 1 then --2.takt lesen der 1. 16 bits
    ce <= '1';
    oe <= '1';
    wr <= '1';
    addr <= "00000000000000000001000"; --zum testen mit festen addressen
    buff(15 downto 0) <= data; --1. 16 bits werden in buff gelesen
  -- elsif c = 2 then --1.takt lesen der 2. 16 bits
  --  ce <= '0';
  --  oe <= '0';
  --  wr <= '1';
  -- elsif c = 3 then --2.takt lesen der 2. 16 bits
  --  ce <= '1';
  --  oe <= '1';
  --  wr <= '1';
  --  addr <= "00000000000000000000100";
  --   buff(31 downto 16) <= data; --2. 16 bits werden in buff gelesen
   elsif c = 4 then
    buff <= buff + 1;
   elsif c = 5 then --1.takt schreibens der 1. 16 bits
    send <= buff; --nur zum debuggen gebe ich hier noch buff an send und send auf die leds vom board
    ce <= '0';
    wr <= '0';
   elsif c = 6 then --2.takt schreibens der 1. 16 bits
    ce <= '1';
    wr <= '1';
    addr <= "00000000000000000001000";
    data <= buff(15 downto 0); --1. 16 bits werden von buff in ram geschrieben
  -- elsif c = 7 then --1.takt schreibens der 2. 16 bits
  --  ce <= '0';
  --  wr <= '0';
  -- elsif c = 8 then --2.takt schreibens der 2. 16 bits
  --  ce <= '1';
  --  wr <= '1';
  --  addr <= "00000000000000000000100";
  --  data <= buff(31 downto 16); --2. 16 bits werden von buff in ram geschrieben
   elsif c = 9 then
     buff <= "00000000000000000000000000000000"; --buff null setzen
   end if;
end process;

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

Autor: Gustl Buheitel (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ich bin etwas weiter:

Jetzt wird alle 10000 Takte um 1 hochgezählt.
process begin
    wait until rising_edge(clock);
   if c < 10000 then
    c <= c + 1;
   elsif c = 10000 then
     c <= 0;
   end if;
    
   if c = 0 then
    ce <= '0';
    oe <= '0';
    wr <= '1';
   elsif c = 1 then
    ce <= '1';
    oe <= '1';
    wr <= '1';
    addr <= "00000000000000000010000";
    buff(15 downto 0) <= data;
   elsif c = 2 then
    ce <= '0';
    oe <= '0';
    wr <= '1';
   elsif c = 3 then
    ce <= '1';
    oe <= '1';
    wr <= '1';
    addr <= "00000000000000000001000";
     buff(31 downto 16) <= data;
    
   elsif c = 5 then
    buff <= buff + 1; --buff und send sind 32bit lang
    
   elsif c = 7 then
    send <= buff; --zum debuggen
    ce <= '0';
    wr <= '0';
   elsif c = 8 then
    ce <= '1';
    wr <= '1';
    addr <= "00000000000000000001000";
    data <= buff(31 downto 16);
   elsif c = 9 then
    ce <= '0';
    wr <= '0';
   elsif c = 10 then
    ce <= '1';
    wr <= '1';
    addr <= "00000000000000000010000";
    data <= buff(15 downto 0);
   elsif c = 11 then
    buff <= "00000000000000000000000000000000";
   end if;
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.