www.mikrocontroller.net

Forum: FPGA, VHDL & Co. cpld SRAM Interface in VHDL


Autor: befro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo an Alle,

für mein kleines CPLD-Projekt brauche ich ein Interface für ein SRAM 
128K*8Bit.

Das Interface hat einen internen Adresscounter, der über ein Clock 
Leitung sowei Reset gesteuert wird. Auserdem gibt es eine Leitung, die 
bestimmt, ob vom Ram gelesen oder ins Ram geschrieben werden soll. Das 
Interface soll einen Dateneingang und einen Datenausgang haben ( also 
nicht Tri-State ).

Hier mein erster Entwurf, vielleicht kann mir jemand sagen, ob es so 
gehen könnte:
entity RamInterface is
    Port ( 
        -- RAM SIGNALS
        ramAddress : out  STD_LOGIC_VECTOR (16 downto 0);
        ramData : inout  STD_LOGIC_VECTOR (7 downto 0);
        ramNWE : out  STD_LOGIC;
        ramNOE : out  STD_LOGIC;
        
        -- Interface Signals
        dataOut : out  STD_LOGIC_VECTOR (7 downto 0);
        dataIn : in  STD_LOGIC_VECTOR (7 downto 0);
        clk : in  STD_LOGIC;
        clkNextValue : in  STD_LOGIC;
        ReadOrNSample : in  STD_LOGIC;
        Reset : in STD_LOGIC);  
end RamInterface;

architecture Behavioral of RamInterface is
signal ramAddressCounter: STD_LOGIC_VECTOR (16 downto 0 );

begin
EinProzessModell: process(clk,clkNextValue,readOrNSample,ramAddressCounter, dataIn)
begin
  if rising_edge(clkNextValue) then
    if Reset = '0' then
      ramAddressCounter <= ramAddressCounter+1;
    else
      ramAddressCounter <= ( others => '0' );
    end if;
  end if;  
  
  if readOrNSample = '1' then -- Daten vom Ram lesen
    ramData <= ( others => 'Z' ); -- CPLD Interface hochohmig
    ramNOE <= '0'; -- Ram Ausgang einschalten 
    ramNWE <= '1'; -- Ram write disable
    dataOut <= ramData ; -- Daten vom Ram auf Interface output
  else -- Daten in Ram schreiben
    ramNOE <= '1'; -- Ram Ausgang ausschalten 
    ramNWE <= '0'; -- Ram write enable
    ramData <= dataIn; -- Daten vom Interface  ins RAM schreiben
  end if;
end process EinProzessModell;

ramAddress <= ramAddressCounter;

end Behavioral;

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

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Einprozessmodell hast du offenbar extrem weit gefasst :-/

Es ist nicht "State of the Art", einen getakteten und einen 
kombinatorischen Teil zusammen in einen Prozess zu packen. Du wirst 
daran später sicher noch deine Freude haben. Nur mal angenommen, du 
änderst irgendwann was, machst die Änderungen wieder raus und bekommst 
sowas:
EinProzessModell: process(clkNextValue)
begin
  if rising_edge(clkNextValue) then
    if Reset = '0' then
      ramAddressCounter <= ramAddressCounter+1;
    else
      ramAddressCounter <= ( others => '0' );
  end if;  
  
  if readOrNSample = '1' then -- Daten vom Ram lesen
    ramData <= ( others => 'Z' ); -- CPLD Interface hochohmig
    ramNOE <= '0'; -- Ram Ausgang einschalten 
    ramNWE <= '1'; -- Ram write disable
    dataOut <= ramData ; -- Daten vom Ram auf Interface output
  else -- Daten in Ram schreiben
    ramNOE <= '1'; -- Ram Ausgang ausschalten 
    ramNWE <= '0'; -- Ram write enable
    ramData <= dataIn; -- Daten vom Interface  ins RAM schreiben
    end if;
  end if;
end process EinProzessModell;
Na, siehst du den Fehler auf Anhieb?

Das Ein-, Zwei- usw. Modell gilt ugs. nur für State-Machines, nicht für 
allgemeine Beschreibungen ;-)

Schreibs besser so:
-- Adresszähler
process(clk,clkNextValue,readOrNSample,ramAddressCounter, dataIn)
begin
  if rising_edge(clkNextValue) then
    if Reset = '0' then
      ramAddressCounter <= ramAddressCounter+1;
    else
      ramAddressCounter <= ( others => '0' );
    end if;  
  end if;  
end process;

-- Kombinatorik
process(readOrNSample, dataIn)
begin
  if readOrNSample = '1' then -- Daten vom Ram lesen
    ramData <= ( others => 'Z' ); -- CPLD Interface hochohmig
    ramNOE <= '0'; -- Ram Ausgang einschalten 
    ramNWE <= '1'; -- Ram write disable
    dataOut <= ramData ; -- Daten vom Ram auf Interface output
  else -- Daten in Ram schreiben
    ramNOE <= '1'; -- Ram Ausgang ausschalten 
    ramNWE <= '0'; -- Ram write enable
    ramData <= dataIn; -- Daten vom Interface  ins RAM schreiben
  end if;
end process;

