Forum: FPGA, VHDL & Co. quartus, vhdl und blockram


von sunny (Gast)


Lesenswert?

servus

gibt es eigendlich in quartus die möglichkeit ein ram in vhdl zu 
beschreiben was dann im EAB und nicht in den LE's erzeugt wird? Ich hab 
nur die möglichkeit gefunden eine ram komponente mit dem megawizard zu 
erstellen und die dann ins desigen einzubinden. Das kann doch aber nicht 
die ultimative lösung sein. Zumal es bei xilinx ja auch über vhdl code 
funktioniert.
Weiß da jemand genaueres?

gruß sunny

von Iulius (Gast)


Lesenswert?

In der Regel wird immer ein Blockram verwendet, außer du hast eine 
krumme Anzahl an Indizes, also keinen "vollen" Ram genutzt.

In dem Fall kannst du in den Optionen aber immer noch einstellen, das 
auch für solche Fälle Blockram verwendet werden soll.


Ansonsten einfach mal den code zur Deklaration und Verwendung des Rams 
zeigen.

Weiß z.b. nicht ob es automatisch instanziiert wird, wenn man in einem 
Takt von mehreren Adressen liest oder solche Späße.

von SeriousSam (Gast)


Lesenswert?

Du brauchst mindestens ein Register am Eingang oder Ausgang und darfst 
keine speziellen Operationen auf ihnen durchführen. (Aufpassen mit 
Resetsignalen) Der folgende Code inferiert RAM in Cyclone FPGAs.
1
use ieee.std_logic_1164.all;
2
use ieee.numeric_std.all;
3
4
entity SampleRecorder is
5
port(
6
    signal clk, reset : in std_logic;
7
    signal ctrl_address : in std_logic_vector(1 downto 0);
8
    signal ctrl_writedata : in std_logic_vector(31 downto 0);
9
    signal ctrl_write : in std_logic;
10
    signal samples_address : in std_logic_vector(11 downto 0);
11
    signal samples_readdata : out std_logic_vector(31 downto 0);
12
    signal samples_read : in std_logic;
13
    signal sample_in : in std_logic_vector(23 downto 0);
14
    signal sample_in_strobe : in std_logic
15
);
16
end entity;
17
18
architecture arch of SampleRecorder is
19
    subtype sample_memword_t is std_logic_vector(23 downto 0);
20
    type sample_mem_t is array(0 to 4095) of sample_memword_t;
21
    signal sample_mem : sample_mem_t;
22
    signal sample_writeaddr : unsigned(11 downto 0);
23
    signal sample_writedata : std_logic_vector(23 downto 0);
24
    signal sample_write : std_logic;
25
begin
26
    process(clk, reset)
27
    begin
28
        if reset = '1' then
29
            sample_writeaddr <= (others=>'0');
30
            sample_writedata <= (others=>'0');
31
            sample_write <= '0';
32
        elsif rising_edge(clk) then
33
            if sample_in_strobe = '1' then
34
                sample_writeaddr <= sample_writeaddr+1;
35
                sample_writedata <= sample_in;
36
                sample_write <= '1';
37
            else
38
                sample_write <= '0';
39
            end if;
40
            if sample_write = '1' then
41
                sample_mem(to_integer(sample_writeaddr)) <= sample_writedata;
42
            end if;
43
            if samples_read = '1' then
44
                samples_readdata <= X"00"&sample_mem(to_integer(unsigned(samples_address)));
45
            end if;
46
            if ctrl_write = '1' then
47
                sample_writeaddr <= unsigned(ctrl_writedata(11 downto 0));
48
            end if;
49
        end if;
50
    end process;
51
end arch;

von sunny (Gast)


Lesenswert?

hallo,

ich hab mal noch ein bischen weiter gespielt. wirklich weiter gekommen 
bin ich aber nicht.
meine plattform ist ein FLEX10KA (EPF10K100A...).
dieser code
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
5
entity ramtest is
6
port(
7
    signal clk, wr : in std_logic;
8
    signal waddr,raddr : in std_logic_vector(7 downto 0);
9
    signal outdata : out std_logic_vector(7 downto 0);
10
  signal indata:in std_logic_vector(7 downto 0));
