Forum: FPGA, VHDL & Co. BRAM wird nicht verwendet


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich will BRAMs verwenden, aber der XST und PAR macht Distributed RAM 
draus. Ich habe mich auch eigentlich an das Mantra gehalten:

"Wenn die Leseadresse getaktet ist, dann gibt es ein synchrones BRAM."

Hier mal der grobe Code:
1
type ram_1024 is array (1023 downto 0) of std_logic_vector(7 downto 0);
2
signal ram_03 : ram_1024;
3
signal ram_04 : ram_1024;
4
5
begin
6
7
process
8
begin
9
   wait until rising_edge(CLK75);
10
11
  if vci_CLK75 = 1 and hci_CLK75 = 1 then
12
    ram_copy_counter_u <= "00000000000";
13
  else
14
    if ram_copy_counter_u < 2047 then
15
      ram_copy_counter_u <= ram_copy_counter_u +1;
16
    end if;
17
  end if;
18
19
  if     (hci_CLK75 >= 270)--279--270
20
    and (hci_CLK75 < 1294)--1304--1294
21
    and (vci_CLK75 > 35)               then
22
    
23
    rai <= (hci_CLK75 - 270); --280
24
    point_new_02 <= to_integer(unsigned(ram_02(rai)));
25
    point_new_03 <= to_integer(unsigned(ram_03(rai)));
26
    point_new_04 <= to_integer(unsigned(ram_04(rai)));
27
  elsif vci_CLK75 < 10 then
28
    if    ram_copy_counter_u(0) = '0' then
29
      ram_copy_buff_02 <= ram_02(to_integer(ram_copy_counter_u(10 downto 1)));
30
      ram_copy_buff_03 <= ram_03(to_integer(ram_copy_counter_u(10 downto 1)));
31
    elsif  ram_copy_counter_u(0) = '1' then
32
      ram_02(to_integer(ram_copy_counter_u(10 downto 1))) <= NEUER_WERT;
33
      ram_03(to_integer(ram_copy_counter_u(10 downto 1))) <= ram_copy_buff_02;
34
      ram_04(to_integer(ram_copy_counter_u(10 downto 1))) <= ram_copy_buff_03;
35
    end if;
36
  end if;

Also ich bekomme Daten von irgendwoher, wo ist hier erstmal vermutlich 
egal, die landen in einem RAM (der kann gerne distributet sein).
Und dann habe ich da ein Bild, also hci_CLK75 und vci_CLK75 sind Zeile 
und Spalte oder anders herum bei 75MHz Pixeltakt, also schön synchron.

Immer wenn ich jetzt im Video_Blank bin, also wenn vci_CLK75 < 35, dann 
möchte ich die Daten aus dem ersten RAM in das nächste RAM kopieren, und 
so weiter.
Ziel sind viele BRAMs, also volles FPGA und zu einem Zeitpunkt geht der 
ram_copy_counter_u (das ist unsigned) nach 0 und es sollen parallel 
immer die Daten aus dem vorherigen RAM in das RAM dahinter kopiert 
werden. Ich mache das in 2 Takten die ich anhand des letzten Bits von 
ram_copy_counter_u unterscheide, ist das '0' wird aus allen RAMs gelesen 
in einen Speicher und ist das '1' soll dieser Speicher in das jeweils 
nächste RAM geschrieben werden.

Wenn dann das Bild da ist, also was angezeigt werden soll, also 
vci_CLK75 > 35, dann ist die horizontale Pixelnummer die Leseadresse, 
also auch wieder getaktet. Da wird dann aus allen RAMs parallel gelesen.

Ich hätte das gerne mit BRAMs und nicht mit distributed RAM, wo ist mein 
Fehler oder woran scheitert das?

Edit:
Was bedeutet denn "Leseadresse getaktet"?

Wenn ich ähnlich wie oben schreibe
1
process
2
begin
3
   wait until rising_edge(CLK75);
4
5
  if vci_CLK75 = 1 and hci_CLK75 = 1 then
6
    ram_copy_counter_u <= "00000000000";
7
  else
