Forum: FPGA, VHDL & Co. VHDL RAM mit "krummer" Größe (keine 2er-Potenz)


von Stephan N. (someone_like_you)


Lesenswert?

Hallo alle zusammen!

Ich stehe gerade etwas auf dem Schlauch...

Folgendes Szenario:
Ich habe in meinem hypothetischen FPGA noch 10 RAM-Blöcke mit einer 
breite von je 8-bit und jeweils 1024 Einträgen (=1kB pro Block) übrig 
und möchte die jetzt zusammenfassen und als 'einen' Speicherblock 
nutzen.
Als Address-Signal habe ich ein 14-bit breites Signal - also genug 
Zustände (=16384) um alle 10*1024=10240 Einträge anzusprechen.
Wie konvertiere bzw. addressiere ich jetzt mein RAM-Array ohne dass mir 
die Simulation um die Ohren fliegt??

Definition des RAMs:
1
type ram_t is array (0 to (10*1024)-1) of std_logic_vector(7 downto 0);
2
signal ram      : ram_t;
3
signal addr_int : integer;

Der Lese-Prozess (behavioral, ich möchte keine Primitives explizit 
instantieren):
1
addr_int <= to_integer(unsigned(addr_i(13 downto 0)));
2
3
ram_read : process(clk_i)
4
begin
5
  if rising_edge(clk_i) then
6
    read_data <= ram(addr_int);
7
  end if;
8
end process ram_read;

Ich habe schon versucht mit "range" für das Signal addr_int zu arbeiten 
um den Wertebereich virtuell zu begrenzen, aber ich bekomme in der 
Simulation immer wieder den Fehler "14336 out of bound 0 to 10239" - 
wahrscheinlich weil addr_int durch die Konvertierung des 14-bit Signals 
eben auch größere Werte als 10240 annehmen kann.

Es ist klar, dass das Signal addr_i nicht den Wertebereich von 0 bis 
10239 verlassen darf (was macht das RAM sonst?!), aber was, wenn dieses 
Signal am Anfang nicht initialisiert ist und erst später durch z.B. 
einen Reset auf einen initialen Wert gesetzt wird? Muss ich extra noch 
einen Komparator einbauen um den Wertebereich direkt am Adresseingang 
des RAMs zu begrenzen??

Irgendwie habe ich hier gerade ein Brett vor dem Kopf...
Vielleicht könnt ihr mir ja helfen ;)

Gruss,
Stephan

von user (Gast)


Lesenswert?

du kannst abfragen ob der bereich auserhalb ist und dann don't care 
ausgeben

ram_read : process(clk_i)
begin
  if rising_edge(clk_i) then
    if addr_int < 10239 then
      read_data <= ram(addr_int);
    else
      read_data <= (others => '-');
    end if;
  end if;
end process ram_read;

von Xilinx-Benutzer (Gast)


Lesenswert?

In der Simulation wird entweder Null gelesen oder Unsinn, oder es geht 
wegen der Einschränkung nicht. In der Realität greift der Zugriff ins 
Leere, weil es die ADR nicht gibt. Gelesen wird damit Nichts, gfs der 
alte Wert aus dem vorherigen Zugriff oder ein Defaultwert.

Dies gilt, sofern die Erzeugerroutinen Deine Definition kapieren und das 
RAm überhaupt noch reinquetschen können.

P.S. Kein normaler Mensch baut RAMs /= Potenz(2,x), weil das nur mehr 
Aufwand macht.

von Markus F. (mfro)


Lesenswert?

Ich verstehe das Problem nicht.

Nahezu jedes Gerät mit einem Adress- und Datenbus hat wesentlich mehr 
(mögliche) Adressen als tatsächlich ansprechbare Daten dahinter (ist 
jedenfalls besser als andersrum). Ich wüsste beispielsweise keinen PC 
mit 16 Exbibyte (ha, das Wort wollte ich schon immer mal schreiben).

Da ist es doch völlig unerheblich, ob ansprechbare Adressbereiche 
irgendwie "gerade" oder "ungerade" anfangen/aufhören?