11
end entity;
12
13
architecture arch of ramtest is
14
    subtype sample_memword_t is std_logic_vector(7 downto 0);
15
    type sample_mem_t is array(0 to 255) of sample_memword_t;
16
    signal mem : sample_mem_t;
17
begin
18
    process(clk,raddr)
19
    variable adv:integer range 0 to 255;
20
    begin
21
    adv:=conv_integer(waddr);
22
        if wr = '1' then
23
            if rising_edge(clk) then
24
        mem(adv)<=indata;
25
            end if;
26
    else
27
     null;
28
     end if;
29
   adv:=conv_integer(raddr);
30
  outdata<=mem(adv);
31
    end process;
32
end arch;

sollte doch eigendlich ein RAM in einem der EAB's erzeugen? (würde auch 
genau in einen rein passen) tut er aber nicht. er bildet das ram aus 
knapp 3700 LE's. es macht auch keinen unterschied ob ich die 
ein/ausgänge registered mache oder nicht. immer das selbe. das ram 
landet in den LE's.
welche option muss ich denn setzen oder wie muss ich den code schreiben 
damit es hin haut?

@serioussam
mit dem code funktioniert es auch nicht. das ram wird dabei auch in den 
LE's erzeugt. zumindest bei mir. egal ob ich cyclone oder flex10k als 
zielplattform auswähle.

gruß sunny

von SeriousSam (Gast)


Lesenswert?

Du musst entweder outdata oder raddr (und ev. auch waddr und indata) 
registrieren, damit ein RAM-Block gebraucht werden kann. Der Compiler 
schiebt dann das Register an den richtigen Platz (Eingang,Adresse).

von ein_unwissender (Gast)


Lesenswert?

kenn mich eher mit Xilinx aus, aber vielleicht ist es ja ähnlich:

Kann man überhaupt ein RAM direkt aus VHDL erzeugen? Für die Simulation 
ja, aber für FPGA sollte normalerweise mit einem Werkzeug des 
Herstellers ein RAM-Block als IP erzeugt werden. Da wird dann eine Datei 
erzeugt, die man bei der Synthese mit einbindet. Dieser IP hat dann alle 
RAM-Signale wie Adressbits/Datenbits und R/W OE usw....Der IP kann dann 
als BlackBox im VHDL instantiiert werden....als COMPONENT mit der 
richtigen Bezeichnung, so dass die Synthesesoftware dann den fertig 
erzeugten Core benutzt.

von Duke Scarring (Gast)


Lesenswert?

ein_unwissender schrieb:
> Kann man überhaupt ein RAM direkt aus VHDL erzeugen?
Ja, man kann. Bei Xilinx steht das im "XST User Guide". Bei Altera wird 
es ein ähnliches Dokument geben.

Ich persönliche finde diese Schreibweise schöner, als einen 
instanziierten Blockram, der komische (und evtl. überflüssige) 
Signalnamen verwendet.

Duke

von ein_unwissender (Gast)


Lesenswert?

ok, wieder was gelernt.

Jedoch denke ich, dass man mit der BlackBox-Methode vielleicht als 
RAM-Neuling anfangen sollte um keinen unsinnigen RAM zu erstellen. Für 
die Profis ist es natürlich Geschmackssache, wenn man weiss was man tut.

von sunny (Gast)


Lesenswert?

tatsache! raddr muss registered sein!?!
1
    process(clk,raddr)
2
    variable adv,adv2:integer range 0 to 255;
3
    begin
4
        adv:=conv_integer(waddr);
5
        if rising_edge(clk) then
6
        if wr = '1' then
7
        mem(adv)<=indata;
8
        else
9
        adv2:=conv_integer(raddr);
10
        end if;
11
        end if;
12
        outdata<=mem(adv2);
13
    end process;
so funktionierts. ist ja doof. das auch das lesen taktsyncron erfolgen 
muss. aber o.k. damit muss man dann warscheinlich leben.
danke für eure hilfe!

gruß sunny

von sunny (Gast)


Lesenswert?

... oder auch nicht.
das target device stand noch auf cyclone. (war mir erst gar nicht 
aufgefallen) wenn man es wieder auf flex10k stellt funktioniert es 
wieder nicht. sch... technik.

gruß sunny

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.