mikrocontroller.net

Forum: FPGA, VHDL & Co. FPGA, Datenbus & Register


Autor: John (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich will gerne einen FPGA mit dem Datenbus eines Mikrocontrollers 
verbinden.
Ich habe nun also 10 Adressleitungen sowie 8 Datenleitungen mit dem FPGA 
verbunden, ausserdem noch WE, OE und CE.
Nun sollen in dem FPGA mehrere "Register" erstellt werden, wo ich was 
speichern kann, und der Inhalt dieser Register beeinflusst dann 
bestimmte Vorgänge im FPGA (z.B. macht der FPGA eine 12 Phasen PWM, und 
über ein entsprechendes 16 Bit breites Register soll der Tastgrad davon 
eingestellt werden können).

Jetzt habe ich dazu mehrere Fragen.
Erstmal: wie mache ich das Interface zum Datenbus, dass es auch sicher 
funktioniert?

Ich habe folgendes:
entity test is
  port(
    clk : in std_ulogic;
    d : inout std_logic_vector(7 downto 0);
    a : in std_logic_vector(9 downto 0);
    we : in std_logic;
    oe : in std_logic;
    ce : in std_logic
    );
end project;

architecture behv of test is
  signal dat : std_logic_vector(7 downto 0);
begin
  process begin
    wait until rising_edge(CLK);
    if ce = '0' then
      if oe = '0' then
        d <= dat;
      end if;
      if we = '0' then
        dat <= d;
      end if;
    else
      d <= (others => 'Z');
    end if;
  end process;
end architecture;

das soll mal als erster Test dienen, ob ich ein einzelnes Byte im FPGA 
speichern und wieder raus lesen kann. Wird es so funktionieren?

Des Weiteren soll natürlich jetzt Abhängig von der angelegten Adresse 
der Wert in unterschiedlichen Registern abgelegt werden. Das hier
entity test is
  port(
    clk : in std_ulogic;
    d : inout std_logic_vector(7 downto 0);
    a : in std_logic_vector(9 downto 0);
    we : in std_logic;
    oe : in std_logic;
    ce : in std_logic
    );
end project;

architecture behv of test is
  signal r0 : std_logic_vector(7 downto 0);
  signal r1 : std_logic_vector(7 downto 0);
  signal r2 : std_logic_vector(7 downto 0);
begin
  process begin
    wait until rising_edge(CLK);
     if ce = '0' then
      if oe = '0' then
        case to_integer(unsigned(a)) is
          when 0 =>
            d <= r0;
          when 1 =>
            d <= r1;
          when 2 =>
            d <= r2;
          when others =>
            null;
        end case;
      end if;
      if we = '0' then
        case to_integer(unsigned(a)) is
          when 0 =>
            r0 <= d;
          when 1 =>
            r1 <= d;
          when 2 =>
            r2 <= d;
          when others =>
            null;
        end case;
      end if;
    else
      d <= (others => 'Z');
    end if;
  end process;
end architecture;

funktioniert vielleicht, aber ist sehr unelegant. Gibt es dafür eine 
einfachere Schreibweise?

Noch was:
Der Mikrocontroller, der das ganze steuern soll, ist ein LPC2378. Es 
kann durchaus auch vorkommen, dass ein Register mehr als 8 Bits breit 
ist; z.B. eben bei der PWM - der Tastgrad wird über 16 Bits eingestellt. 
Ich kann wohl im Programm des Mikrocontrollers einen 16 Bit 
Speicherzugriff realisieren; doch wie schaut dies dann aus Sicht des 
FPGAs aus? Wie muss ich mit den Registern hantieren, um am Schluss den 
korrekten 16 Bit Wert zu erhalten?

Ich hoffe, ihr könnt mir ein paar Tipps geben. Bin gespannt :)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wird es so funktionieren?
Oft. Aber garantiert nicht immer.
Denn die Signale des uCs sind (vermutlich) asynchron zum FPGA-Takt.

Zudem wirst du Treiberkonflikte auf dem Datenbus bekommen, denn das 
Abschalten der Treiber erfolgt nicht direkt mit we, sondern mit dem 
nächsten FPGA-Takt...

> Erstmal: wie mache ich das Interface zum Datenbus, dass es auch sicher
> funktioniert?
Wie hoch ist dein uC-Takt?
Wie hoch ist dein FPGA-Takt?
Kannst du den FPGA-Takt mit dem uC-Takt koppeln (synchrones Design)?
Hast du die Möglichkeit Waitstates für den Buszugriff zu konfigurieren?

> Wie muss ich mit den Registern hantieren, um am Schluss den
> korrekten 16 Bit Wert zu erhalten?
Lies mal nach, wie uCs das intern machen:
Da wird z.B. zuerst das untere Byte in ein Schattenregister geschrieben, 
und nur wenn gleich danach das obere Byte kommt, wird das komplette Wort 
ins FPGA übernommen...

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als erstes empfehle ich dir eine Simulation, dann siehst du schnell, was 
schief läuft.

Wie Lothar schon sagte, mach die I/O Umschaltung am besten 
kombinatorisch:
d <= dat when oe = '0' and ce = '0' else (others => 'Z');

Sonst bekommst du in der Simulation schöne rote 'X' und in der Hardware 
eventuell Treiber-Defekte oder zumindest stark erhöhte Stromaufnahme...

Autor: John (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Lothar,
die Signale vom Daten- und Adressbus und die Steuersignale sind synchron 
zum FPGA-Takt, denn der FPGA-Takt ist gleich dem CPU-Takt. Somit dürfte 
das kein Problem darstellen, oder?
Wie kann ich die Datenbustreiber zum richtigen Zeitpunkt abschalten? 
Kannst du mir mal einen Codeschnipsel geben.
Der Takt beträgt 48 MHz, und ich kann beliebige Waitstates konfigurieren 
(aber ich möchte natürlich so wenige wie nur möglich verwenden).

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> denn der FPGA-Takt ist gleich dem CPU-Takt.
Dann hast du tolles Glück und mußt nur mit geeigneten Mittel (Xilinx: 
DCM) den Skew (Laufzeitversatz) zwischen dem FPGA-Takt und dem uC-Takt 
korrigieren.
Der Vorteil dabei ist, dass du (höchstwahrscheinlich) ganz ohne 
Waitstates auskommen wirst.

> Wie kann ich die Datenbustreiber zum richtigen Zeitpunkt abschalten?
Wie bereits von Christian gepostet.
Alles getaktete käme (um genau einen Takt) zu spät  :-/

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo John,

nach den sachdienlichen Hinweisen von Lothar und Christian:

>Erstmal: wie mache ich das Interface zum Datenbus, dass es auch sicher 
funktioniert?

Neben der reinen logischen Funktion musst Du noch das korrekte Timing 
sicherstellen...

Hierzu musst Du die Setup und Hold Anforderungen deiner CPU deinem FPGA 
als Constraint mitgeben.
Zusaetzlich waere es sinnvoll die Taktgeschwindigkeit ebenfall mit 
zuzugeben.

Gruss

Andreas

Autor: John (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
danke für eure Tipps!
könnt ihr mir noch sagen, wie ich das im Altera Quartus II einstelle? 
ich denke, das wird sicher über den Assignment Editor passieren, nur 
weiss ich nicht genau wo.

Autor: John (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe mal ein bisschen gegoogelt, und ein Projekt gefunden, wo mit 
einem CPLD etwas ähnliches gemacht wurde.
Nun habe ich meinen VHDL-Code umgeschrieben:

write_proc : process begin
  wait until falling_edge(clk);
  if ce = '0' and we = '0' then
    my_register <= d;
  end if;
end process;

read_proc : process begin
  wait until falling_edge(clk);
  if ce = '0' and oe = '0' then
    dat <= my_register;
  end if;
end process;

d <= dat when ce = '0' and oe = '0' else (others => 'Z');


Ich habe anhand eines Timing-Diagramms herausgefunden, dass immer bei 
der fallenden Taktflanke die Adressen und Daten gültig sind.

Autor: John (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann mir keiner weiterhelfen?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast keine Frage gestellt...   :-o

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann das Ganze auch per Schemaeingabe zusammenclicken...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.