Wenn es für die Anwendung notwendig ist, muss die Steuerlogik eben beim 
Adressieren illegaler Adressbereiche irgendeine Art von Fehler 
(Bus-Error) auslösen. Wenn nicht, dann nicht (Garbage in -> Garbage 
out).

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

Xilinx-Benutzer schrieb:
> P.S. Kein normaler Mensch baut RAMs /= Potenz(2,x), weil das nur mehr
> Aufwand macht.

Unsinn. Die Summe zweier Zweierpotenzen ist z.B. erstaunlich üblich, 
obwohl es selbst keine Zweierpotenz ist. Sowas wie 48 oder 96 KB findet 
man häufiger.

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


Lesenswert?

Stephan N. schrieb:
> Vielleicht könnt ihr mir ja helfen ;)
Ich würde für die Simulation vollkommen unabhängig von der eigentlichen 
RAM-Beschreibung einen Fehler ausgeben:
1
addr_int <= to_integer(unsigned(addr_i(13 downto 0)));
2
assert addr_int<10240 report "RAM Adressbereich verletzt" severity failure;

In der realen Hardware ist das Ergebnis des RAM-Zugriffs ausserhalb der 
Grenzen sowieso spannend und beliebig...

von C. A. Rotwang (Gast)


Lesenswert?

Denk in Hardware, Check "memory banking" und address decoding.

die addressbits die einen von den 10 Ram-primitiven auswählen, gehen 
über einen 1 aus n decoder (wie 74??42) und treiben die einzelnen 
chipselects oder output e-enable der RAM- primitive. Bei nicht tristate 
datenbussen, müßen die Ausgänge noch gemuxt werden.

du brauchst also 2 arrays -> eins für die 2**n Zellen der Ramcomponenten 
und eins für die 0 .. 9 RAM-primitive.

http://research.cs.tamu.edu/prism/lectures/mbsd/mbsd_l16.pdf

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


Lesenswert?

C. A. Rotwang schrieb:
> du brauchst also 2 arrays -> eins für die 2**n Zellen der Ramcomponenten
> und eins für die 0 .. 9 RAM-primitive.
Die Toolchain kann die 14 Adressbits normalerweise locker selbst so 
aufdröseln, dass die unteren 10 Bits der Adresse für die RAM-Adressen 
und die oberen 4 Bit über einen Adressdecoder zur RAM-Selektion 
verwendet werden.

von C. A. Rotwang (Gast)


Lesenswert?

Lothar M. schrieb:
> C. A. Rotwang schrieb:
>> du brauchst also 2 arrays -> eins für die 2**n Zellen der Ramcomponenten
>> und eins für die 0 .. 9 RAM-primitive.
> Die Toolchain kann die 14 Adressbits normalerweise locker selbst so
> aufdröseln, dass die unteren 10 Bits der Adresse für die RAM-Adressen
> und die oberen 4 Bit über einen Adressdecoder zur RAM-Selektion
> verwendet werden.

Auch bei dem "Hypothetischen FPGA" des TO?

Im Zweifelsfall würde ich das nicht der VHDL-Synthese überlassen sodern 
dem Coregenerator o.ä. bspw https://www.youtube.com/watch?v=fbEuQk0-fE4 
Auch Core-generatoren gehören der Toolchain und ersparen einem propitäre 
VHDL-Konstrukte wo Simu und Synthese nicht zusammenpassen. Und in der 
Regel gibt es auch gescheite Doku zu den Modellen, die einem verrät was 
in der Simu in "Grenzbereichen" passiert.

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


Lesenswert?

C. A. Rotwang schrieb:
> Auch bei dem "Hypothetischen FPGA" des TO?
Anscheinend traut er es dessen Toolchain zu.

> Und in der Regel gibt es auch gescheite Doku zu den Modellen
Naja, es sind die selben Bauteile, für die es idR. auch Datenblätter 
gibt. Und auf diese Datenblätter bauen die Simulationsmodelle auch auf.

> Im Zweifelsfall würde ich das nicht der VHDL-Synthese überlassen sodern
> dem Coregenerator
Im Zweifelsfall würde ich die RAM von Hand instantiieren. Dann bleibt 
das Design (trotz des geringeren Abstraktionslevels verglichen mit der 
reinen Verhaltensbeschreibung) immer noch recht leicht portier- und 
parametrierbar.

