Forum: FPGA, VHDL & Co. BRAM wird nicht richtig ausgelesen


von Tom (Gast)


Angehängte Dateien:

Lesenswert?

Hallo VHDL Profi's,

ich habe folgendes Problem. Ich habe eine BRAM Componente instanziiert, 
welche aus dem Top Level die Write und Read Adressen erhält. Anhand 
einer Testbench konnte ich jedoch sehen, dass die erste Zeile des RAM's 
nicht ausgelesen wird. Erst die zweite Zeile ist Anfang des RAM's.

Entweder wird die erste Zeile gar nicht mit dem ersten Wert beschrieben 
oder die erste Zeile wird nicht richtig ausgelesen.

Hier der Code für den Adressen Prozess:
1
process (clk, lval)
2
  begin
3
    if rising_edge(clk) then
4
      if lval = '1' then      
5
        enable <= '1';              -- nachdem lval = 1, enable  1 
6
        write_counter <= write_counter + 1;      
7
      else
8
        write_counter <= (others => '0');
9
        
10
      end if;
11
      
12
      if lval = '0' then
13
        if (enable = '1') then
14
          read_counter <= read_counter + 1;      
15
        end if;
16
      
17
      else 
18
        read_counter <= (others => '0');
19
        
20
      end if;
21
    end if;
22
      write_address <= std_logic_vector(write_counter);
23
    read_address <= std_logic_vector(read_counter);
24
    write_address_test <= std_logic_vector(write_counter);
25
    read_address_test <= std_logic_vector(read_counter);    
26
    
27
  end process;


write_address_test und read_address_test dienen nur zur Anzeige der 
Signalwerte.

Solange lval = 1 ist, soll der RAM beschrieben werden, sobald lval auf 0 
wechselt, soll der RAM auslesen werden. Enable wird gesetzt, sobald lval 
= 1 ist. Eine Abbruchbedingung  für den Auslese - Adressencounter und 
enable ist noch nicht implementiert, dies wird abhängig sein von der 
Anzahl der Elemente im Speicher. Später soll auch nur ein gewisser 
Bereich des RAM's ausgelesen werden und nicht mehr alle Werte. Aber das 
zu späteren Stunde.

Die Portmap sieht folgendermaßen aus:
1
PM1: BRAM port map ( clk => clk,
2
              data_a => data_a,
3
              data_b => data_b,
4
              write_address => write_address,
5
              read_address => read_address,
6
              enable => enable,
7
              write_enable => lval,
8
              data_out_a => data_out_a,
9
              data_out_b => data_out_b
10
              );

Ein Screenshot habe ich dem Anhang hinzugefügt. Die ersten zwei Werte, 
welche in im Speicher mit einer Breite von 24 Bit (2 x 12) ablegegt 
werden, fehlen bei der Ausgabe (data_out_a und data_out_b), also die 53 
und 61.

Kann mir jmd. sagen, wo ich den Denkfehler habe?

Viele Dank und Grüße,

Tom

von Tom (Gast)


Lesenswert?

PS: Der BRAM sieht folgendermaßen aus:
1
entity BRAM is
2
port(
3
clk    : IN std_logic;
4
data_a : IN std_logic_vector(11 downto 0);
5
data_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
data_out_a: OUT std_logic_vector(11 downto 0);
11
data_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
--signal write_address : integer range 0 to 4095 := 0;
21
--signal read_address : integer range 0 to 4095 := 0;
22
23
24
begin
25
26
27
28
process (clk)
29
begin
30
   if rising_edge(clk) then 
31
    if enable = '1' then
32
      if write_enable='1' then
33
      --  write_address <= write_address + 1;
34
        
35
        bram(conv_integer(write_address)) <= data_a & data_b;
36
        --bram(write_address) <= data_a & data_b;
37
      
38
      else
39
      --  read_address <= read_address + 1;
40
        data_out_a <= bram(conv_integer(read_address))(23 downto 12);
41
        data_out_b <= bram(conv_integer(read_address))(11 downto 0);       
42
      end if;  
43
    end if;
44
   end if;    
45
end process;
46
47
48
49
50
end Behavioral;

von SuperWilly (Gast)


Lesenswert?

Das "enable" wird einen Takt nach "lval" gesetzt!


VG, SuperWilly

von Tom (Gast)


Lesenswert?

TATSACHE :-) OHMAN,

vielen Dank. Manchmal sieht man den Wald vor lauter Bäume nicht

von Tom (Gast)


Lesenswert?

Ok, nun möchte ich den RAM nicht mehr komplett von vorne auslesen. Ich 
habe einen Adresswert, mit dem ein gewisser Bereich vor dem Wert und 
einen Bereich nach den Wert ausgelesen werden soll.

Also wenn ich meinen Speicher mit 1000 Werte (500 Speicherzeilen) 
beschrieben habe und ab Adresse 350, 400 Werte (200 Zeilen) um die 350 
herum "ausschneiden" möchte, also alle Zeilenwerte von Zeile 250 - 450 
auslesen möchte, wie weise ich das genau meiner read_address zu?

Ich müsste doch jetzt im folgenden Code den read_counter so 
programmieren, dass er ab Adresse (Mittelwert - auszuschneidener Bereich 
/2) also  350 - (200/2) dann genau 200 mal die Adresse hochzählt, oder?
1
process (clk, lval)
2
  begin
3
    if rising_edge(clk) then
4
      if lval = '1' then      
5
        enable <= '1';              -- nachdem lval = 1, enable  1 
6
        write_counter <= write_counter + 1;      
7
      else
8
        write_counter <= (others => '0');
9
        
10
      end if;
11
      
12
      if lval = '0' then
13
        if (enable = '1') then
14
          read_counter <= read_counter + 1;      
15
        end if;
16
      
17
      else 
18
        read_counter <= (others => '0');
19
        
20
      end if;
21
    end if;
22
    write_address <= std_logic_vector(write_counter);
23
    read_address <= std_logic_vector(read_counter);
24
    write_address_test <= std_logic_vector(write_counter);
25
    read_address_test <= std_logic_vector(read_counter);    
26
    
27
  end process;

von SuperWilly (Gast)


Lesenswert?

Was genau hast du eigentlich vor? Ist das eine Fingerübung oder steckt 
ein tieferer Sinn dahinter?

Denk mal darüber nach, eine Zustandsmaschine einzusetzen. Hier kannst du 
in verschiedenen Zuständen machen, was Du willst: RAM füllen, RAM 
komplett auslesen, RAM bereichsweise auslesen usw.

VG, SuperWilly

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.