BRam im eigenen IP Core initialisieren

Gast #1488571
Lesenswert?

Hallo an Alle,

ich gerade dabei einen eigenen IP Core zu erstellen, der mit mehr als 
einem Microblaze per FSL kommunizieren können soll.
Mehrere FSL Busse habe ich inzwischen in den IP Core reinbekommen, sogar 
so, dass man die Anzahl per GUI einstellen kann.
Der nächste Schritt wäre nun Block RAM zu verwenden.
Um Block Ram zu instanzieren habe ich folgendes gemacht:

type bram_type is array ((2**bram_addr_width)-1 downto 0) of 
std_logic_vector(bram_data_width-1 downto 0);

signal BRAM : bram_type;

Bevor ich das Block Ram nun benutze würde ich dieses gerne 
initialisieren. Das Problem dabei: Ich möchte es nicht beim Laden des 
FPGA's mit initialisieren, sondern immer dann, wenn das reset-Signal 
meines IP-Cores auf '1' geht. Da tut sich mir die Frage auf, ob das 
überhaupt möglich ist, da es ja eine bestimmte Zeit dauern würde, bis 
das BRam komplett initialisiert ist und ich nicht sicherstellen kann, 
dass das reset-Signal mindestens diese Zeit auf '1' bleibt.

Für die Initialisierung habe ich folgendes versucht:

The_SW_accelerator : process (FSL_Clk) is
   begin  -- process The_SW_accelerator
    if FSL_Clk'event and FSL_Clk = '1' then
      if FSL_Rst = '1' then
        for i in 0 to (2**mbx_addr_width)-1 loop
          BRAM(to_integer(unsigned(i))) <= i;
        end loop;
      end if;
    end if;
end process;

Dies ist ein verkürzter Abschnitt des VHDL-Codes. Leider kommt dabei 
folgender Fehler, der sich auf die zeile des BRam Zugriffs bezieht:
ERROR:HDLParsers:854 - The expression can not be converted to type 
unsigned.

Mache ich da etwas falsch? Ich verstehe das Problem an der Stelle nicht 
so ganz.

Ist es überhaupt möglich per reset-Signal das BRam mit 0, 1, 2, 3, 4... 
usw. zu belegen?

Wenn es da eine Möglichkeit gibt wäre ich euch sehr dankbar, mir ein 
paar Tips zu geben.

lg,
ChrisB
Moderator (Firma: Titel) Persönliche Seite #1488641
Lesenswert?

> Da tut sich mir die Frage auf, ob das
> überhaupt möglich ist, da es ja eine bestimmte Zeit dauern würde, bis
> das BRam komplett initialisiert ist und ich nicht sicherstellen kann,
> dass das reset-Signal mindestens diese Zeit auf '1' bleibt.
Dann mußt du hergehen und mit dem Reset die Initialisierung starten. 
allerdings solltest du erst dann auf das BRAM zugreifen, wenn di 
Initialisierung beendet ist. Wie willst du übrigens dann später mal 
irgendwas anderes in das BRAM bekommen?

> The expression can not be converted to type unsigned.
Ja, klar: i ist ein integer....
Du solltest es also eher so machen:

BRAM(i) <= std_logic_vector(to_unsigned(i,bram_data_width));

