www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Xilinx FPGA: Organisation des BlockRAM


Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine kurze Frage zu Xilinx BlockRAM im Spartan 3E:
Wie wird ein BlockRAM mit Speicherbreite 4Bit umgesetzt? Werden trotzdem 
8Bit verwendet, der Rest ist einfach nicht benutzt oder wird ein 
"echtes" 4Bit RAM erstellt?
Wäre auch ein 1Bit RAM möglich?

Sowas stelle ich mir vor:
entity RAM_4Bit_ is
  port (
    ADDR  : in  std_logic_vector(9 downto 0); -- Address
    DI    : in  std_logic_vector(3 downto 0); -- Data in
    DO    : out std_logic_vector(3 downto 0); -- Data out
    clk   : in std_logic;                     -- Clock
    WE    : in std_logic;                     -- Write Enable
    CE    : in std_logic                      -- Chip Enable
  );
end RAM_4Bit;
 
architecture RAM_4Bit_arch of RAM_4Bit is
  type ram_type is array (9 downto 0)
                   of std_logic_vector (3 downto 0);
  signal RAM : ram_type := (others => "0000");
begin
  process (clk)
  begin
    if (rising_edge(clk)) then
      if (CE = '1') then
        if (WE = '1') then
          RAM(to_integer(ADDR)) <= DI;
        end if;
        DO <= RAM(to_integer(ADDR));
      end if;
    end if;
  end process;
end RAM_4Bit_arch;

Danke für die Antworten.
Gruss, Martin Kohler

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann klick doch mal auf Synthesize und gucke, was rauskommt:
Loading device for application Rf_Device from file '4vlx15.nph' in environment ...
INFO:Xst:2452 - Unit <RAM_4Bit> : The small RAM <Mram_RAM> will be implemented on LUTs in order to maximize performance and save block RAM resources. If you want to force its implementation on block, use option/constraint ram_style.
    -----------------------------------------------------------------------
    | ram_type           | Distributed                         |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 10-word x 4-bit                     |          |
    |     clkA           | connected to signal <clk>           | rise     |
    |     weA            | connected to signal <WE_0>          | high     |
    |     addrA          | connected to signal <ADDR>          |          |
    |     diA            | connected to signal <DI>            |          |
    |     doA            | connected to internal node          |          |
    -----------------------------------------------------------------------

Das Ergebnis ist (teilweise) vom Device abhängig.

Duke

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

Bewertung
0 lesenswert
nicht lesenswert
> wird ein "echtes" 4Bit RAM erstellt?
Ja.
Allerdings werden bei deinem BRAM je nach FPGA einige Bits nicht 
verwendet. Du brauchst nur 4096 Bits, ein BRAM eines S3 hat 18kBit, d.h. 
du verwendest nur 1/4 davon (die unbenutzen Adressen werden einfach auf 
0 gelegt).

> Wäre auch ein 1Bit RAM möglich?
Ja. Steht in der XAPP463.

Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke euch beiden für die Antworten.
Ich werde mal die AppNote studieren.
(ich wusste, dass sicher eine zum Thema bestehen muss, habe sie aber 
nicht gefunden)

Martin

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Speicher enthält übrigens nur 10 Elemente:
type ram_type is array (9 downto 0) ...

Wolltest Du das?

