mikrocontroller.net

Forum: FPGA, VHDL & Co. RAM Initialisierung in VHDL


Autor: Flori K. (jasi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich habe eine Frage zur richtigen RAM Initialisierung in VHDL.
Ich will ein RAM (1024 Bit breit) anlegen, diesem 16 mal 64 Bit Blöcke 
zuweisen und danach wieder ausgeben.
Bei der Simulation klappt alles, bei der Synthese wird aber kein BRAM 
synthetisiert sondern Flip Flops, ich benutze Xilinx ISE 10.1.
Als Fehlermeldung bekomme ich:
INFO:Xst:738 - HDL ADVISOR - 1024 flip-flops were inferred…describe a 
RAM in a way that is incompatible…

Wenn ich den Eingangsvektor „di“ genauso groß wähle wie die RAM breite 
wird BRAM synthetisiert.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ram_test is
      port (clk : in std_logic;
            ce  : in std_logic;
            rst : in std_logic;
            di : in std_logic_vector(63 downto 0);   --(1023 downto 0)  --// zu b.)
            do : out std_logic_vector(63 downto 0)); --(1023 downto 0)  --// zu b.)
end ram_test;

architecture syn of ram_test is
      
      type ram_type is array (0 downto 0) of std_logic_vector (1023 downto 0);      --// zu a.) 
      signal RAM : ram_type;                                                        --// zu a.) 
      
      --type ram_type_2 is array (63 downto 0) of std_logic_vector (1023 downto 0); --// zu b.)
      --signal RAM_2 : ram_type_2;                                                  --// zu b.)
      
      signal counter : integer range -1 to 16;
      signal counter2 : integer range -1 to 16;
      begin
          process (clk)
            begin
                if rising_edge (clk) then
                  if rst ='1' then
                     counter <= 0;
                     counter2 <= 0;
                     elsif ce ='1' then                    
                           if counter >= 0  and counter2 <= 0 then
                              RAM (0)  ((1024-1-(64*counter)) downto (1024-64-(64*counter)))  <= di; --// zu a.) 
                              --RAM_2 (counter)  <= di; --// zu b.)
                              counter <= counter + 1;
                           end if;
                           if counter >= 15 and counter2 >=0 then
                              do <= RAM (0) ((1024-1-(64*counter2)) downto (1024-64-(64*counter2))); --// zu a.) 
                              --do <= RAM_2 (counter2); --// zu b.)
                              counter2 <= counter2 + 1;
                           end if;
                           if counter2 >= 15  then
                              counter <= 0;
                              counter2 <= 0;
                           end if;
                  end if;                            
                end if;    
          end process;         
end syn;

Das XST User Guide hilft mir auch nicht weiter.
Wie löse ich das Problem, ist so etwas überhaupt als BRAM realisierbar?

Gruß
Flori

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muß es nicht heißen :

type ram_type_2 is array (3 downto 0) of std_logic_vector (63 downto 0);

Das ergäbe 16 Zeilen zu je 64 Bit.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denkfehler :

type ram_type_2 is array (15 downto 0) of std_logic_vector (63 downto 
0);

Autor: Flori K. (jasi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich will beim ersten Takt den Adressen 1023 bis 960 einen Wert di 
zuweisen.
Beim nächsten Takt den Adressen 959 bis 896 eine Wert di zuweisen usw…
type ram_type_2 is array (15 downto 0) of std_logic_vector (63 downto
0);
 
Damit erstelle ich ja ein Feld 16 Zeilen a 64 Bit breite.

Ich möchte “nur“ ein RAM mit einer Breite von 1x1024 erstellen.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 16 mal 64 Bit Blöcke
> zuweisen und danach wieder ausgeben.
Warum machst du das den nicht sondern so komisch?
Mach doch einfach ein Ram mit Tiefe 16 und Breite 64 oder was erhoffst 
du dir aus der Beschreibung?

Autor: Flori K. (jasi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte zwei oder mehrere 1024 Bit Vektoren erzeugen, diese dann 
addieren (voneinander subtrahieren usw.), wenn ich den eingelesen Wert 
in verschieden Vektoren Splitte wird das weiterverarbeiten unmöglich.

Das ganze will ich dann auf einem FPGA Board laufen lassen, deswegen 
kann ich nicht einfach ein signal mit beliebiger länge definieren.
Weil dann die vorhanden Ressourcen aufgebraucht werden.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eben, deshalb klappt es wahrscheinlich nicht.
Du definierst ein Ram, das 1 Zeile hat und diese Zeile ist 1024 Bit 
breit.
Das geht mit BlockRam nicht, die maximale Breite ist 32 Bit, obwohl der 
Compiler bei 64 Bit vielleicht auch automatisch 2 BRAM parallel 
verwendet.

Verwende 16 Zeilen zu 64 Bits, dann versteht der Compiler dass das Ram 
in einem 64 Bit breiten Datenpfad angesprochen werden soll und wird 
(hoffentlich) BRAM verwenden.

Oder Du erzeugst Dir dein RAM mit dem Core Generator und bindest es ein. 
Dann bekommst Du vielleicht auch ein Gefühl dafür, über welche 
Datenpfade man es am besten anspricht.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flori K. schrieb:
> Ich möchte zwei oder mehrere 1024 Bit Vektoren erzeugen, diese dann
> addieren (voneinander subtrahieren usw.), wenn ich den eingelesen Wert
> in verschieden Vektoren Splitte wird das weiterverarbeiten unmöglich.
>
> Das ganze will ich dann auf einem FPGA Board laufen lassen, deswegen
> kann ich nicht einfach ein signal mit beliebiger länge definieren.
> Weil dann die vorhanden Ressourcen aufgebraucht werden.

Wenn Du mit den Vektoren rechnen willst, dann kannst Du sie sowieso 
nicht im Block Ram ablegen

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
doofe Frage : wenn man schreibt
 sram_io_3 <= sram_io_1 + sram_io_1; 

ist das dann nicht auch snythetisierbar ohne ein FF dazwischen ?

(jetzt mal unabhängig von der Größe)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, es geht ohne Register.

> sram_io_3 <= sram_io_1 + sram_io_1;
ist funktionell das selbe wie
> sram_io_3 <= sram_io_1 & '0';

Zu klären wäre, wie die Synthese das sieht  ;-)

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm dachte es ist ersichtlich das ich mich verschrieben habe.

gemeint war natürlich :

sram_io_3 <= sram_io_1 + sram_io_2;

so wie Flori das wollte.


das 2 mal der gleiche wert nur mal 2 -> leftshift bedeuted ist klar ;)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> hmm dachte es ist ersichtlich das ich mich verschrieben habe.
Der Synthesizer hätte an dieser falsch getippten Zeile auch nichts 
auszusetzen, und daraus dann die falsch Hardware gemacht. So ersichtlich 
ist dieser Schreibfehler also nicht  :-/

> sram_io_3 <= sram_io_1 + sram_io_2;
Aber auch diese Addition geht ohne Register.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das nicht eine einfache Delayline mit 64 bit?

Wenn Du sicher gehen willst, dass BRAM genommen werden soll, dann nimm 
ihn halt von Hand. (Bei mir hat XST bisher nur versucht reine Logik in 
BRAMs zu packen, aber noch nie FFs mit irgendwelcher Logik drumherum.)

Im Prinzip brauchst du nur deine zwei Zähler aussen und einen 
Zugriffsmechanismus für den BRAM. In meinen Augen die saubere Lösung, 
selbst wenn XST jetzt ein BRAM implementiert und du eine Zeile Code 
nachträglich ändert die wiederum nicht realisierbar wäre, fängt das 
Spiel von Vorne an.

Du hast uns noch nicht verraten welches FPGA von Xilinx du nutzt.
Mit den Instanzierungen RAMB16_S36 könntest Du 32 bit plus Parity 
direkt ansprechen.

Autor: Flori K. (jasi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michael, benutze ein Virtex 4 Board.
Was ich aber dennoch nicht verstehe, ist warum erkennt ISE bei der 
Synthese ein RAM wenn der Eingangsvektor genauso groß ist wie die RAM 
breite.
port (di : in std_logic_vector(1024 downto 0)); 
type ram_type is array (0 downto 0) of std_logic_vector (1023 downto 0);      --// zu a.) 
signal RAM : ram_type; 
  
RAM (0)  <= di; 


Aber wenn ich bei jedem Takt etwas in das RAM schreiben will wird kein 
RAM synthetisiert.
port (di : in std_logic_vector(64 downto 0));
type ram_type is array (0 downto 0) of std_logic_vector (1023 downto 0);     
signal RAM : ram_type;  
 
RAM (0)  ((1024-1-(64*counter)) downto (1024-64-(64*counter)))  <= di; 


Oder wenn das RAM ein Bit größer ist, als der Eingangsvektor wird 
ebenfalls kein RAM bei der Synthese erkannt.
port (di : in std_logic_vector(1023 downto 0));
type ram_type is array (0 downto 0) of std_logic_vector (1024 downto 0);     
signal RAM : ram_type; 
.  
RAM (0) (1023 downto 0)  <= di (1023 downto 0);


Gibt es denn noch andere pdf´s in denen beschrieben ist, wie man RAM 
(BRAM) richtig initialisiert.
Das  XST User Guide und das VHDL Buch von Peter J.Ashenden helfen mir 
nicht wirklich weiter.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil du gleichzeitig lesen und schreiben willst!
Überleg dir einfach wie du ein echtes Ram ansprechen würdest was 1024 
bit breit ist du aber nur 64 bit schreiben willst.

Du könntest aber ein Ram dir generieren lassen was auf der einen Seite 
mit 1024bit gelesen werden kann und auf der anderen mit 64 bit 
geschrieben.
Für mich hat es sich bewährt die RAM beschreibung in eine Seperate 
entity zu stecken und das dann ganz normal als component einzubinden.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie löse ich das Problem, ist so etwas überhaupt als BRAM realisierbar?
Es gibt keine BRAMS mit 1024 Bit Breite. Für eine Verktorbreite von 1024 
müssten 1024/36 = 29 BRAMs parallel geschaltet werden. Hast du so viele?

Das hier:
port (di : in std_logic_vector(1023 downto 0));
type ram_type is array (0 downto 0) of std_logic_vector (1024 downto 0);     
signal RAM : ram_type; 
:  
RAM (0)  <= di;
:
könnte genausogut so geschrieben werden:
port (di : in std_logic_vector(1023 downto 0));
type ram_type is std_logic_vector (1023 downto 0);     
signal RAM : ram_type; 
:  
RAM <= di;
:
oder gleich so:
port (di : in std_logic_vector(1023 downto 0));
signal RAM : std_logic_vector (1023 downto 0); 
:  
RAM <= di;
:
Und dafür brauchst du überhaupt kein RAM.
Lies nochmal den Beitrag "Re: RAM Initialisierung in VHDL"

BTW:
   signal counter : integer range -1 to 16;
   signal counter2 : integer range -1 to 16;
Du hast m.E. offenbar noch grundlegende Probleme mit irgendwelchen 
Randbedingungen.

Deine Ablaufsteuerung sollte besser über ein Zustandssignal geschehen, 
nicht über die Counter.
architecture syn of ram_test is
      
      signal RAM : std_logic_vector (1023 downto 0);   
      signal counter : integer range 0 to 15;
      signal write   : std_logic := '1';
      signal read    : std_logic := '1';
      begin
          process begin
              wait until rising_edge (clk);
              if rst ='1' then
                  counter <= 0;
                  write  <= '1';
                  read   <= '0'; 
              elsif ce ='1' then           
                  -- Schreiben         
                  if write='1' then
                      RAM(1023-(64*counter) downto 1023-63-(64*counter))  <= di;
                  end if;
                  -- Lesen
                  if read = '1' then
                      do <= RAM(1023-(64*counter2) downto 1023-63-(64*counter2));
                  end if;
                  -- Verwaltung
                  if counter < 15  then
                      counter <= counter + 1;
                  else                        -- fertig gezählt
                      counter <= 0;
                      if (write='1) then      -- wenn schreiben fertig:
                           write <= '0';      -- mit lesen weitermachen
                           read  <= '1';
                      end if;
                      if (read='1) then       -- wenn lesen fertig:
                          read  <= '0';       -- ende
                      end if;
                  end if;
              end if;    
          end process;         
end syn;

Insgesamt habe ich den Eindruck, du willst was Einfaches unnötig 
kompliziert machen... :-/

Autor: Flori K. (jasi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke euch allen für die Tipps.
Ich werde mir noch mal das Kapitel über RAM’s im XST genau durchlesen.

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.