BTW:
Du solltest das Datenblatt deines SRAMs mal genau anschauen, ob du nach 
einem Schreibzugriff sofort wieder lesen darfst. Da gibt es durchaus 
Einschränkungen  :-o

Autor: befro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Na, siehst du den Fehler auf Anhieb?
Ich vermute Du meinst die Empfindlichkeitsliste?

>Du solltest das Datenblatt deines SRAMs mal genau anschauen, ob du nach
>einem Schreibzugriff sofort wieder lesen darfst.

Ein wenig problematisch ist meine Implementierung wahrscheinlich schon. 
Bei den SRAMs wird das Schreiben normalerweise über ein low/high Flanke 
am WE (write enable pin, bei mir ramNWE ) gesteuert. Die Adressen und 
Daten müssen eine bestimmte Zeit vorher schon anliegen. Ich habe den WE 
pin quasi fix auf den Wert ReadOrNSample geklemnnt, der für das lesen 
von n-Samples auf 0 gelegt wird. Meine Hoffnung ist, dass durch das 
Weiterschalten der Adresse die Daten auch schon so übernommen werden. 
Zugegebenermaßen etwas murksig, aber ich dachte mir, so kann ich eine 
State-Machine für das korrekte toggeln der Signale sparen. Vor allen 
Dingen, weil das lesen der N-Samples mit vollem Systemtakt erfolgen 
soll.
Ein weiteres Problem, bei dem ich mir noch nicht so sicher bin, ist, ob 
die Datenübertragung vom VHDL-Speicherinterface zur Restlogik 
zuverlässig funktioniert, oder ob man dafür noch zusätzliche Ein und 
Ausgangslatches einbauen sollte.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch das Output Enable des FPGA's wirkt nicht sofort, sondern mit einer 
gewissen Verzögerung, die größer ist, als die Laufzeit eines "normalen" 
Pins.
DataIn erscheint deshalb am Pin später als z.B. ramNWE.

Das mußt Du auch beim Hochohmig schalten berücksichtigen.
Wenn ramNWE zurück auf high geht, und das SRAM wieder die Ausgänge 
aktiviert, aber das FPGA noch nicht hochohmig ist, kommt es zu 
Konflikten auf dem Bus.

Autor: befro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Auch das Output Enable des FPGA's wirkt nicht sofort, sondern mit einer
>gewissen Verzögerung, die größer ist, als die Laufzeit eines "normalen"
>Pins.

Deshalb hier eine neue Version des SRAM-Interfaces. Hier habe ich 
versucht, das Timing von WE und OE so hinzuschieben, dass kein 
Buskonflickt auftritt. Vom Timing her scheint das Ganze jetzt 
einigermaßen zu stimmen, aber irgendwie klappt es nicht den Datenport 
des CPLDs laut Simulation hochohmig zu schalten ( ramData = "ZZZZZZZZ" 
). Habt Ihr eine Idee, woran es liegen könnte?
entity RamInterface is
    Port ( 
        -- RAM SIGNALS
        ramAddress : out  STD_LOGIC_VECTOR (16 downto 0);
        ramData : inout  STD_LOGIC_VECTOR (7 downto 0):="ZZZZZZZZ";
        ramNWE : out  STD_LOGIC;
        ramNOE : out  STD_LOGIC;
        
        -- Interface Signals
        dataOut : out  STD_LOGIC_VECTOR (7 downto 0);
        dataIn : in  STD_LOGIC_VECTOR (7 downto 0);
        clk : in  STD_LOGIC;
        clkNextValue : in  STD_LOGIC;
        ReadOrNSample : in  STD_LOGIC;
        Reset : in STD_LOGIC);  
end RamInterface;

architecture Behavioral of RamInterface is
signal ramAddressCounter: STD_LOGIC_VECTOR (16 downto 0 ):="00000000000000000";
signal rns_delayed: STD_LOGIC:='1';
signal ramDataOutEnable: STD_LOGIC:='0'; --disable output buffer

begin
EinProzessModell: process(clk,clkNextValue,readOrNSample,ramAddressCounter, dataIn)
begin
  
  if rising_edge(clkNextValue) then
    if Reset = '0' then
      ramAddressCounter <= ramAddressCounter+1;
    else
      ramAddressCounter <= ( others => '0' );
    end if;  
    rns_delayed <= readOrNSample; -- verzögertes read/write Umschaltsignal
  end if;  
  
  if readOrNSample = '1' then -- Daten vom Ram lesen
    ramData <= ( others => 'Z' ); -- CPLD Interface hochohmig
    ramNWE <= '1'; -- Ram write disable
    dataOut <= ramData ; -- Daten vom Ram auf Interface output
  
  else -- Daten ins Ram schreiben
    ramNWE <= clkNextValue or clk;
    if ramDataOutEnable ='1' then
      ramData <= dataIn; -- Daten vom Interface  ins RAM schreiben
    --else ramData <= (others => 'Z');
    end if;
  end if;
end process EinProzessModell;

ramDataOutEnable <= not (rns_delayed or readOrNSample );
ramNOE <= not (rns_delayed and readOrNSample );

ramAddress <= ramAddressCounter;

end Behavioral;


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.