8
    ram_copy_counter_u <= ram_copy_counter_u +1;
9
  end if;

Dann kommt kein BRAM raus, schreibe ich aber
1
process
2
begin
3
   wait until rising_edge(CLK75);
4
5
   ram_copy_counter_u <= to_unsigned(hci_CLK75,10);

dann wird es ein BRAM. Wo ist der Unterschied? Beide sind Bitmuster die 
im Takt von den 75MHz synchron geändert werden, das eine ist ein Zähler 
der die Pixel in einer Zeile zählt, das Andere ist nur so ein Zähler der 
auch zurückgesetzt wird synchron. Ich verstehe das nicht.

Vielen Dank!

: Bearbeitet durch User
von Marius S. (lupin) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Warum nimmst du nicht eines von den RAM Templates aus ISE? Ich würde das 
RAM auf jeden Fall über ein separates Entity beschreiben.

Schau dir mal den Block-RAM User-Guide von Xilinx an.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Ja könnte ich machen aber eigentlich erkennt das ja selber wenn man da 
einen BRAM statt Logik verwenden könnte. Und diese RAM Templates die man 
mit dem Coregen erzeugen kann sind halt bei vielen kleinen BRAMs mühsam, 
also da hat man dann lauter Lese- und Schreibadressen und so Zeug das 
man auch vielleicht hübscher so beschreiben könnte.

Auch schön:
Wenn ich da jetzt als Leseadresse die Pixelnummer nehme, dass werden das 
BRAMs, ist auch fein und schön, aber, das sind ja BRAMs, also kommen die 
Daten mit einem Takt Versatz. Jetzt will ich also von dem einen BRAM ins 
Nächste kopieren, da darf ich dann natürlich nicht Leseadresse = 
Schreibadresse verwenden, sondern die Schreibadresse sollte kleiner 
sein.

Ich schreibe also:
1
      ram_02(to_integer(SCHREIBADR)) <= NEUER_WERT;
2
      ram_03(to_integer(SCHREIBADR)) <= ram_02(to_integer(LESEADR));
3
      ram_04(to_integer(SCHREIBADR)) <= ram_03(to_integer(LESEADR));

Wenn SCHREIBADR = LESEADR, dann ist alles fein, also es werden genau so 
viele BRAMS wie ich beschreibe, nur die Daten werden eben nicht dort hin 
geschrieben wo sie hin sollen, sondern mit Versatz kopiert.

Wenn ich SCHREIBADR = LESEADR -1 schreibe, dann werden aus mir 
unbekanntem Grund die BRAMs in die gleichzeitig gelesen und geschrieben 
wird dupliziert (!) also im Beispiel hier wird also ram_02 und ram_03 
doppelt angelegt. Wieso macht das keinen DualportBRAM draus?

von wosnet (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sicher dass das mit dem 'wait until rising_edge' richtig synthetisiert 
wird und zu einem getakteten Block führt?
Von VHDL kenne ich 'wait' eigentlich als delay für Simulationen.
Ein getakteter Prozess sollte doch mit 'if' auf das Ereignis 
(rising_edge oder clk'event o.ä.) abfragen.

Korrigiert mich wenn ich falsch liege, ich mache sonst Verilog.

von Tobias L. (murxwitz)


Bewertung
0 lesenswert
nicht lesenswert
das mit dem "wait until rising_edge(clk)" funktioniert, genauso wie 
falling_edge, ist die zweite Moeglichkeit neben if(rising_edge(clk)), 
man spart sich eine Einrueckebene.

Wieso willst du ueberhaupt als von einem BRAM in den naechsten kopieren? 
Schalte doch einfach einen Multiplexer dahinter und davor und aktiviere 
dann einen BRAM nach dem anderen, wenn du durch bist faengst du einfach 
wieder vorne an.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
@  Tobias L.: Richtig, das wäre die andere Möglichkeit. Das "Problem":
Ich bekomme die Daten in einem anderen Teil mit schnellerem Takt. Beim 
weiterkopieren habe ich nur ein BRAM das beide Takte hat und sonst hat 
jedes BRAM nur einen Takt.

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]
  • [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.