Forum: FPGA, VHDL & Co. BRAM auslesen


von nic (Gast)


Lesenswert?

Hallo allerseits,


ich habe eine Frage bezüglich des Auslesens eines RAM's in VHDL.
Ich habe mir ein BlockRam erstellt.


Der Code für den Ram sieht so aus:
1
entity BRAM is
2
port(
3
clk    : IN std_logic;
4
wert_a : IN std_logic_vector(11 downto 0);
5
wert_b : IN std_logic_vector(11 downto 0);
6
write_address : IN std_logic_vector (11 downto 0);
7
read_address : IN std_logic_vector (11 downto 0);
8
enable : IN std_logic;
9
write_enable :  IN std_logic;
10
wert_out_a: OUT std_logic_vector(11 downto 0);
11
wert_out_b: OUT std_logic_vector(11 downto 0)
12
);
13
end BRAM;
14
15
16
architecture Behavioral of BRAM is
17
type t_bram is array(0 to 4095) of std_logic_vector(23 downto 0);
18
signal bram : t_bram;
19
20
21
22
23
begin
24
25
26
27
process (clk)
28
begin
29
   if rising_edge(clk) then 
30
    if enable = '1' then
31
      if write_enable='1' then      
32
        bram(conv_integer(write_address)) <= wert_a & wert_b;
33
      
34
      else      
35
        wert_out_a <= bram(conv_integer(read_address))(23 downto 12);
36
        wert_out_b <= bram(conv_integer(read_address))(11 downto 0);       
37
      end if;  
38
    end if;
39
   end if;    
40
end process;
41
42
43
44
45
end Behavioral;





Erste Frage:
1
type t_bram is array(0 to 4095) of std_logic_vector(23 downto 0);
2
signal bram : t_bram;

Würde dies bedeuten, dass mir dann als Block betrachtet 4096 Ram-Zeilen 
mit jeweils 24 Bit zur Verfügung stehen? Dieser dann also ein 
Speichervolumen von (24 Bit * 4096) aufweist?


Zweite Frage:

Angenommen der RAM ist beschrieben. Um ihn auszulesen, muss ich dazu den 
Baustein von aussen mit dem enable Signal und den Leseaddressen 
versorgen. Nun möchte ich den Ram nicht komplett auslesen, sondern nur 
im Bereich von bespielsweise adresse 'start' - 250 bis adresse 'start' + 
250. Also dann insgesamt 500 Zeilen.


Wie realisiere ich am geschicktesten den dazu nötigen Zähler, der jetzt 
von Adresse start-250 bis start+250 zählt? (normaler Zähler mit zähler 
+= 1 oder FOR-LOOP?)Dazu soll der Zähler nur dann gestartet werden, wenn 
der 'start'Wert > 250 und ('start'Wert + 250) <  Anzahl der vorhandenen 
RAM Zeilen ist, damit es nicht dazu kommt, weniger als 500 Zeilen 
auszulesen.


Habe ich mich so ausgedrückt, dass man mich verstehen kann? :-)

von Thomas T. (knibbel)


Lesenswert?

nic schrieb:
> Wie realisiere ich am geschicktesten den dazu nötigen Zähler, der jetzt
> von Adresse start-250 bis start+250 zählt? (normaler Zähler mit zähler
> += 1 oder FOR-LOOP?)Dazu soll der Zähler nur dann gestartet werden, wenn
> der 'start'Wert > 250 und ('start'Wert + 250) <  Anzahl der vorhandenen
> RAM Zeilen ist, damit es nicht dazu kommt, weniger als 500 Zeilen
> auszulesen.

Ich denke mit einer "FOR LOOP"-Schleife wird das nichts. Du 
programmierst nicht, du beschreibst!

Meine (bescheidene) Idee:

Einen Zähler bauen, der von 0 bis 250 zählt und dort verharrt. Eingänge 
hier sind ein Takt(-Enable) und ein Reset, welcher den Zähler wieder auf 
Null setzt.

Die RAM-Adresse bekommst du, indem du den Zählerstand mit deinem 
Startwert und "-250" addierst.

So übergibst du dem Modul dann nur deine Endadresse, resettest den 
Zähler und dein Takt, bzw. das Enable-Signal läßt die Werte auf der 
anderen Seite des RAMs rausfallen.

Dabei beachten: Evtl. will das BRAM auch einen Takt sehen, d.h. die 
richtigen RAM-Daten würden dann erst einen Takt später erscheinen.

Gruß,
Thomas

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


Lesenswert?

nic schrieb:
> Erste Frage: ...
Ja.

