Wie oft braucht man nur einfach irgend einen Takt?
Der muss nicht genau oder stabil sein, sondern einfach nur vor sich hintakten.
Dann ist die gute alte Methode über Gatterlaufzeiten und einen Inverter einen Ringoszillator zu bauen eigentlich naheliegend. Allerdings neigen die Tools beim FPGA-Design zur Optimierung. Hintereinandergeschaltete Gatter werden zusammengefasst, vereinfacht und gehen so im Build-Prozess verloren
Dagegen hilft bei Xilinx das Attribut "KEEP". Auf ein Signal angewandt teilt man der Toolchain mit, dass dieses Signal erhalten bleiben soll. Und das ist der Weg, der für den Ringoszillator beschritten wird.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity RingOszillator is Port (reset : in std_logic; oscout : out std_logic); end RingOszillator; architecture Behavioral of RingOszillator is signal oscff : std_logic := '0'; signal ring : std_logic_vector(7 downto 0); attribute KEEP : string; attribute KEEP of ring : signal is "true"; begin -- die Gatterkette ring <= ring(6 downto 0) & not ring(7) when reset='0' else (others=>'0'); -- das Symmetrier-Flipflop process (ring) begin if rising_edge(ring(7)) then oscff <= not oscff; end if; end process; -- die Ausgangszuweisung oscout <= oscff; end Behavioral;
Der reset ist wichtig, ohne dieses Signal wird keine Gatterkette erzeugt, sondern einfach nur alles parallel verdrahtet, und der Oszillator beginnt nicht zu schwingen. Siehe dazu die Ausführungen im Beitrag VHDL Coolrunner Delay line wird wegoptimiert trotz keep auf dem mikrocontroller.net.
Mit einem Spartan3 XC3S400 im FG456 Gehäuse erhält man damit eine ziemlich temperaturstabile Frequenz von 50MHz am oscout. Damit lässt sich doch schon arbeiten, oder?
Wer das Design auf einem neueren Xilinx FPGA implementieren will und mit Vivado arbeitet, der sollte sich das Attribut "DONT_TOUCH" mal genauer anschauen. Siehe dazu den Beitrag Welches FPGA Board für TRNG (VHDL) auf dem µC.net.