Dual Port Ram als Block Ram

OP #7807522
Lesenswert?

Hallo zusammen,

ich möchte in meinem Design ein Dual Port Ram als Block Ram verwenden. Jetzt habe ich aber das Verhalten, dass das Block Ram durch Register ersetzt wird, sobald ich den zweiten Port schreibend hinzunehme.

So sieht die Implementierung aus:

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4

5
entity DualPort_CacheRam is
6
    Port ( clk : in  std_logic;
7
           PortA_Adr : in  std_logic_vector (7 downto 0);
8
        PortA_Din : in std_logic_vector(7 downto 0);
9
        PortA_Dout : out std_logic_vector(7 downto 0);
10
        PortA_we : in std_logic;
11
        PortA_en : in std_logic;
12
        PortB_Adr : in  std_logic_vector (5 downto 0);
13
        PortB_Din : in std_logic_vector(31 downto 0);
14
        PortB_Dout : out std_logic_vector(31 downto 0);
15
        PortB_we : in std_logic;
16
        PortB_en : in std_logic);
17
end DualPort_CacheRam;
18

19
architecture Behavioral of DualPort_CacheRam is
20
  type mem_type is array(0 to 255) of std_logic_vector(7 downto 0);
21
  signal memory : mem_type := (others => "00000000");
22

23
begin
24

25
  process   
26
  begin
27
    wait until rising_edge(clk);
28
    if(PortA_en = '1') then
29
      if (PortA_we='1') then
30
        memory(to_integer(unsigned(PortA_Adr))) <= PortA_Din;    --PortA write operation
31
      else
32
        PortA_Dout <= memory(to_integer(unsigned(PortA_Adr)));  --PortA read operation
33
      end if;
34
    end if;    
35
    
36
    if(PortB_en = '1') then
37
      if(PortB_we = '1') then
38
--        memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "00")) <= PortB_Din(7 downto 0);    
39
--        memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "01")) <= PortB_Din(15 downto 8);
40
--        memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "10")) <= PortB_Din(23 downto 16);
41
--        memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "11")) <= PortB_Din(31 downto 24);
42
      else
43
        PortB_Dout(7 downto 0) <= memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "00"));    
44
        PortB_Dout(15 downto 8) <= memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "01"));    
45
        PortB_Dout(23 downto 16) <= memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "10"));  
46
        PortB_Dout(31 downto 24) <= memory(to_integer(unsigned(PortB_Adr(5 downto 0)) & "11"));  
47
      end if;
48
    end if;
49
  end process;
50

51
end Behavioral;

Sobald ich den Teil unter "if(PortB_we = '1') then" auskommentiere ist nach der Synthese das FPGA komplett voll und er macht das nicht mehr als Block Ram. Wenn ich es weglasse, dann macht die Synthese was sie soll. Muss ich das noch als irgendeine Option mitgeben, dass ich ein Block Ram möchte?

Viele Grüße, Jens

#7807606
Lesenswert?

BRAM:

  • aktualisiert den Leseausgang i.A. auch bei we=1
  • schreibt undefiniert, wenn beide Ports auf dieselbe Adresse schreiben

Dein Code:

  • aktualisiert den Leseausgang nur bei we=0
  • schreibt die Daten von Port B, wenn beide auf dieselbe Adresse schreiben

Ersteres ist evtl. noch kein Problem für die Synthese, zweiteres zwingt die Synthese Register zu nehmen (wenn sie nicht so schlau ist, da noch zusätzliche address collision-Logik einzubauen).

Daher (mindestens) drei Möglichkeiten am Beispiel Xilinx:

OP #7807664
Lesenswert?

Hallo zusammen,

UG901 hat ein bisschen Licht ins Dunkel gebracht. Da muss man deutlich mehr machen, damit das funktioniert. Da muss man mit Funktionen arbeiten und so weiter. Das was ich brauche steht 1:1 drin. Hab ich übernommen und jetzt meckert er, dass da das Ausgangssignal mehrere Treiber hat. Da könnte man sicher den Fehler suchen, aber das artet gleich wieder aus. Ich gehe zurück auf den IP Generator, damit funktioniert es tadellos.