> Zweite Frage: ...
> zähler += 1 oder FOR-LOOP?
Aha, ein C-Programmierer.
Gegenfrage: Was hast du bisher mit VHDL gemacht?
Hast du mal die einfachen Sachen wie eine blinkende LED und ein 
Lauflicht gemacht und auch verstanden was da passiert?
Nein?
Mein Vorschlag: fann erst mal damit an...
http://www.lothar-miller.de/s9y/archives/80-Hello-World!.html
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

Und ich empfehle dann gleich die numeric_std:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

Zusammenfassend: die Aufgabe ist recht einfach, du hast aber noch nicht 
den geringsten Plan. Und es würde auch nichts helfen, wenn jemand sagen 
würde: nimm einen unsigned-Zähler mit 12 Bit und lass in einer 
Statemachine einen zweiten Zähler als Offset drumrum laufen.
BTW: jede Art von "Ablauf" oder "Sequenz" wird auf einem FPGA als 
Statemachine (FSM) realisiert. Wenn du also "erst" vergleichen musst, 
"dann" "Schritt für Schritt" den Speicher ausliest, brauchst du eine 
FSM.

von nic (Gast)


Lesenswert?

Vielen Dank für die Antworten,

Lothar Miller schrieb:
> Aha, ein C-Programmierer.

Nein, Faulheit ;-)

Lothar Miller schrieb:
> Hast du mal die einfachen Sachen wie eine blinkende LED und ein
> Lauflicht gemacht und auch verstanden was da passiert?
> Nein?

Ja

Lothar Miller schrieb:
> du hast aber noch nicht
> den geringsten Plan.

Tausche "den geringsten " gegen "den richtigen" und wir sind uns einig

Benötige ich für diese Aufgabe wirklich eine State Machine? Reicht es 
nicht, wenn ich einen Zähler baue, welcher beim Lesevorgang auf den 
StartWert-250 vorinitialiser wird und dann 500 mal um 1 (count <= count 
+ 1) inkrementieren wird?

von nic (Gast)


Lesenswert?

Thomas T. schrieb:
> Ich denke mit einer "FOR LOOP"-Schleife wird das nichts. Du
> programmierst nicht, du beschreibst!

Jedoch ist eine For-Loop doch synthetisierbar. Das heißt, diese lässt 
sich doch auch in Hardware umsetzen (auch wenn es nicht so praktisch 
ist). Oder nicht?

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


Lesenswert?

Natürlich lässt sich eine Schleife umsetzen. Nur kommt da bei VHDL ganz 
was anderes raus, als du mit deinen C Programmierkenntnissen erwarten 
würdest...
Und ein Zugriff auf die Elemente eines RAMs lässt sich mit einer 
Schleife sicher nicht realisieren, weil eine Schleife nämlich 
gleichzeitig "ausgeführt" wird.

Und ja: du brauchst eine FSM. Streng genommen ist nämlich schon ein 
einfacher Zähler ein Zustandsautomat...

von nic (Gast)


Lesenswert?

Danke Lothar für die Erklärung. Könntest Du mir das mit der State 
Machine nochmal näher erläutern?

Wie meinst Du das genau mit

Lothar Miller schrieb:
> zweiten Zähler als Offset drumrum laufen

Wäre es dann richtig, die State Machine mit drei States (idle, compare , 
count) zu versehen? Oder soll diese nur zählen und nach dem Vergleich 
dann ausgeführt werden oder dann nicht.
1
type state_type is (idle, compare, count);  
2
signal current_s,next_s: state_type;


Wenn ich direkt nach dem Beschreiben den RAM auslesen möchte, muss die 
State Machine dann doch beim Flankenwechsen (fallenden Flanke) des write 
enable-Signals den Status das erste mal ändern, oder?



Den Counter würde ich dann so realisieren:

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
.
5
.
6
7
8
architecture ....
9
.
10
.
11
.
12
signal count: unsigned (11 downto 0) := (others => '0');  
13
.
14
.
15
.
16
17
18
begin
19
20
21
process(clk)
22
begin
23
   if rising_edge(clk) then
24
     if (bedingung_erfuellt = '1') then
25
        count <= count + 1;      
26
     else
27
  count <= (others => '0');      
28
     end if;
29
   end if;
30
end process;



Vielen Dank für die Geduld :-)

von nic (Gast)


Lesenswert?

Habe es mit der State-Machine ausprobiert.

Habe jetzt 2 States. Einen Idle State und einen Counter State.
Bei dem Flankenwechsel des Schreibevorgangs von 1 auf 0 erfolgt der 
Statewechsel von Idle auf Count. Dann lasse ich den Counter 500 mal 
durchlaufen und wechsel danach in den Idle State zurück.

Und es funktioniert !!! :-)


Gruß und Dank,

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.