> Ist es überhaupt möglich per reset-Signal das BRam mit 0, 1, 2, 3, 4...
> usw. zu belegen?
Nicht so ohne weiteres, du mußt jede Zelle per Handschlag auf den Wert 
setzen.
Eine Möglichkeit wäre eine komplette Neuinitialisierung des FPGAs (via 
PROG_B) und die Verwendung von Defaultwerten (wie dort in der 
Sinus-Tabelle: http://www.lothar-miller.de/s9y/categories/31-DDFS).
Gast #1488662
Lesenswert?

Danke für deine Antwort.

Ja, so habe ich es auch gerade gelöst. Mit dem Reset wird die 
Initialisierung gestartet und nach Fertigstellung setze ich ein Signal, 
welches ich nach außen führe, auf '1'. An Hand dieses Signals wissen die 
angeschlossenen Microblazes dann, ab wann diese auf meinen IP Core 
zugreifen dürfen.

Wie meinst du das, wie ich später mal was anderes ins BRam bekommen 
will?
Nach der Initialisierung soll dann per FSL was ins BRam geschrieben 
werden können. Sollte doch gehen oder?
Gast #1488726
Lesenswert?

Ja, ich hatte vor dass der weitere Zugriff in einer State-Machine 
abläuft, sobald das reset-Signal auf '0' ist und die Initialisierung 
abgeschlossen ist.

Zunächst möchte ich dann (aus der Sicht meines IP Cores) die über den 
Slave empfangenen Daten als Adresse des BRams verwenden und den Inhalt 
des BRams an den Master FSL raus zu schicken.

Das wäre so mein erster Test um zu gucken, ob ich das BRam auslesen 
kann.
Danach würde ich versuchen auch auf das BRam zu schreiben, aber das ist 
erst der nächste Schritt.
Gast #1488781
Lesenswert?

Leider habe ich folgendes Problem bezüglich meines IP Cores:
Der angeschlossene Microblaze macht immer ein put-Befehl, um die Adresse 
zu übermitteln, wartet bis fsl_isinvalid '0' liefert, macht dann solange 
get-Befehle bis fsl_isinvalid '0' liefert.
Das Ganze mache ich in einer Schleife mit nem Delay von ner halben 
Sekunde und gebe dem put-Befehl einen Zählerwert mit.
Leider kommt beim Get Befehl 16 mal 0 zurück und danach hängt er sich 
auf, da fsl_isinvalid nicht mehr 0 wird.
Vermutlich ist nach 16 Put-Befehlen der 16-stufige Fifo voll, mein IP 
Core arbeitet nicht richtig, da die Daten nicht abgeholt werden.
Hat jemand eine Idee, was falsch sein könnte?
1
entity coprocessor is
2
  generic 
3
  (
4
    bram_addr_width  : natural := 8;
5
    bram_data_width  : natural := 32
6
   );
7
        
8
  port 
9
  (
10
    FSL_Clk        : in  std_logic;
11
    FSL_Rst        : in  std_logic;
12
    FSL0_S_CLK      : out  std_logic;
13
    FSL0_S_READ      : out  std_logic;
14
    FSL0_S_DATA      : in  std_logic_vector(0 to 31);
15
    FSL0_S_CONTROL    : in  std_logic;
16
    FSL0_S_EXISTS    : in  std_logic;
17
    FSL0_M_CLK      : out  std_logic;
18
    FSL0_M_WRITE    : out  std_logic;
19
    FSL0_M_DATA      : out  std_logic_vector(0 to 31);
20
    FSL0_M_CONTROL    : out  std_logic;
21
    FSL0_M_FULL      : in  std_logic
22
    );
23
);
24

25
architecture EXAMPLE of coprocessor is
26

27
   type STATE_TYPE is (Idle, Read_Inputs, Write_Outputs);
28
   signal state        : STATE_TYPE;
29
  
30
  -- BRAM
31
  type bram_type is array ((2**bram_addr_width)-1 downto 0) of std_logic_vector(bram_data_width-1 downto 0);
32
  signal BRAM : bram_type;
33
  signal bram_addr : std_logic_vector (bram_data_width-1 downto 0) := x"00000000";
34
  signal bram_data : std_logic_vector (bram_data_width-1 downto 0) := x"00000000";
35

36
begin
37
   FSL0_S_Read  <= FSL0_S_Exists   when state = Read_Inputs   else '0';
38
   FSL0_M_Write <= not FSL0_M_Full when state = Write_Outputs else '0';
39
  
40
   FSL0_M_Data <= bram_data;
41

42
   The_SW_accelerator : process (FSL_Clk) is
43
   begin  -- process The_SW_accelerator
44
    if FSL_Clk'event and FSL_Clk = '1' then     -- Rising clock edge
45
      if FSL_Rst = '1' then               -- Synchronous reset (active high)
46
        -- CAUTION: make sure your reset polarity is consistent with the
47
        -- system reset polarity
48
      
49
      -- BRAM Init
50
      if bram_addr < 2**bram_addr_width then  
51
        BRAM(to_integer(unsigned(bram_addr))) <= bram_addr;
52
       bram_addr <= bram_addr + 1;
53
        end if;
54

55
        state        <= Idle;
56
      else
57
        case state is
58
          when Idle =>
59
            if (FSL0_S_Exists = '1') then
60
              state       <= Read_Inputs;
61
            end if;
62

63
          when Read_Inputs =>
64
            if (FSL0_S_Exists = '1') then
65
          --
66
          bram_data <= BRAM(conv_integer(FSL0_S_Data));
67
          --
68
              state <= Write_Outputs;
69
            end if;