Danke euch!

Grüße, Jens

#7808079
Lesenswert?

Du findest sonst unzaehlige portable TDP-RAM-HDL-Implementierungen im Netz, die mit dem VHDL93-Standard zumindest mit A, L, X und inzwischen auch yosys-unterstuetzten Architekturen korrekt uebersetzen. Bei VHDL08 wirds lustig, da gab es Diskrepanzen bei den Tools, bis zu im Detail inkorrekten Simulationen. Aeussert sich allerdings dann bei Kollisionen und Transparenz-Glitches, aber das wirst du wohl fuer den Anfang nicht brauchen. Wenn du nur mit einem Clock arbeitest und nicht auf beiden Ports schreibst, tut es auch eine einfache Simple-Dualport-Implementierung.

OP #7808183
Lesenswert?

Hi Martin,

ich schreibe schon auf beiden Ports, aber nicht gleichzeitig. Über das Ram übergebe ich Daten zwischen µC und FGPA in beide Richtungen. Die AD-Werte füttert der µC rein und das FPGA rechnet damit den Rest. Das Ergebnis, gibt es dann auch wieder über das Ram zurück.

Für den Rest schau ich mich mal um.

Danke dir!

Grüße

#7809789
Lesenswert?

Dazu hätte ich eine Frage:

Was passiert bei einem true dual port ram, wenn beide Seiten schreiben?

Hier gibt es ein Beispiel von Altera, das so klingt, als sei das intern gemanged. Das kann aber irgendwie nicht sein.

https://www.intel.de/content/www/de/de/support/programmable/support-resources/design-examples/horizontal/vhd-true-dual-port-ram-sclk.html

Was mich daran stört ist die Bezeichung dual port, wo es aber nur einen Takt hat. Nach meiner Erinnerung (ich habe länger nichts mehr mit Altera gemacht) war es aber so, dass das ein true dual port RAM mit zwei unterschiedlichen Takten klarkommt und das oben dargestellte ein "normales" dual port ram ist.

#7809825
Lesenswert?

Bei einem synchronen statischem TDP-RAM (mit zwei unterschiedlichen Clks) lassen sich zwei 'gleichzeitige' (TBD) Writes auf dieselbe Adresse ganz unten in der harten BRAM-Logik abfangen, gibt auch in manchen Architekturen die Option das zu aktivieren. Geht nur auf die Performance. Ansonsten ist der Inhalt der Speicherzelle beliebig korrumpiert, je nachdem wie nahe die Writes zeitlich beeinander sind. Ist allerdings gar nicht so einfach, in der HW etwas deterministisches wie in der Simulation mit exakt verstimmten Clocks zu provozieren. Ansonsten kann man bei einem TDP-RAM natuerlich gleichzeitig auf verschiedene Adressen schreiben. Entweder stellt man mit Gray-Logik sicher, dass die Adressen nie gleich sein koennen, oder nimmt grundsaetzlich eine Pingpong-Buffer-Logik her, wenn die Daten in synchronen Paketen kommen/gehen.

(Firma: Starfleet) #7823573
Lesenswert?

Was passiert bei einem true dual port ram, wenn beide Seiten schreiben?

Naja eine Seite gewinnt. Welche verrät das Handbuch.

Im Handbuch steht "unknown", was letzlich bedeudet, das der FPGA-Designer dafür zu sorgen hat, das dergleichen nicht auftritt, wenn er an einem deterministischen Verhalten interessiert ist.

So wie der Ampel-Programmierer Sorge trägt, das nicht alle an einer Kreuzung "Grün" bekommen.

(Anhang aus http://web.mit.edu/neboat/Public/6.111_final_project/code/blk_mem_gen_ds512.pdf)

Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren