Hallo, ich würde gerne ein Signal um eine beliebige Anzahl von Takten verzögern. Die Forumsuche habe ich schon verwendet, jedoch bin ich nur auf den Lösungsansatz mit dem Schieberegister gekommen. Wenn ich diese Variante für mein Design verwende, verbrauche ich zuviele Ressourcen. Ich würde gerne ein 4KHz Signal um mindestens 2 Perioden permanent verzögern. Hab schon einwenig recherchiert, dass man es mit einem Counter realisieren kann. Nun meine Frage, ob jemand einen Beispiel-Code von so einer Verzögerung mittels Counter hat. lg
Christoph M. schrieb: > Hab schon einwenig recherchiert, dass man es mit einem Counter > realisieren kann. Das ist wie wenn ich schreibe: Ich hab gehört, dass man ein Auto mit Stahl realisieren kann... > Nun meine Frage, ob jemand einen Beispiel-Code von > so einer Verzögerung mittels Counter hat. Was du brauchst ist ein Ringpuffer, mit einer Speichertiefe von 2*fadc/4kHz Worten. Wenn du also dien Signal z.B. mit 48kHz abtastest, dann brauchst du einen Speicher mit 2*48/4 = 24 Worten > Ich würde gerne ein 4KHz Signal WAS für ein signal? Analog/Digital? > um mindestens 2 Perioden permanent verzögern. Um 2 Perioden von was? Ist die Frequenz des Signals konstant? Welche Abtastrate hat dein ADC? Und richtig: zur Realisierung eines Ringpuffers brauchst du (mindestens) einen Zähler. Aber viel wichtiger ist der Speicher...
Danke für die schnelle Antwort.... :) Lothar Miller schrieb: > Christoph M. schrieb: >> Hab schon einwenig recherchiert, dass man es mit einem Counter >> realisieren kann. > Das ist wie wenn ich schreibe: > Ich hab gehört, dass man ein Auto mit Stahl realisieren kann... Ja war ein bisschen blöd formuliert... :) Lothar Miller schrieb: >> Ich würde gerne ein 4KHz Signal > WAS für ein signal? Analog/Digital? >> um mindestens 2 Perioden permanent verzögern. > Um 2 Perioden von was? > Ist die Frequenz des Signals konstant? > Welche Abtastrate hat dein ADC? Es handelt sich um ein Rechtecksignal mit 4 KHz welches konstant bleibt. Dieses Signal möchte ich mit dem FPGA um 2 Perioden von diesen 4 Khz verzögern und wieder ausgeben. Das ganze hat nichts mit einem ADC zu tun ich möchte nur dieses 4 KHz Signal verzögern. Mir ist schon klar, ich muss einen Counter verwenden, wenn ein vorgegebener Wert erreicht ist habe ich dann auch meine Verzögerung erreicht. Jedoch wie gebe ich dann das Signal aus. Ich denk mal es ist ganz einfach nur ich komm da im Moment nicht weiter. Ich weiss nicht wie ich es ausgeben soll (das verzögerte 4 KHz Signal) lg
Welchen Jitter darf dieses verzögerte Signal maximal haben? 100ns? 1us? 10us?
Christoph M. schrieb: > Ich hab mir mal 1us als Grenze gesetzt. Dann wäre das gerade mal ein Schieberegister mit 250 Stellen. Das sind gerade mal 16 Luts, wenn die als Schieberegister geschaltet werden. Kleiner bekommst du das auch mit irgendwelchen Zählern und Speichern niemals hin... Du brauchst also 1. einen Zähler, der die die 1us Sample-Zeit erzeugt, und dann 2. das Schieberegister. Nehmen wir mal 50MHz FPGA-Takt. Dann sieht das so aus:
1 | :
|
2 | signal oneus_cnt : integer range 0 to 49 := 0; |
3 | signal sr = std_logic_vector(249 downto 0) := (others=>'0'); |
4 | :
|
5 | process begin |
6 | wait until rising_edge(clk); -- 50MHz |
7 | if (oneus_cnt=49) then |
8 | sr <= sr(sr'left-1 downto 0) & input; |
9 | oneus_cnt <= 0; |
10 | else
|
11 | oneus_cnt <= oneus_cnt+1; |
12 | end if; |
13 | end process; |
14 | |
15 | output <= sr(sr'left); |
16 | :
|
Hallo danke für deine Code, hab mein Taktfrequenz angepasst und siehe da es funktioniert :) Danke vielmals, einmal muss ich noch lästig sein, ist es möglich die Einstellung der Verzögerung sprich den Wert der Verzögerung variable zu machen?
Christoph M. schrieb: > siehe da es funktioniert :) Klar. ;-) > Danke vielmals, De nada. > einmal muss ich noch lästig sein, ist es möglich die Einstellung der > Verzögerung sprich den Wert der Verzögerung variable zu machen? Ja.
1 | port ( |
2 | in clk : std_logic; |
3 | in input : std_logic; |
4 | in delayus : std_logic_vector(7 downto 0); |
5 | :
|
6 | out output : std_logic; |
7 | :
|
8 | );
|
9 | :
|
10 | signal oneus_cnt : integer range 0 to 49 := 0; |
11 | signal sr = std_logic_vector(249 downto 0) := (others=>'0'); |
12 | :
|
13 | process begin |
14 | wait until rising_edge(clk); -- 50MHz |
15 | if (oneus_cnt=49) then |
16 | sr <= sr(sr'left-1 downto 0) & input; |
17 | oneus_cnt <= 0; |
18 | else
|
19 | oneus_cnt <= oneus_cnt+1; |
20 | end if; |
21 | end process; |
22 | |
23 | output <= sr(to_integer(unsigned(delay))); |
24 | :
|
Aber wenn du das zur Laufzeit machen willst, wird dich das Ressourcen kosten, weil dann keine LUTs mehr als Schieberegister verwendet werden können...
Lothar Miller schrieb: > Aber wenn du das zur Laufzeit machen willst, wird dich das Ressourcen > kosten, weil dann keine LUTs mehr als Schieberegister verwendet werden > können... dann kann man ein Block-RAM opfern und einen synchronen FIFO bauen. Ist zwar auch Verschwendung, aber das RAM ist eh' auf dem Chip vorhanden. Bei einem 2k*9 RAM koennte man sogar 2048*9 Werte fuer ein Signal speichern...
berndl schrieb: > dann kann man ein Block-RAM opfern und einen synchronen FIFO bauen. Das wäre auch elegant, dann könnte man auch den Jitter noch deutlich reduzieren und vor allem: dann brauchen wir wieder den bereits erwähnten Zähler.. ;-) Hier mal die obige Lösung mit 255 Abgriffen:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity Delayline is |
6 | Port ( clk : in STD_LOGIC; |
7 | input : in STD_LOGIC; |
8 | output : out STD_LOGIC; |
9 | delay : in STD_LOGIC_VECTOR (7 downto 0)); |
10 | end Delayline; |
11 | |
12 | architecture Behavioral of Delayline is |
13 | signal oneus_cnt : integer range 0 to 49 := 0; |
14 | signal wrptr : unsigned (7 downto 0) := (others=>'0'); -- unsigned wegen des kostenlosen wrap-arounds... ;-) |
15 | signal rdptr : unsigned (7 downto 0) := (others=>'0'); -- unsigned wegen des kostenlosen wrap-arounds... ;-) |
16 | type speicher is array(0 to 255) of STD_LOGIC; |
17 | signal memory : speicher; |
18 | begin
|
19 | |
20 | process begin |
21 | wait until rising_edge(clk); -- 50MHz |
22 | if (oneus_cnt=49) then |
23 | memory(to_integer(wrptr)) <= input; |
24 | wrptr <= wrptr+1; |
25 | rdptr <= wrptr-unsigned(delay); |
26 | oneus_cnt <= 0; |
27 | else
|
28 | oneus_cnt <= oneus_cnt+1; |
29 | end if; |
30 | end process; |
31 | |
32 | output <= memory(to_integer(rdptr)); |
Und tatsächlich: es wird hier ein DP-RAM erkannt, das dann aber wegen des geringen Speicherbedarfs in LUTs abgebildet:
1 | INFO:Xst:3231 - The small RAM <Mram_memory> will be implemented on LUTs in |
2 | order to maximize performance and save block RAM resources. If you want to |
3 | force its implementation on block, use option/constraint ram_style. |
4 | ----------------------------------------------------------------------- |
5 | | ram_type | Distributed | | |
6 | ----------------------------------------------------------------------- |
7 | | Port A | |
8 | | aspect ratio | 256-word x 1-bit | | |
9 | | clkA | connected to signal <clk> | rise | |
10 | | weA | connected to signal <_cmp_eq0000> | high | |
11 | | addrA | connected to signal <wrptr> | | |
12 | | diA | connected to signal <input> | | |
13 | ----------------------------------------------------------------------- |
14 | | Port B | |
15 | | aspect ratio | 256-word x 1-bit | | |
16 | | addrB | connected to signal <rdptr> | | |
17 | | doB | connected to signal <output> | | |
18 | ----------------------------------------------------------------------- |
Wir die Länge dann z.B. auf 8192 Bits aufgeblasen, dann kommt tsatsächlich das gewünschte BlockRAM heraus... ;-)
Hallo, ich hab mir die Realisierung mittels des Speichers nochmal angeschaut. Kann es sein, dass die Läösung mit den 255 Abgriffen aber nur eine Periode verzögter oder? Ich hab es mal angepasst für 2 Perioden bzw. ich denke es sollte so funktionieren.
1 | entity main is |
2 | Port ( reset : in STD_LOGIC; |
3 | clk : in STD_LOGIC; |
4 | referenz : in STD_LOGIC; |
5 | output : out STD_LOGIC); |
6 | end main; |
7 | |
8 | architecture Behavioral of main is |
9 | |
10 | ----------------------------------------------------------------------------------------------------
|
11 | |
12 | signal oneus_cnt : integer range 0 to 100 := 0; |
13 | signal wrptr : unsigned (9 downto 0) := (others=>'0'); -- unsigned wegen des kostenlosen wrap-arounds... ;-) |
14 | signal rdptr : unsigned (9 downto 0) := (others=>'0'); -- unsigned wegen des kostenlosen wrap-arounds... ;-) |
15 | type speicher is array(0 to 512) of STD_LOGIC; |
16 | signal memory : speicher; |
17 | |
18 | Signal delay : unsigned (9 downto 0) := "0111110100"; |
19 | |
20 | ----------------------------------------------------------------------------------------------------
|
21 | |
22 | begin
|
23 | |
24 | ----------------------------------------------------------------------------------------------------
|
25 | |
26 | delay_process : process (reset,clk) |
27 | begin
|
28 | if reset = '0' then |
29 | oneus_cnt <= 0; |
30 | elsif rising_edge(clk) then -- 100MHz |
31 | if (oneus_cnt=100) then |
32 | memory(to_integer(wrptr)) <= referenz; |
33 | wrptr <= wrptr+1; |
34 | rdptr <= wrptr-unsigned(delay); |
35 | oneus_cnt <= 0; |
36 | else
|
37 | oneus_cnt <= oneus_cnt+1; |
38 | end if; |
39 | end if; |
40 | end process; |
41 | |
42 | ----------------------------------------------------------------------------------------------------
|
43 | |
44 | output <= memory(to_integer(rdptr)); |
45 | |
46 | ----------------------------------------------------------------------------------------------------
|
47 | |
48 | end Behavioral; |
Bin ich hier richtig von meiner Denkweise? Wenn ich das die Delay auf den Wert 500 einstelle, dann sollte das Signal um 2 Perioden verzögert sein oda? lg
Leuchtet mir alles ein, nur wieso passt denn Lothars Lösung rein? Ich dachte ein Schieberegister passt NICHT? Sonst wär mir nur ein entsprechend langsamer Takt eingefallen. Phase von dem Rechtecksignal ist vermutlich konstant?
Hallo, ja ist konstant! Sagen wir es mal so.... Er kann VHDL ich noch nicht so gut.. :) Theoretisch müsste ich aber die 1us auch noch reduzieren können oder?? Könnte es mit 100ns noch klappen?
Christoph M. schrieb: > Bin ich hier richtig von meiner Denkweise? Wenn ich das die Delay auf > den Wert 500 einstelle, dann sollte das Signal um 2 Perioden verzögert > sein oda? Was sagt denn deine Simulation? Meine sagt (für meinen Code) auf jeden Fall: Ja, stimmt.
Hallo, ok die Größe vom Array war falsch jetzt sagt die meine Simulation auch, dass es passt.. :) danke! und noch zur Frage der Genauigkeit. Dazu müsste ich den oneus_cnt counter und das Array anpassen oder? lg
Christoph M. schrieb: > und noch zur Frage der Genauigkeit. Fachwort: Jitter > Dazu müsste ich den oneus_cnt counter und das Array anpassen oder? Ja, du müsstest öfter abtasten: Wenn du alle 500ns abtastest, dann brauchst du doppelt soviel Speicher und bekommst den halben Jitter.
Wenn man Dein Bild so anschaut, dann sieht das aus wie ein Taktsignal. Wenn man einen Takt um das Vielfache einer Periodendauer verzögert, dann hat man wieder das selbe Taktsignal, lediglich mit einer einzigen Verzögerung am Anfang. Wenn die 4kHz fest sind, dann kannst Du diese Einschaltverzögerung mit einem x-beliebigen Zähler und einem clock gate bauen. Ansonsten natürlich ein Schieberegister... Gruß Marcus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.