Forum: FPGA, VHDL & Co. Frage zum Block RAM


von Cihan K. (lazoboy61)


Lesenswert?

Hallo,

habe mal eine kleine Frage zum Block RAM.

Ich möchte den Block Ram des Virtex 5 verwenden. Dabei gehe ich genauso 
vor, wie Lothar es auch auf seiner Homepage beschrieben hat. Das ein und 
auslesen funktioniert auch alles richig.

Nun zur Frage, ich möchte Bsp.weise einen Block Ram von 256 Words x 8 
Bit erstellen. Dabei will ich die Daten 8 Bit weise in den Block Ram 
rein schreiben, aber evtl. mit 16 Bit-Weise, 32Bit-Weise, etc. auslesen. 
Mit anderen Worten will ich verschiedene Datenbusgrößen haben. Mit dem 
Coregenerator kann man sowohl beim Fifo als auch beim Block Ram 
Generator diese Einstellungen machen, doch wie mache ich es per VHDL 
Code selber.

Hier mein jetztiger Stand:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
use ieee.numeric_std.all;
5
use IEEE.STD_LOGIC_UNSIGNED.ALL;
6
7
-- Uncomment the following library declaration if instantiating
8
-- any Xilinx primitives in this code.
9
--library UNISIM;
10
--use UNISIM.VComponents.all;
11
12
entity TOP is
13
  GENERIC(
14
      Addrbreite: integer:= 13;
15
      Wortbreite: integer:= 64
16
      );
17
  PORT (
18
      CLK: in std_logic;
19
      RST: in std_logic;
20
      BT: in std_logic;
21
      SW: in std_logic;
22
      Test: out std_logic
23
      );
24
end TOP;
25
26
architecture Behavioral of TOP is
27
28
type speicher is array(0 to (2**Addrbreite)-1) of STD_LOGIC_VECTOR(Wortbreite-1 downto 0);
29
signal memory : speicher;   
30
31
signal A, B: std_logic_vector(12 downto 0):= (others => '0');
32
signal Din, Dout: std_logic_vector(63 downto 0):= (others => '0');
33
signal entprell: natural range 0 to 1000000;
34
signal BT_v: std_logic;
35
signal Read_Ram, Write_Ram: std_logic:= '0';
36
37
begin
38
39
process(CLK)
40
41
begin
42
43
if rising_edge(CLK) then
44
  if RST = '1' then
45
    A <= (others => '0');
46
    B <= (others => '0');
47
    Din <= (others => '0');
48
    entprell <= 0;
49
    Test <= '0';
50
    Read_Ram <= '0';
51
  else
52
    if BT = '1' and BT_v = '0' and entprell = 0 then
53
      entprell <= 1000000;
54
    elsif entprell > 1 then
55
      entprell <= entprell - 1;
56
    elsif entprell = 1 then
57
      entprell <= entprell - 1;
58
      if BT = '1' and SW = '1' then
59
        Write_Ram <= '1';
60
        Din <= Din + 1;
61
        A <= A + 1;
62
      elsif BT = '1' and SW = '0' then
63
        Read_Ram <= '1';
64
        B <= B + 1;
65
      end if;
66
    end if;
67
    BT_v <= BT;