70

71
          when Write_Outputs =>
72
            if (FSL0_M_Full = '0') then
73
          state <= Idle;
74
            end if;
75
        end case;
76
      end if;
77
    end if;
78
   end process The_SW_accelerator;
79
end architecture EXAMPLE;
Gast #1488813
Lesenswert?

Ja wird das denn nicht an folgender Stelle gemacht:

[vhdl]

FSL0_S_Read  <= FSL0_S_Exists   when state = Read_Inputs   else '0';
FSL0_M_Write <= not FSL0_M_Full when state = Write_Outputs else '0';

[\vhdl]

Das habe ich aus dem Beispiel übernommen, das Xilinx generiert, wenn man 
den Coprocessor-Wizard benutzt.

Im übrigen muss ich mich korrigieren. Hatte nen kleinen Fehler im 
C-Code. Es ist so, dass ich den put-Befehl mache, daraufhin dne 
get-Befehl wie oben beschrieben, aber dass sich schon beim ersten 
Durchlauf nichts mehr tut, da das fsl_isinvalid liefert nach dem 
get-Befehl immer eine '1'. Also siehts so aus, als würde mein IP Core 
nichts auf den bus schreiben...
Persönliche Seite #1488825
Lesenswert?

ChrisB schrieb:
> C-Code. Es ist so, dass ich den put-Befehl mache, daraufhin den
Zeig mal den Code... wichtig ist u.A. das du erst einmal was schreibst 
und dann liest, sonst lauft deine Statemachine nicht weiter.
Das invalid, ist mein ich auch nur bei non_blocking interessant.
Ich würde auch erstmal konstante Werte geben nicht das das Problem an 
deinem BRAM Code liegt...
Gast #1488838
Lesenswert?

Ja, das war mein erster Fehler... Jetzt läuft alles rund. Ich lege eine 
Adresse mit put an und mit get bekomme ich den vorinitialisierten Wert 
aus dem BRam.
Soweit so gut, dann kanns jetzt weitergehn.

Danke nochmal!

Gruß
Gast #1490036
Lesenswert?

Mal eine allgemeine Frage zum BRam und VHDL.

Mit:
1
type bram_type is array ((2**bram_addr_width)-1 downto 0) of std_logic_vector(bram_data_width-1 downto 0);
2
signal BRAM : bram_type;
3

4
signal bram_num   : std_logic_vector (0 to bram_addr_width);
definiere ich mein Ram.
Momentan kann ich leider nur mit:
1
BRAM(conv_integer(bram_num)) <= x"0F0F0F0F";
oder
1
BRAM(to_integer(unsigned(bram_num))) <= x"0F0F0F0F";
auf das BRam zugreifen, da bram_num vom Typ std_logic_vector ist.
Welches der beiden Möglichkeiten ist die bessere, bzw. eventuell 
einfacher und platzsparender im Design? Hat die Konvertierung von 
std_logic_vector zu integer überhaupt einfluss auf das Design?
Gibt es eine Möglichkeit das BRam direkt durch einen std_logic_vector zu 
adressieren, anstatt eines integers?
Gast #1490057
Lesenswert?

Alles klar, danke.

Noch eine andere Frage die sich mir gerade auftut: Im EDK sehe ich in 
der Design Summary, dass für mein coprozessor ein Haufen FlipFlops und 
LUT's benutzt werden, jedoch kein BRam.
Wird mein bram aus dem obigen Beispiel tatsächlich aus FlipFlop's und 
LUT's aufgebaut anstatt aus wirklichem BRam?
Gast #1490105
Lesenswert?

Meinst du damit, dass ich die Leseadresse bei einem Takt erst in ein 
Register schreiben muss und erst beim nächsten Takt mit der Adresse aus 
diesem Register auf das BRam zugreifen kann?
Muss das beim Schreiben nicht gemacht werden?
Moderator (Firma: Titel) Persönliche Seite #1490115
Lesenswert?

Auf das Lesen kommt es an. Dort siehst du die Unterschiede:
http://www.lothar-miller.de/s9y/archives/20-RAM.html

EDIT:
> Meinst du damit, dass ich die Leseadresse bei einem Takt erst in ein
> Register schreiben muss und erst beim nächsten Takt mit der Adresse aus
> diesem Register auf das BRam zugreifen kann?
Richtig.
> Muss das beim Schreiben nicht gemacht werden?
Nein, das Schreiben ist sowieso schon synchron.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren