www.mikrocontroller.net

Forum: FPGA, VHDL & Co. I/O Port so OK?


Autor: Marko B. (glagnar)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

vorgestern habe ich mit VHDL angefangen. Erstes Projekt sollte ein 8-bit 
I/O Port mit Datenrichtungsregister (Port laesst sich bitweise auf 
Eingang oder Ausgang umschalten) und Intel-Bus (z.B. fuer 8051) sein. 
Hier ist mein Code, der fehlerfrei synthetisiert wird (ISE 13.1) und 
auch in der Simulation korrekt laeuft (s. Anhang).

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity intelbus is
    Port ( data : inout  STD_LOGIC_VECTOR (7 downto 0);  -- data bus
           addr : in  STD_LOGIC;                  -- address bit
        p0 : inout STD_LOGIC_VECTOR (7 downto 0);    -- i/o port
           rd : in  STD_LOGIC;                  -- /RD
           wr : in  STD_LOGIC;                  -- /WR
           res : in  STD_LOGIC;                  -- /RESET
           cs : in  STD_LOGIC);                  -- /CS
end intelbus;

architecture Behavioral of intelbus is

signal p0reg: std_logic_vector (7 downto 0);
signal ddr0: std_logic_vector (7 downto 0);

begin

process(res,rd,wr,cs,data) is
begin

  if (cs = '1') then
    data <= (others => 'Z');

  else  
    if falling_edge(wr) then
      if(addr = '0') then
        p0reg <= data;
      else
        ddr0 <= data;
      end if;
    end if;
  
    if falling_edge(rd) then
      if(addr = '0') then
        data <= p0;
      else
        data <= ddr0;
      end if;
    end if;
  end if;

  --asynchronous reset
  if (res = '0') then
    p0reg <= (others => '0');
    ddr0 <= (others => '0');
  end if;
  
  if (rd = '1') then
    data <= (others => 'Z');
  end if;
  
end process;

G: for i in 0 to 7 generate
  p0(i) <= p0reg(i) when ddr0(i) = '1' else 'Z';
end generate G;

end Behavioral;

Wuerde mich freuen wenn jemand kommentieren koennte ob alles OK ist oder 
ob man etwas besser/anders machen koennte.

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dir fehlt jegliche Synchronisation auf einen Takt und noch dazu ein 
asynchroner Reset.

Das wird in realer Hardware nur sehr glitchig laufen, denn du versuchst 
auf Kontrollsignale taktmäßig zu triggern.

Eigentlich ist da alles falsch, was ein Anfänger falsch machen kann.

Autor: Marko B. (glagnar)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Aha, was waeren Deine konkreten Vorschlaege?

Ich will Dich ja nicht belehren, aber der Intel-Bus ist asynchron, da 
gibts keinen Takt.

Der Schaltplan (s. Anhang) sieht fuer mich OK aus (etwas vereinfachter 
Code, damit die Multiplexer rausfallen): die Register werden ueber das 
/WR-Signal getaktet.

Das ganze ist uebrigens fuer ein CPLD gedacht (XC9500).

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

Bewertung
0 lesenswert
nicht lesenswert
Marko B. schrieb:
> Aha, was waeren Deine konkreten Vorschlaege?
Das muß nicht alles in 1 Prozess, dann passiert es auch nicht, dass 
unnötige Signale in der Sensitivliste auftauchen (data)...

Die Richtungsumschaltung machst du besser concurrent:
signal din  : STD_LOGIC_VECTOR (7 downto 0);
signal dout : STD_LOGIC_VECTOR (7 downto 0);
:
:
  -- Schreiben
  process (res,wr) begin
    if (res = '0') then
      p0reg <= (others => '0');
      ddr0 <= (others => '0');
    elsif rising_edge(wr) then  --< ressourcenschonender
--  elsif (wr='0') then         --< eigentlich richtiger
      if(addr = '0') then
        p0reg <= din;
      else
        ddr0 <= din;
      end if;
    end if;
  end process;

  -- Daten fürs Lesen bereitstellen
  dout <= p0 when addr = '0' else
          ddr0;

  -- Busverwaltung
  din  <= data;
  data <= (others => 'Z') when rd='1' or cs='1' else
          dout;

> Erstes Projekt sollte ein 8-bit I/O Port mit Datenrichtungsregister
> (Port laesst sich bitweise auf Eingang oder Ausgang umschalten) und
> Intel-Bus (z.B. fuer 8051) sein.
Diese Busse sind eigentlich nicht getaktet (auch nicht auf rd bzw. wr). 
Sondern da wird bei low-aktivem Signal gelatcht. Der richtige 
Zeitpunkt zur Datenübernahme ist also die steigende Flanke des 
wr-Signals...

Marko B. schrieb:
> Das ganze ist uebrigens fuer ein CPLD gedacht (XC9500).
Das hätte ganz an den Anfang der Frage hingehört. Es ist nämlich ein 
eklatanter Unterschied, ob du ein synchrones Design auf einem FPGA hast, 
oder irgendwelche Tricksereien auf einem CPLD... :-/

Autor: Lattice User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast recht, dein Takt ist das wr Signal. Da glitcht nichts wenn der 
Busmaster sich an die Spec hält, und davon sollte man ausgehen können. 
Auch ein 8051 benimmt sich nicht wenn man ihn falsch ansteuert.

Zum Lesen würde ich allerdings nicht falling_edge(rd) verwenden, das 
lässt sich rein kombinatorisch ausführen.

Autor: Lattice User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bah, ich schreibe zu langsam, bzw denke zuviel dabei.

Lothar Miller schrieb:
> Das hätte ganz an den Anfang der Frage hingehört. Es ist nämlich ein
> eklatanter Unterschied, ob du ein synchrones Design auf einem FPGA hast,
> oder irgendwelche Tricksereien auf einem CPLD... :-/

Für die Aufgabe ist das finde ich egal. Es ist nunmal kein getaktetes 
Design mit einer ständigen Clock.

Fertig hinschreiben hätte meine Ansicht nach nicht sein müssen, was 
lernt er jetzt noch?

PS: Ich habe in meiner Antwort 8051 mit 8255 verwechselt.

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

Bewertung
0 lesenswert
nicht lesenswert
Lattice User schrieb:
> Für die Aufgabe ist das finde ich egal. Es ist nunmal kein getaktetes
> Design mit einer ständigen Clock.
Klar, in so ein CPLD passt ja nicht arg viel mehr rein...  ;-)

Aber man müsste die Sache wesentlich tiefer angehen, wenn da eine zweite 
Taktdomäne mit im Spiel wäre...

Autor: Marko B. (glagnar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:

> Das muß nicht alles in 1 Prozess, dann passiert es auch nicht, dass
> unnötige Signale in der Sensitivliste auftauchen (data)...

Hatte ich sogar anfangs versucht, wurde aber durch "multiple drivers" 
Fehler frustriert.

> Die Richtungsumschaltung machst du besser concurrent:
>
> signal din  : STD_LOGIC_VECTOR (7 downto 0);
> signal dout : STD_LOGIC_VECTOR (7 downto 0);
> :
> :
>   -- Schreiben
>   process (res,wr) begin
>     if (res = '0') then
>       p0reg <= (others => '0');
>       ddr0 <= (others => '0');
>     elsif rising_edge(wr) then  --< ressourcenschonender
> --  elsif (wr='0') then         --< eigentlich richtiger
>       if(addr = '0') then
>         p0reg <= din;
>       else
>         ddr0 <= din;
>       end if;
>     end if;
>   end process;
> 
>   -- Daten fürs Lesen bereitstellen
>   dout <= p0 when addr = '0' else
>           ddr0;
> 
>   -- Busverwaltung
>   din  <= data;
>   data <= (others => 'Z') when rd='1' or cs='1' else
>           dout;
> 

Ah, super. Das ist natuerlich deutlich eleganter :)

>> Erstes Projekt sollte ein 8-bit I/O Port mit Datenrichtungsregister
>> (Port laesst sich bitweise auf Eingang oder Ausgang umschalten) und
>> Intel-Bus (z.B. fuer 8051) sein.

> Diese Busse sind eigentlich nicht getaktet (auch nicht auf rd bzw. wr).
> Sondern da wird bei low-aktivem Signal gelatcht.

Ich hatte als erstes eine Level-getriggerte Version versucht, aber die 
ganzen Warnungen bzgl. "Latch found" haben mich dann auf die obige 
Version gefuehrt.

> Der richtige Zeitpunkt zur Datenübernahme ist also die steigende
> Flanke des wr-Signals...

Das hatte ich aber anders gelesen:

"If the 8051 is writing data, it appears on the bus following the 
address information, and the active-low write signal, WR_, indicates 
that the data is available. The falling edge of WR_ is typically used to 
capture the data from the bus."

http://www.design-reuse.com/articles/8692/fpga-des...

Fuer RD ist die kombinatorische Variante natuerlich viel eleganter.

>> Das ganze ist uebrigens fuer ein CPLD gedacht (XC9500).

> Das hätte ganz an den Anfang der Frage hingehört. Es ist nämlich ein
> eklatanter Unterschied, ob du ein synchrones Design auf einem FPGA hast,
> oder irgendwelche Tricksereien auf einem CPLD... :-/

Wieso dieses? Koennte man obigen Code so nicht in ein FPGA packen?

Danke uebrigens fuer den Code und die Erklaerungen!

Lattice User schrieb:

> Fertig hinschreiben hätte meine Ansicht nach nicht sein müssen, was
> lernt er jetzt noch?

Ich glaube fuer einen Anfaenger ist es schon extrem hilfreich, wenn man 
einen kompletten lauffaehigen Code hat, an dem man sich orientieren 
kann. Ausserdem ist das ja nur ein Hello World. Als naechstes kommt eine 
DMA Engine fuer einen 6502 :D

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

Bewertung
0 lesenswert
nicht lesenswert
Marko B. schrieb:
> Hatte ich sogar anfangs versucht, wurde aber durch "multiple drivers"
> Fehler frustriert.
Und dann hast du dir selber was in die Tasche gelogen und alles in 1 
Prozess gepackt...   :-o

> The falling edge of WR_ is typically used to capture the data from the
> bus."
Sieh dir die Timing-Diagramme an: an der steigenden Flanke hast du 
wesentlich mehr Setupt-Zeit. Und die brauchst du eher, als die lange 
Hold-Zeit...

> Koennte man obigen Code so nicht in ein FPGA packen?
Doch, aber idR. läuft so ein FPGA-Design mit einem Takt um 50-100MHz. 
Und der externe uC/ISA ist dazu asynchron und damit wie ein solches 
Signal zu behandeln. Will heissen: Einsynchronisieren tut Not.

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.