Oder doch eher so?!:
type ram_type is array (0 to 2**ADDR'length-1) ...

Duke

Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring wrote:
> Dein Speicher enthält übrigens nur 10 Elemente:
> Oder doch eher so?!:
>
> type ram_type is array (0 to 2**ADDR'length-1) ...
> 
Du hast recht, natürlich!

Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anschlussfrage:
Ist es auch möglich, ein RAM zu erstellen, welches auf der einen Seite 
2^9x32Bit organisiert ist, auf der anderen Seite 2^14*1Bit ?

Meine bisherigen Abklärungen deuten auf ein "Nein" hin.

Der Workaround wäre dann wohl: auch auf der zweiten Seite mit einer 
grösseren Datenbreite zugreifen und die Bits mit nachgeschalteter Logik 
decodieren.

Martin

Autor: Christian R. (supachris)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Zumindest kann man es im Core Generator bei Xilinx einstellen. Sollte 
also klappen.

Autor: Morin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Anschlussfrage:
> Ist es auch möglich, ein RAM zu erstellen, welches auf der einen Seite
> 2^9x32Bit organisiert ist, auf der anderen Seite 2^14*1Bit ?

Ja. Ich habe selbst schon mit einem RAM gearbeitet, welches auf der 
einen Seite als 2k*16 Bits und auf der anderen Seite als 1k*32 Bits 
organisiert war. Bis auf die konkreten Zahlen habe ich also "genau das" 
schon gemacht.

Autor: Morin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: Dieser RAM wurde problemlos auf 2 BlockRAMs abgebildet (die 
Zahl 2 hier wegen der Gesamtgröße 4kB, nicht wegen der zwei 
Zugriffsmodi).

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

Bewertung
0 lesenswert
nicht lesenswert
Das geht aber glaub ich nur wenn die eine Seite eine ganzzahlige 
Vielfache einer zweierpotenz ist und hängt ggf auch vom Chip ab, ich 
würd einfach mal schauen was der Coregenerator sagt.

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

Bewertung
0 lesenswert
nicht lesenswert
> 2^9x32Bit organisiert ist, auf der anderen Seite 2^14*1Bit ?
> Meine bisherigen Abklärungen deuten auf ein "Nein" hin.
Ich meine die XAPP463 auch so interpretieren zu können :-/

> Der Workaround wäre dann wohl: auch auf der zweiten Seite mit einer
> grösseren Datenbreite zugreifen
Das Problem ist nicht die Seite mit 1 Bit. Es geht um die Breitseite :-o
Es gibt kein RAMB16_S1_S32, mit dem ein direktes Ummappen möglich wäre.
Es gibt nur einen RAMB16_S1_S36, also 1 Bit auf der einen, 36 bit auf 
der anderen Seite :-/
Wenn ich z.B. auf der 1-Bit Seite an Adresse 0 etwas schreibe, kommt das 
an der breiten Seite an Adresse 0 Bit 0 heraus.
Wenn ich auf auf der 1-Bit Seite an Adresse 31 etwas schreibe, kommt das 
an der breiten Seite auf Adresse 0 Bit 31 heraus.
Wenn ich jetzt aber auf auf der 1-Bit Seite an Adresse 32 etwas 
schreibe, und bei einem 32-Bit Wort dann die Adresse 1 Bit 0 erwarten 
würde, kommt das am BRAM an der breiten Seite auf Adresse 0 Bit 32 
heraus.

D.h. das BRAM kann nicht einfach als 1-->32 Bit-Buskonverter verwendet 
werden. Eine Möglichkeit wäre jetzt, beim Schreiben auf der 1-Bit-Seite 
die Adresse so zu manipulieren, dass auf der 36-Bit-Seite die Bits 
35..32 nicht beschrieben werden.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht doch:

RAMB16_S1_S36 ist genau das, was Du brauchst:
an den Bits 0..31 (DOA(31 downto 0) oder DOB(31 downto 0))
liegen genau die 32 'eingeschriebenen' Bits

Bits 32..35 (DOPA(3 downto 0) oder DOPB(3 downto 0) einfach
'open' lassen

Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> RAMB16_S1_S36 ist genau das, was Du brauchst:

Sieht gut aus.
Wie verwende ich dieses Konstrukt nun konkret in meinem VHDL Code?
Kann mir da jemand evtl. ein Beispiel zeigen?

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

Bewertung
0 lesenswert
nicht lesenswert
> Wie verwende ich dieses Konstrukt nun konkret in meinem VHDL Code?
Das sieht gut aus:
http://www.te.rl.ac.uk/esdg/cms-fed/xilinx-fpgas/v...

Autor: Martin Kohler (mkohler)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller wrote:
> Das sieht gut aus:
Tut es, ja.

Ich binde also das Dual Port RAM also als "component" ein:
component RAMB16_S1_S36 
  port (
  DIA     : in std_logic_vector (0 downto 0);
  ADDRA   : in std_logic_vector (13 downto 0);
  ENA     : in std_logic;
  WEA     : in std_logic;
  SSRA    : in std_logic;
  CLKA    : in std_logic;
  DOA     : out std_logic_vector (0 downto 0);

  DIB     : in std_logic_vector (31 downto 0);
  DIPB    : in std_logic_vector (3 downto 0);
  ADDRB   : in std_logic_vector (8 downto 0);
  ENB     : in std_logic;
  WEB     : in std_logic;
  SSRB    : in std_logic;
  CLKB    : in std_logic;
  DOB     : out std_logic_vector (31 downto 0);
  DOPB    : out std_logic_vector (3 downto 0)  
  ); 
end component;

und verwende das Teil in der üblichen Art als Instanz:
U_RAMB16_S1_S36: RAMB16_S1_S36
  port map (
  DIA     => X, -- insert 1 bit data in bus (<0 downto 0>)
  ADDRA   => Y, -- insert 14 bits address bus
  ENA     => Z, -- insert enable signal
  ...

Soweit, so gut.
Welche RAM Konfigurationen möglich sind, entnehme ich der AppNote 463, 
Seite 10, Tabelle 7 (Bild im Anhang)

Woher nehme ich nun aber die Port Beschreibung? Muss ich mir diese aus 
einem Beispiel kopieren oder sind die Port Maps für die einzelnen 
Konfigurationsvarianten irgendwo abrufbar?
Aus dem Datenblatt zusammenklauben erscheint mir etwas mühsam...

Danke für die bisherigen Antworten.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
<Xilinx-Installation>\doc\usenglish\books\docs\<MeinTyp>\<MeinTyp>.pdf

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry - genauer

<Xilinx-Installation>\doc\usenglish\books\docs\<device>_hdl\<device>.pdf

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

Bewertung
0 lesenswert
nicht lesenswert
Martin Kohler wrote:
> Woher nehme ich nun aber die Port Beschreibung?
Die steht in den Komentaren hinter dem Beispiel. Da solltest du 
natürlich nicht X,Y und Z abschliessen, sondern eher z.B.
  port map (
  DIA     => datain,  -- insert 1 bit data in bus (<0 downto 0>)
  ADDRA   => addrin,  -- insert 14 bits address bus
  ENA     => '1',     -- insert enable signal / immer enabled
  WEA     => write,   -- insert write enable signal 
  SSRA    => '0',     -- insert set/reset signal
  CLKA    => clkin,   -- insert clock signal
  DOA     => open,    -- insert 1 bit data out bus (<0 downto 0>)
--
  DIB     => (others=>'0'), -- insert 32 bits data in bus (<31 downto 0>)
  DIPB    => (others=>'0'), -- insert 4 bits parity data in bus (or <35 downto 32>)
  ADDRB   => addrout, -- insert 9 bits address bus
  ENB     => '1',     -- insert enable signal / immer enabled
  WEB     => '0',     -- insert write enable signal / nur lesen
  SSRB    => '0',     -- insert set/reset signal
  CLKB    => clkout,  -- insert clock signal
  DOB     => dataout, -- insert 32 bits data out bus (<31 downto 0>)
  DOPB    => open     -- insert 4 bits parity data out bus (or <35 downto 32>)
  );
Hier jetzt 1 Bit Eingangsbreite und 32 Bit Ausgangsbreite. Du könntest 
natürlich auch auf beiden Seiten lesen bzw. schreiben.

Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die bisherigen Antworten!

Lothar Miller wrote:
> Die steht in den Komentaren hinter dem Beispiel. Da solltest du
> natürlich nicht X,Y und Z abschliessen, sondern eher z.B.
Ist schon klar, danke trotzdem ;-)

Gast wrote:
> sorry - genauer
> <Xilinx-Installation>\doc\usenglish\books\docs\<device>_hdl\<device>.pdf
bei mir:
C:\Programme\Xilinx_92i\doc\usenglish\books\docs\s3edl
--> also eher: ...\docs\<device>dl

Die Port Beschreibungen habe ich nun im ISE auch gefunden:
>ISE x.y >Edit >Language Templates >VHDL >Device Primitive Instantiation >FPGA 
>RAM/ROM >Block RAM >...Spartan-3E >Dual-Port (Mis-matched Port Widths) >16k/1k x 
1/16 ...

Wenn ich nun den oben beschriebenen Typ wähle erhalte ich den folgenden 
(hier abgekürzten) Code:
--  <-----Cut code below this line and paste into the architecture body---->
   -- RAMB16_S1_S18: Virtex-II/II-Pro, Spartan-3/3E 16k/1k x 1/16 + 0/2 Parity bits Dual-Port RAM
   -- Xilinx HDL Language Template, version 9.2.1i
   RAMB16_S1_S18_inst : RAMB16_S1_S18
   generic map (
      INIT_A => "0", --  Value of output RAM registers on Port A at startup
      INIT_B => X"00000", --  Value of output RAM registers on Port B at startup
      SRVAL_A => "0", --  Port A ouput value upon SSR assertion
      SRVAL_B => X"00000", --  Port B ouput value upon SSR assertion
      WRITE_MODE_A => "WRITE_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
      WRITE_MODE_B => "WRITE_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
      SIM_COLLISION_CHECK => "ALL", -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL" 
      -- The following INIT_xx declarations specify the initial contents of the RAM
      -- Port A Address 0 to 4095, Port B Address 0 to 255
      INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
      ...
      INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Port A Address 4096 to 8191, Port B Address 256 to 511
      INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
      ...
      INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Port A Address 8192 to 12287, Port B Address 512 to 767
      INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
      ...
      INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Port A Address 12288 to 16383, Port B Address 768 to 1023
      INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
      ...
      INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- The next set of INITP_xx are for the parity bits
      -- Port B Address 0 to 255
      INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
      ...
      INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
   port map (
      DOA => DOA,       -- Port A 1-bit Data Output
      DOB => DOB,       -- Port B 16-bit Data Output
      DOPB => DOPB,     -- Port B 2-bit Parity Output
      ADDRA => ADDRA,   -- Port A 14-bit Address Input
      ADDRB => ADDRB,   -- Port B 10-bit Address Input
      CLKA => CLKA,     -- Port A Clock
      CLKB => CLKB,     -- Port B Clock
      DIA => DIA,       -- Port A 1-bit Data Input
      DIB => DIB,       -- Port B 16-bit Data Input
      DIPB => DIPB,     -- Port-B 2-bit parity Input
      ENA => ENA,       -- Port A RAM Enable Input
      ENB => ENB,       -- PortB RAM Enable Input
      SSRA => SSRA,     -- Port A Synchronous Set/Reset Input
      SSRB => SSRB,     -- Port B Synchronous Set/Reset Input
      WEA => WEA,       -- Port A Write Enable Input
      WEB => WEB        -- Port B Write Enable Input
   );
   -- End of RAMB16_S1_S18_inst instantiation

Die im Teil "generic map" eingetragenen Daten werden als Initialwert in 
s DPRAM übernommen, ich könnte so z.B. den Programmcode für einen 
PicoBlaze einfügen, richtig?

Sehe ich auch richtig, dass ich den "generig map" Teil weglassen kann 
und dann alles mit '0' resp. (others => '0') initialisiert wird?

Gruss, Martin

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.