von C. A. Rotwang (Gast)


Lesenswert?

Lothar M. schrieb:
> C. A. Rotwang schrieb:
>> Auch bei dem "Hypothetischen FPGA" des TO?
> Anscheinend traut er es dessen Toolchain zu.
>
>> Und in der Regel gibt es auch gescheite Doku zu den Modellen
> Naja, es sind die selben Bauteile, für die es idR. auch Datenblätter
> gibt. Und auf diese Datenblätter bauen die Simulationsmodelle auch auf.
>
>> Im Zweifelsfall würde ich das nicht der VHDL-Synthese überlassen sodern
>> dem Coregenerator
> Im Zweifelsfall würde ich die RAM von Hand instantiieren. Dann bleibt
> das Design (trotz des geringeren Abstraktionslevels verglichen mit der
> reinen Verhaltensbeschreibung) immer noch recht leicht portier- und
> parametrierbar.

Der Coregenerator macht auch nix anderes als die RAM zu instanzieren. 
Und mit ner GUI tut man sich m.E. deutlich einfacher beim 
paramtrisieren/verdrahten als jedes mal die GENERIC/Port MAP im 
Libraryguide nachzuschlagen. 
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_2/ug953-vivado-7series-libraries.pdf

Ein CoreGenerator ist halt besser als ich komplexere Speicherstrukturen 
, (insbesonders FIFO mit Flags an unterschiedlichen taktdomainen) 
"zusammenzustricken". Steckt eben mehr KnowHow in dem generator als ein 
Entwickler auf die Schnelle im Schädel hat. Nicht so "elegant" wie 3 
Zeilen VHDL, dafür nicht so fehleranfällig wie elbstgeschriebene 
Modelle.

von J. S. (engineer) Benutzerseite


Lesenswert?

C. A. Rotwang schrieb:
> Ein CoreGenerator ist halt besser als ich komplexere Speicherstrukturen
Sofern er funktioniert :-) Gerade der Xilinx-Coregen, hat mir u.a. bei 
SERDES, DDR3-CTRL (MIG) und sogar bei PLLs oft schon Mist hingeschrieben 
und der Rat des jeweiligen FAEs war, den CoreGen zur Seite zu lassen und 
alles per Hand zu machen.

Trotzdem ist die Nutzung der individuellen Primitive - gerade für 
komplexe DualPort-RAMs - schon der richtige Weg, wenngleich man sich 
dann auf den Hersteller festlegt und das VHDL nicht mehr universell ist. 
Solange es aber nur der Austausch des Xilinx- gegen einen Altera-Wrapper 
ist, macht es nichts. Letztlich muss man das VHDL oft ohnehin auf den 
Hersteller anpassen, weil die RAM-Funktionen nicht 100% austauschbar 
sind.

Zu dem Problem:

Man schränkt eigentlich nur die Adresse ein und überlässt es der 
Synthese, sich was auszudenken. Erst, wenn die nicht greift und es 
vergeigt, wird gestückelt. In Deinem Fall würde Ich die ADR beschränken 
und die Simulation vollständig aufziehen, damit die Einschränkung 
verifiziert und evident ist.

: Bearbeitet durch User
von Stephan N. (someone_like_you)


Lesenswert?

Danke dür die Hinweise soweit!

Ich habe auch schon überlegt mir meinen Speicherblock aus mehreren 
Arrays, die dann wiederum eine 2er-Potenz als Größe haben, zu bauen. 
Also quasi eine "manuelle" Dekodierung der oberen Adressbits zu machen 
und dann den richtigen Block auszuwählen.

Das ganze soll aber generisch sein und nach Möglichkeit eben auch 
Plattform-umabhängig. Und gerade bei der alten Xilinx ISE hatte ich 
immer wieder Probleme mit mehrdimensionalen Arrays als Speicher...

Wie auch immer - ich prüfe jetzt ob der Speicher eine 2er-Potenz als 
Größe hat und falls nicht schalte ich einen Komparator vor, der nur 
gültige Adressen an den Speicher weiter gitb. Ist vielleicht nicht die 
elganteste Möglichkeit, aber funktioniert soweit ganz gut ;)

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.