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
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.
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; |
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
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).
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.
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
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.
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
... 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.