68
    if Dout = (Dout'range => '1') then
69
      Test <= '1';
70
    else
71
      Test <= '0';  
72
    end if;
73
  end if;
74
  if Write_Ram = '1' then
75
    Write_Ram <= '0';
76
    memory(to_integer(unsigned(A))) <= Din;
77
  end if;
78
  if Read_Ram = '1' then
79
    Read_Ram <= '0';
80
    Dout <= memory(to_integer(unsigned(B)));
81
  end if;
82
end if;
83
84
end process;
85
86
end Behavioral;

In diesem Programm wird per Button und Switch der Block Ram entweder 
beschrieben oder gelesen. Sowohl Din als auch Dout sind 64 Bit groß. Wie 
kann ich z.B. mit Din 64 Bit reinschreiben aber mit Dout 256 Bit 
auslesen in einem Takt. Geht das überhaupt? (Muss doch gehen oder?, 
zumindest wenn man es unter dem Coregenerator auch so erzeugen kann ?!)

Würde mich über jede Anregung sehr freuen.
Danke im Voraus
Cihan

von Christian R. (supachris)


Lesenswert?

Im XST User Guide steht drin, wie man das macht. Und ich glaube in den 
Code Templates in ISE direkt auch.

von Cihan K. (lazoboy61)


Lesenswert?

In den Code Templates habe ich schon gesucht, doch bin noch nicht findig 
geworden.

Im XST User Guide schaue ich gleich mal nach. Hoffe jemand kann mir 
evtl. ein Beispiel zu meinem Problem geben.

Danke
Gruß Cihan

von Cihan K. (lazoboy61)


Lesenswert?

Im XST User Guide sind viele Beispiele zum Block Ram drin, aber keins 
mit unterschiedlichen Datenbusbreiten. Heisst das, dass es nicht möglich 
ist, Daten-Eingang und -Ausgang unterschiedlich zu machen.

In den Templates bin ich auch nicht findig geworden.

So schwer dürfte dies doch gar nicht sein eigentlich, denn wenn es im 
Coregenerator möglich ist, dann sollte man es auch per VHDL Code machen 
können, oder ?!

Cihan

von Cihan K. (lazoboy61)


Lesenswert?

Bei dem Xst User Guide vom Spartan 6 oder Virtex 6 ist ein Code Beispiel 
da zum Block Ram mit unterschiedlicher Datenbusbreite, aber nicht im 
User Guide vom Virtex 5, also geht es vermutlich dann auf dem Virtex 5 
nicht. Schade

Cihan

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


Lesenswert?

Oh doch. Das geht garantiert. Lies einfach mal das Datenblatt des FPGAs 
durch. Und sieh dir die Language Templates in der ISE an...

von Cihan K. (lazoboy61)


Lesenswert?

Ich suche schon die ganze Zeit wie ein wilder, aber immer noch nicht 
findig geworden. Habe auch schojn ins Datenblatt reingeschaut, auch in 
den XST User Guides, auch in die Templates von ISE vom Block RAM, doch 
bis jetzt nicht die richtige Lösung gefunden.

Das einzige was im User Guide vom Spartan 6 gefunden habe ist folgender 
Code auf Seite 218 und 219:
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_2/xst_v6s6.pdf
Das kommt meinem Fall am nähesten. Kann ich es nun genauso für den 
Virtex 5 anwenden?

Cihan

von namenlos (Gast)


Lesenswert?

ISE 14.2:

Edit -> Language Templates -> VHDL -> Synthesis Constructs -> Coding 
Examples -> RAM -> BlockRAM -> Dual Port -> Asymetric Ports

kannst Du sogar noch aussuchen, ob Du "No Change", "Read First" oder 
"Write First" haben willst - einfacher geht's wohl kaum noch...

von Cihan K. (lazoboy61)


Lesenswert?

Danke für die Hinweise, aber ich glaube das das mit dem Virtex 5 nicht 
geht.

Ich habe nun mir auch die Language Templates angesehen und in einem ISE 
Testprojekt synthesiert und das Ergebnis ist folgendes:

Sobald ich für das Projekt als Target den Virtex 5 nehme treten viele 
Fehler beim synthesieren der Example Codes auf, habe die Fehler meist 
auch wegbekommen, aber der Block Ram wird nicht mit unterschiedlichen 
Bussen angesteuert (aspect ratio). Das sah ich im Synthese Report.

Nun wenn ich aber als Target den Virtex 6 wähle, dann funktionieren die 
Beispiele zu 100%, ohne irgendwelche Fehler und vor allem wird der Block 
Ram richtig angesteuert (unterschiedliche Datenbusse, etc).

Ich habe mir die beiden XST User Guides vom Virtex 6 und Virtex 5 
angeschaut und nur beim Virtex 6 gab es Example Codes zu asymmetrischem 
Block Ram (unterschiedliche Datenbusse). Beim Virtex 5 im XST User Guide 
sind keine aufgeführt.

Liege ich nun mit der Erkenntnis richtig, dass ich mit dem Virtex 5 
keine unterschiedlichen Datenbusse beim Block Ram haben kann?

Cihan

von Thosch (Gast)


Lesenswert?

Cihan Kalayci schrieb:
> Danke für die Hinweise, aber ich glaube das das mit dem Virtex 5 nicht
> geht.

Sorry, aber das ist völliger Unsinn!
Wie Lothar Miller bereits gesagt hat: Das geht garantiert.
Und zwar bei jedem Xilinx-FPGA mit BlockRams.

Ich nutze täglich BlockRams mit unterschiedlichen Wortbreiten, arbeite 
allerdings nicht mit VHDL, sondern mit Schematic Entry über 3rd party 
Software, die ISE bekommt dann nur ein EDIF als Quelle.

Hab Dir mal aus dem Virtex-5 Libraries Guide for HDL Designs
das Instanziierungs-Template für ein RAMB18 BlockRam reinkopiert:

1
Library UNISIM;
2
use UNISIM.vcomponents.all;
3
-- RAMB18: 16k+2k Parity Paramatizable True Dual-Port BlockRAM
4
-- Virtex-5
5
-- Xilinx HDL Libraries Guide, version 13.4
6
RAMB18_inst : RAMB18
7
generic map (
8
DOA_REG => 0, -- Optional output register on A port (0 or 1)
9
DOB_REG => 0, -- Optional output register on B port (0 or 1)
10
INIT_A => X"00000", -- Initial values on A output port
11
INIT_B => X"00000", -- Initial values on B output port
12
READ_WIDTH_A => 0, -- Valid values are 1, 2, 4, 9, or 18
13
READ_WIDTH_B => 0, -- Valid values are 1, 2, 4, 9, or 18
14
SIM_COLLISION_CHECK => "ALL", -- Collision check enable "ALL", "WARNING_ONLY",
15
-- "GENERATE_X_ONLY" or "NONE"
16
SIM_MODE => "SAFE", -- Simulation: "SAFE" vs "FAST", see "Synthesis and Simulation
17
-- Design Guide" for details
18
SRVAL_A => X"00000", -- Set/Reset value for A port output
19
SRVAL_B => X"00000", -- Set/Reset value for B port output
20
WRITE_MODE_A => "WRITE_FIRST", -- "WRITE_FIRST", "READ_FIRST" or "NO_CHANGE"
21
WRITE_MODE_B => "WRITE_FIRST", -- "WRITE_FIRST", "READ_FIRST" or "NO_CHANGE"
22
WRITE_WIDTH_A => 0, -- Valid values are 1, 2, 4, 9, or 18
23
WRITE_WIDTH_B => 0, -- Valid values are 1, 2, 4, 9, or 18
24
-- The following INIT_xx declarations specify the initial contents of the RAM
25
INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
26
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
27
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
28
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
29
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
30
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
31
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
32
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
33
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
34
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
35
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
36
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
37
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
38
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
39
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
40
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
41
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
42
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
43
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
44
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
45
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
46
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
47
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
48
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
49
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
50
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
51
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
52
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
53
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
54
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
55
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
56
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
57
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
58
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
59
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
60
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
61
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
62
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
63
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
64
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
65
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
66
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
67
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
68
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
69
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
70
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
71
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
72
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
73
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
74
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
75
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
76
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
77
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
78
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
79
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
80
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
81
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
82
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
83
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
84
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
85
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
86
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
87
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
88
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
89
-- The next set of INITP_xx are for the parity bits
90
INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
91
INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
92
INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
93
INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
94
INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
95
INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
96
INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
97
INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
98
port map (
99
DOA => DOA, -- 16-bit A port data output
100
DOB => DOB, -- 16-bit B port data output
101
DOPA => DOPA, -- 2-bit A port parity data output
102
DOPB => DOPB, -- 2-bit B port parity data output
103
ADDRA => ADDRA, -- 14-bit A port address input
104
ADDRB => ADDRB, -- 14-bit B port address input
105
CLKA => CLKA, -- 1-bit A port clock input
106
CLKB => CLKB, -- 1 bit B port clock input
107
DIA => DIA, -- 16-bit A port data input
108
DIB => DIB, -- 16-bit B port data input
109
DIPA => DIPA, -- 2-bit A port parity data input
110
DIPB => DIPB, -- 2-bit B port parity data input
111
ENA => ENA, -- 1-bit A port enable input
112
ENB => ENB, -- 1-bit B port enable input
113
REGCEA => REGCEA, -- 1-bit A port register enable input
114
REGCEB => REGCEB, -- 1-bit B port register enable input
115
SSRA => SSRA, -- 1-bit A port set/reset input
116
SSRB => SSRB, -- 1-bit B port set/reset input
117
WEA => WEA, -- 2-bit A port write enable input
118
WEB => WEB -- 2-bit B port write enable input
119
);
120
-- End of RAMB18_inst instantiation


Du kannst hier sogar (anders als bei anderen Xilinx-Familien)
die Read und Write Portbreite getrennt festlegen.
(siehe Parameter READ_WIDTH_A, READ_WIDTH_B, WRITE_WIDTH_A, 
WRITE_WIDTH_B)

also erzähl hier nicht, daß funktioniere nicht...

Gruß,
Thosch

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


Lesenswert?

Cihan Kalayci schrieb:
> Danke für die Hinweise, aber ich glaube das das mit dem Virtex 5 nicht
> geht.
Ich kann dir sicher sagen, dass das mit dem Virtex 5 (der ja immerhin 
lange Jahre die Oberliga von Xilinx war) geht. Und im UG160 steht auf 
Seite 120 ganz klar:
1
Independent Read and Write Port Width Selection
2
Each block RAM port has control over data width and address depth (aspect ratio). The 
3
true dual-port block RAM in Virtex-5 FPGAs extends this flexibility to Read and Write 
4
where each individual port can be configured with different data bit widths.
http://www.xilinx.com/support/documentation/user_guides/ug190.pdf

von Cihan K. (lazoboy61)


Lesenswert?

Thosch schrieb:
> also erzähl hier nicht, daß funktioniere nicht...

Das war ja nur eine Frage und keine Behauptung, im ersten Satz steht ja 
auch "ich glaube".

Ich habe nur meine Erkenntnisse geschildert und versucht evtl. mit euren 
Antworten meine Fehler zu entdecken, die ich ggf. gemacht habe.

Natürlich denke ich, dass ein Virtex 5 dazu fähig sein muss, aber wie 
hier geschildert, habe ich Probleme gehabt:

Cihan Kalayci schrieb:
> Sobald ich für das Projekt als Target den Virtex 5 nehme treten viele
> Fehler beim synthesieren der Example Codes auf, habe die Fehler meist
> auch wegbekommen, aber der Block Ram wird nicht mit unterschiedlichen
> Bussen angesteuert (aspect ratio). Das sah ich im Synthese Report.
>
> Nun wenn ich aber als Target den Virtex 6 wähle, dann funktionieren die
> Beispiele zu 100%, ohne irgendwelche Fehler und vor allem wird der Block
> Ram richtig angesteuert (unterschiedliche Datenbusse, etc).

Thosch schrieb:
> Hab Dir mal aus dem Virtex-5 Libraries Guide for HDL Designs
> das Instanziierungs-Template für ein RAMB18 BlockRam reinkopiert:
Diese habe ich mir auch angeschaut, doch brauche viel mehr an Speicher 
(z.B. 15 Block Rams) und wusste nicht wie ich mehrere zusammenbringe.

Eigentlich bezieht sich meine Frage auf meinem ersten Beitrag ganz oben. 
Ich habe ja einen Beispiel oben angegeben und hatte gefragt wie ich den 
anpassen müsste um die Datenbusse unterschiedlich zu verwenden. Da würde 
ich ja jetzt ungern eine oder mehrere Ram-Instanzen instanziieren, 
sondern würde gerne es so haben, dass der Synthesierer das automatisch 
händelt, was für ihn ja normalerweise auch kein Problem sein kann. Oder 
liege ich da falsch?

Cihan

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


Lesenswert?

Cihan Kalayci schrieb:
> Diese habe ich mir auch angeschaut, doch brauche viel mehr an Speicher
> (z.B. 15 Block Rams) und wusste nicht wie ich mehrere zusammenbringe.
Also, die gute Nachricht: es geht.

> Da würde ich ja jetzt ungern eine oder mehrere Ram-Instanzen
> instanziieren
Die Schlechte: du musst es händisch machen...

> würde gerne es so haben, dass der Synthesierer das automatisch händelt
Zusammen mit Spartan6 und Virtex6 gab es natürlich auch eine gründliche 
Überarbeitung der Toolchain, so dass evtl. ein in VHDL generisch 
beschreibenes RAM jetzt reibungsloser übersetzt werden kann. Aber 
soooooo arg weit weg von "automatisch" ist der Weg über eine manuelle 
Instantiierung ja nun auch nicht...

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.