www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Single Dual Port RAM, delay time einstellen


Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte gerne ein kontinuierliches Signal um eine bestimmte 
(einstellbare) delay time verzögert ausgeben. Dazu dachte ich mir dies 
in ein Dual Port Ram verwirklichen, in dem ich in eine Adresse schreibe 
und in die andere Adresse auslese. Und der die delaytime rechnet sich 
dann doch theoretisch aus RD_PTR = WR_PTR - (Zeit/ OFFSET).

So dualport in xilinx core generator erstellt, Breite 12 bit und tiefe 
1024.

Jetzt weis ich nur nicht wie ich dieses Verhältniss oben am besten 
realisere??

Benutze ein SPARTAN 6...


Kann mir da jemand ein Tipp geben...?


Gruss

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

Bewertung
0 lesenswert
nicht lesenswert
> ich möchte gerne ein kontinuierliches Signal um eine bestimmte
> (einstellbare) delay time verzögert ausgeben.
Um welche Zeiten handelt es sich?
Mit welcher Genauigkeit/Auflösung soll die Einstellbarkeit erfolgen?
Welchen Takt hast du?

>  Dazu dachte ich mir dies in ein Dual Port Ram verwirklichen,
Du brauchst einen FIFO. Den kannst du mit einem BRAM realisieren, 
allerdings ist sowohl das Schreiben wie auch das Lesen von einem Takt 
abhängig.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

also ich lese das 12 bit breite Signal mit 20 Mhz rein, d.h alle 
0,05usek ein signal. mit einer genauigkeit von 1 promil.

Ich möchte das Signal um max. 900 stellen verzögert ausgeben, dies aber 
einstellbar veränder können.


Gruss

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

Bewertung
0 lesenswert
nicht lesenswert
> mit einer genauigkeit von 1 promil.
Die 20Mhz sind auf 1 Promille genau?

> um max. 900 stellen verzögert ausgeben
Also um 0..900*50ns = 0..45us?
Und die Ausgabe soll synchron zu den 20MHz sein?
Dann brauchst du einen FIFO mit 900 Speicherplätzen. Am einfachsten 
machst du den selber über ein DPRAM mit 1024 Worten Speichertiefe, bei 
dem der Lesezähler über einen Offset dem Schreibzähler folgt.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die 20Mhz sind auf 1 Promille genau?
Genau

> Also um 0..900*50ns = 0..45us?
Genau

>Und die Ausgabe soll synchron zu den 20MHz sein?
Genau

>Dann brauchst du einen FIFO mit 900 Speicherplätzen. Am einfachsten
machst du den selber über ein DPRAM mit 1024 Worten Speichertiefe, bei
dem der Lesezähler über einen Offset dem Schreibzähler folgt.folgt.

Genau soweit bin ich gedanklich auchgekommen, den DPRAM mit 
coregenerator hab ich schon erstellt,


nun wie muss mein vhdlcode ausschuen um den LESEZHÄHLER mit OFFSET zu 
versehen und diesen OFFSET als einstellbar zu realisieren...

Danke

Gruss

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

Bewertung
0 lesenswert
nicht lesenswert
> um den LESEZHÄHLER mit OFFSET zu versehen
Mal angenommen, deine Zähler wären integer und du würdest numeric_std 
verwenden:
   port (  ...
           offset : std_logic_vector(9 downto 0); -- Offset in 50ns Schritten
           ... );

   :
   signal RD_PTR : integer range 0 to 1023;
   signal WR_PTR : integer range 0 to 1023;
   :
   :
   if (offset=(offest'range=>'0')) then -- Sonderbehandlung: keine Verzögerung
      dout <= din;
   else
      RD_PTR <= to_integer(to_unsigned(WR_PTR,10)-unsigned(offest));
   end if;  

Wenn es std_logic Vektoren sind, müssen die Casts ein wenig anders 
aussehen:
   port (  ...
           offset : std_logic_vector(9 downto 0); -- Offset in 50ns Schritten
           ... );

   :
   signal RD_PTR : std_logic_vector(9 downto 0);
   signal WR_PTR : std_logic_vector(9 downto 0);
   :
   :
   if (offset=(offest'range=>'0')) then -- Sonderbehandlung: keine Verzögerung
      dout <= din;
   else
      RD_PTR <= std_logic_vector(unsigned(WR_PTR)-unsigned(offest));
   end if;  

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm...

mal ein vereinfachtes beispiel, ich hab als eingagn 4 bit signal und 
länge vom DPRAM 16 ... über coregenerator implementiere ich mir

COMPONENT TESTRAM
port (
  clka: IN std_logic;
  wea: IN std_logic_VECTOR(0 downto 0);
  addra: IN std_logic_VECTOR(3 downto 0);
  dina: IN std_logic_VECTOR(3 downto 0);
  clkb: IN std_logic;
  rstb: IN std_logic;
  addrb: IN std_logic_VECTOR(3 downto 0);
  doutb: OUT std_logic_VECTOR(3 downto 0)); 

 und über PORTMAP HAB ich dann die einzelnen signale zugewiesen..
DP1 : TESTRAM 
  
  Port Map ( clka => clk_2,
      wea => "1",
      addra => ADD1,
      dina => SAVEY,
      clkb =>clk_2,
      rstb => MASTERRESET,
      addrb =>ADD2,
      doutb => AUSGANG);


Ich denke jetzt müsste ich über addra und addrb diese logik 
implementieren

z.B hab ich folgendes probiert
ADD_TAKT:process (clk_A,reset)
  begin
  
    if clk_A = '1' and clk_A'event then
      if reset = '1' then
        ADDA1 <= "0000";
        ADDA2 <= ADDA1 -1;
        cnt <= 0;
      elsif (cnt= 16) then
        cnt<=0;
        ADDA1 <= "0000";
        
      else
        ADDA1 <= ADDA1 +1;
        
        cnt<=cnt+1;
      end if;
      
    end if;
    
  end process ADD_TAKT;
  
  ADDA <= ADDA1;
  ADDB <= ADDA1;


                                        

Als clk verwende ich ein 1 Hz takt, somit müsste ja das signal nach 8 
takten am ausgang erscheinen, was es auch tut, nur geht es dann wieder 
aus, und dann wieder nach paar takten an, und dann bleibt es auch 
dauerhaft an....

Wieso
Gruss

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

Bewertung
0 lesenswert
nicht lesenswert
> Als clk verwende ich ein 1 Hz takt, somit müsste ja das signal nach 8
> takten am ausgang erscheinen, was es auch tut, nur geht es dann wieder
> aus, und dann wieder nach paar takten an, und dann bleibt es auch
> dauerhaft an....
Mit visuellem Debuggen wird das nichts...
Du simulierst das einfach mal durch, dann kannst du auch interne 
signalverläufe sehen.

> somit müsste ja das signal nach 8 takten am ausgang erscheinen
16 Takte sind es.


Warum eigentlich zwei Zähler? ADDA und cnt zählen das selbe :-/
Probiers mal so:
    if clk_A = '1' and clk_A'event then
      if reset = '1' then
        ADDA1 <= "0000";
      else
        ADDA1 <= ADDA1+1;
      end if;
    end if;

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.