Hallo zusammen, ich würde gerne in VHDL ein n-Stufiges Flip Flop erzeugen, wobei ich den Parameter n über ein generic weitergeben wollte. Ich habe mir zwei Codebeispiele überlegt, wobei beim ersten Codebespiel in der Simulation mit Vivado beim Ergebnis "X" auftauchen, also anscheinend mehrere Quellen für das Signal. Kann bitte jemand die Codebeispiele bewerten oder hat evtl. noch einen besseren Vorschlag. Vielen Dank im Voraus Daniel
Daniel P. schrieb: > ein n-Stufiges Flip Flop Was soll das sein? Mehrere FFs kann man als Schieberegister oder als Zähler kaskadieren. Zähler können z.B. binär, dezimal, Gray-Code zählen.
Daniel P. schrieb: > ich würde gerne in VHDL ein n-Stufiges Flip Flop erzeugen, Du willst aus mehreren Flipflops ein n-stufiges Schieberegister erzeugen, oder? Und über dieses Schieberegister willst du ein Signal um n Takte verzögern. > wobei ich den Parameter n über ein generic weitergeben wollte. Das geht für 1 Bit einfach so:
1 | :
|
2 | generic n : integer range 2 to 16 := 2; |
3 | :
|
4 | :
|
5 | signal sr: std_logic_vector (n-1 downto 0) |
6 | :
|
7 | sr <= sr(n-2 downto 2) & inbit when rising_edge(clk); -- schiebt nach links |
8 | :
|
9 | outbit <= sr(n-1); |
10 | :
|
Und für Vektoren geht es in etwa so:
1 | :
|
2 | generic n : integer := 2; |
3 | :
|
4 | type slv16_array is array (n-1 downto 0) of std_logic_vector(15 downto 0); |
5 | signal vsr : slv16_array := (others => (others => '0')); |
6 | :
|
7 | vsr <= vsr(n-2 downto 2) & invect when rising_edge(clk); -- liest ein und schiebt nach links |
8 | outvect <= vsr(n-1); |
9 | :
|
Wenn die Länge des Schieberegisters zur Laufzeit umgeschaltet werden soll, dann sieht es für 1 Bit so aus:
1 | :
|
2 | signal n : integer range 2 to 16 := 2; -- min. 2 Bit, max. 16 Bit lang |
3 | signal sr: std_logic_vector (15 downto 0); -- muss für maximale Länge ausgelegt sein |
4 | :
|
5 | sr <= sr(n-2 downto 2) & inbit when rising_edge(clk); -- schiebt nach links |
6 | :
|
7 | outbit <= sr(n-1); |
8 | :
|
Die Schieberegister-Zeile mit dem "when rising_edge()" kann man natürlich auch auf die lange Art mit einem Prozess schreiben:
1 | process begin |
2 | wait until rising_edge(clk); |
3 | sr <= sr(n-2 downto 2) & inbit; -- schiebt nach links |
4 | end process; |
Oder die traditionelle, ganz ausführliche Art aus dem letzten Jahrtausend:
1 | process (clk) |
2 | begin
|
3 | if rising_edge(clk) then |
4 | sr <= sr(n-2 downto 2) & inbit; -- schiebt nach links |
5 | end if; |
6 | end process; |
> also anscheinend mehrere Quellen für das Signal.
Für welches Signal?
:
Bearbeitet durch Moderator
Daniel P. schrieb: > in der Simulation mit Vivado beim Ergebnis "X" auftauchen, also > anscheinend mehrere Quellen für das Signal. Nicht zwingend. Manche Simulatoren machen bei der Zusammenfassung von Vektoren aus dem 'U' ein 'X'...
Sorry für die Verwirrung: Zum Hintergrund. Ich bekomme als Eingangssignal einen 16Bit Zeitstempel. In Abhängigkeit von einem Generic (in meinem Beispiel die Konstante c_clk_del) möchte ich den Zeitstempel um die Anzahl "c_clk_del" Takte verzögern. Das ganze muss nicht zur Laufzeit umgeschaltet werden. Lothar M. schrieb: >> also anscheinend mehrere Quellen für das Signal. > Für welches Signal? time_stamp(0)
Danke für die Hilfe, habe mich für folgende Lösung entschieden:
1 | type slv16_array is array (n-1 downto 0) of std_logic_vector(15 downto 0); |
2 | signal vsr : slv16_array := (others => (others => '0')); |
3 | signal vsr_out : std_logic_vector(15 downto 0); |
4 | generic n : natural := 2; |
5 | vsr <= vsr(n-2 downto 0) & invec when rising_edge(clk); |
6 | vsr_out <= vsr(n-1) when n > 0 else |
7 | invec; |
>
1 | type slv16_array is array (n-1 downto 0) of std_logic_vector(15 downto 0); |
2 | signal vsr : slv16_array := (others => (others => '0')); |
3 | --snip
|
Auf den default-wert in Zeile 2 ist nach der Synthese kein Verlass.
:
Bearbeitet durch User
Bradward B. schrieb: > Auf den default-wert in Zeile 2 ist nach der Synthese kein Verlass. Prinzipiell ja, aber sowas prüft man einmal, ob das vom jeweiligen Synthesetool richtig umsetzt wird. Und das Synthesetool wechselt man nicht so oft wie die Socken... Ich hatte den Fall bei Lattice Diamond neulich, wo ich meinen Code etwas umformulieren musste: Ein
1 | type config_type is array( 0 to 15) of std_ulogic_vector( 7 downto 0); |
2 | constant default_config : config_type := |
3 | (
|
4 | 0 => "11110000", |
5 | others => ( others => '0') |
6 | );
|
7 | |
8 | constant default_config_array : config_array_t := ( others => ( default_config)); |
wird später partiell überschrieben, aber die default_config wurde nur komplett mit '0' initialisiert. Nach ausformulieren:
1 | signal config_array : config_array_t := default_config_array; |
2 | |
3 | begin
|
4 | |
5 | -- needed for Lattice LSE
|
6 | -- otherwise byte 0 is not correct inialized
|
7 | --config_array( 0) <= default_config; -- is used
|
8 | config_array( 1) <= default_config; |
9 | config_array( 2) <= default_config; |
10 | ...
|
11 | |
12 | module_i0: entity work.module |
13 | port map |
14 | (
|
15 | clk => clk, -- : in std_ulogic; |
16 | ...
|
17 | config => config_array( 0), -- : out config_type; |
18 | ...
|
19 | );
|
klappte es wie gewünscht...
>> Auf den default-wert in Zeile 2 ist nach der Synthese kein Verlass. > Prinzipiell ja, aber sowas prüft man einmal, ob das vom jeweiligen > Synthesetool richtig umsetzt wird. Und das Synthesetool wechselt man > nicht so oft wie die Socken... Hm, erzähl das mal einem Barfüßler ;-) Ich seh hier eher das Problem der Architektur, gibt man einen Reset-Value an, nimmt das Synthesetool oft keine Schieberegister.Makros wie SRL16 (bspw. Xilinx Spartan) auch wenn es in der konkreten FPGA-Architektur möglich wäre. Aber der TO wollte ja lt. Headline ohnehin ("riesige") FF statt schlanke Schiebeketten.
:
Bearbeitet durch User
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.