Hallo Zusammen Da ich ein VHDL-Anfänger bin (aber nicht bleiben will :-) ) möchte ich euch hier mal meinen kleinen Frequenzteiler vorstellen und hoffe darauf, dass ihr mir vielleicht ein paar Tipps und Tricks nennen könnt, wie ich die Schaltung eleganter/effizienter schreiben könnte. Zum Projekt, ich habe ein Altera DE0 Board mit einem Cyclone III. Das Board hat einen internen 50MHz-Takt mit welchem ich verschiedene Frequenzen aufbereiten will. Ich habe mich jetzt für für 7 verschiedene Frequenzen von 10Hz bis 10MHz entschieden (siehe Code) welche ich mit verschieden Zählschritten erreiche. Das Programm funktioniert so grundsätzlich ohne Probleme, compilieren und auf das Board laden funktioniert... ebenfalls kann ich die Signale auf dem KO anschauen, bis auf den 10MHz-Takt sehen die sogar alle einigermassen gut aus. (leichte Überschwinger sind aber bei allen Frequenzen zu erkennen.) Hat irgendwer ein paar gute Inputs was ich an diesem Code evtl. noch verbessern/anpassen kann? Bitte keine Posts wie: nicht zu viele Frequenzen in einem Projekt verwenden etc. -- das weiss ich selbst, mir gehts hier auch nur darum den Syntax von VHDL kennen zu lernen und ein wenig damit zu spielen. :-P Vielen Dank schon im Voraus Gruess Nico Hier der Code: ------------Wahrheitstabelle und Pinbelegung---------------- --Ein-/Ausgänge A B C | Z Pin's -- 0 0 0 | 10Hz AA20 -- 0 0 1 | 100Hz AB20 -- 0 1 0 | 1kHz AB19 -- 0 1 1 | 10kHz AA18 -- 1 0 0 | 100kHz Ab17 -- 1 0 1 | 1MHz W17 -- 1 1 0 | 10MHz T15 -- 1 1 1 | Fehler Led0 -- | leuchtet J1 ------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity Takt_Geni is port ( Set : in std_logic_vector(2 downto 0); clk_50MHz : in std_logic; clk_10Hz : out std_logic; clk_100Hz : out std_logic; clk_1kHz : out std_logic; clk_10kHz : out std_logic; clk_100kHz : out std_logic; clk_1MHz : out std_logic; clk_10MHz : out std_logic; fehler : out std_logic ); end Takt_Geni; architecture Behaviour of Takt_Geni is constant count_limit_10Hz : integer := 5000000; --1/50MHz x 5000000 = 100ms --> 10Hz constant count_limit_100Hz : integer := 500000; --1/50MHz x 500000 = 10ms --> 100Hz constant count_limit_1kHz : integer := 50000; --1/50MHz x 50000 = 1ms --> 1kHz constant count_limit_10kHz : integer := 5000; --1/50MHz x 5000 = 100us --> 10kHz constant count_limit_100kHz : integer := 500; --1/50MHz x 500 = 10us --> 100kHz constant count_limit_1MHz : integer := 50; --1/50MHz x 50 = 1us --> 1MHz constant count_limit_10MHz : integer := 5; --1/50MHz x 5 = 100ns --> 10MHz signal cnt : integer range 0 to count_limit_10Hz :=0; signal clk_100ms : std_logic :='0'; signal clk_10ms : std_logic :='0'; signal clk_1ms : std_logic :='0'; signal clk_100us : std_logic :='0'; signal clk_10us : std_logic :='0'; signal clk_1us : std_logic :='0'; signal clk_100ns : std_logic :='0'; signal set_fehler : std_logic :='0'; begin process (clk_50MHz) begin if (rising_edge(clk_50MHz)) then cnt <= cnt + 1; if (cnt = count_limit_10Hz) and (Set = "000") then cnt <=0; clk_100ms <= not clk_100ms; set_fehler <= '0'; end if; if (cnt = count_limit_100Hz) and (Set = "001") then cnt <=0; clk_10ms <= not clk_10ms; set_fehler <= '0'; end if; if (cnt = count_limit_1kHz) and (Set ="010") then cnt <= 0; clk_1ms <= not clk_1ms; set_fehler <= '0'; end if; if (cnt = count_limit_10kHz) and (Set ="011") then cnt <= 0; clk_100us <= not clk_100us; set_fehler <= '0'; end if; if (cnt = count_limit_100kHz) and (Set ="100") then cnt <= 0; clk_10us <= not clk_10us; set_fehler <= '0'; end if; if (cnt = count_limit_1MHz) and (Set ="101") then cnt <= 0; clk_1us <= not clk_1us; set_fehler <= '0'; end if; if (cnt = count_limit_10MHz) and (Set ="110") then cnt <= 0; clk_100ns <= not clk_100ns; set_fehler <= '0'; end if; if (Set ="111") then cnt <= 0; set_fehler <= '1'; end if; end if; end process; clk_10Hz <= clk_100ms; clk_100Hz <= clk_10ms; clk_1kHz <= clk_1ms; clk_10kHz <= clk_100us; clk_100kHz <= clk_10us; clk_1MHz <= clk_1us; clk_10MHz <= clk_100ns; fehler <= set_fehler; end Behaviour;
Warum teilst du jede Frequenz mit einem eigenen Zähler? Sinnvoller wäre hier doch ein gestufter Teiler: Eingang 50MHz :5 10MHz :10 1MHz :10 100kHz :10 10kHz usw... Auf diese Art bekommst du alle Frequenzen gleichzeitig und musst nur noch einen Multiplexer dahinterschalten. BTW: aus den 50MHz wirst du nur asymmetrische 10MHz (TV 3:5 oder 2:5) bekommen...
Hmmm, danke für den Input habe das jetzt mal versucht aber irgendwie scheitere ich an den integer-Variabeln... Mein Code sieht jetzt wie folgt aus: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity Takt_GeniV2 is port ( clk_50MHz : in std_logic; clk_10Hz : out integer; clk_100Hz : out integer; clk_1kHz : out integer; clk_10kHz : out integer; clk_100kHz : out integer; clk_1MHz : out integer; clk_10MHz : out integer ); end Takt_GeniV2; architecture Behaviour of Takt_GeniV2 is constant count_limit_10Hz : integer := 5000000; --1/50MHz x 5000000 = 100ms --> 10Hz constant teiler_5 : integer := 5; --Teilverhältnis 5 signal cnt : integer range 0 to count_limit_10Hz :=0; signal clk_100ms : integer := 0; signal clk_10ms : integer := 0; signal clk_1ms : integer := 0; signal clk_100us : integer := 0; signal clk_10us : integer := 0; signal clk_1us : integer := 0; signal clk_100ns : integer := 0; begin process (clk_50MHz) begin if (rising_edge(clk_50MHz)) then cnt <= cnt + 1; if (cnt = count_limit_10Hz) then cnt <=0; clk_100ms <= clk_100ms; clk_10ms <= (clk_100ms / teiler_5); clk_1ms <= (clk_10ms / teiler_5); clk_100us <= (clk_1ms / teiler_5); clk_10us <= (clk_100us / teiler_5); clk_1us <= (clk_10us / teiler_5); clk_100ns <= (clk_1us / teiler_5); end if; end if; end process; clk_10Hz <= clk_100ms; clk_100Hz <= clk_10ms; clk_1kHz <= clk_1ms; clk_10kHz <= clk_100us; clk_100kHz <= clk_10us; clk_1MHz <= clk_1us; clk_10MHz <= clk_100ns; end Behaviour; Das Problem ist jetzt, dass die Ausgänge in integer sind (weil ich sonst nicht durch 5 teilen kann). Das heisst am Ausgang meines Moduls sind jetzt Ausgänge mit einer Bitbreite von 32. Ich habe mit den Befehlen "to_bit" und "to_stdulogic" rumprobiert aber da hat er mir immer diverse Fehler ausgegeben. Kann ich nicht einfach sagen clk_10Hz to_stdulogic(integer)??? Hoffentlich nerv ich jetzt nicht zu stark mit "Basic-Probleme" aber ich komm da irgendwie nicht weiter...? Gruess Nico
Nico M. schrieb: > Hmmm, danke für den Input habe das jetzt mal versucht aber irgendwie > scheitere ich an den integer-Variabeln... ... 1. Bibliotheken > library ieee; > use ieee.std_logic_1164.all; > use ieee.std_logic_unsigned.all; Die std_logic_unsigned fliegt bitte raus. Die ist obsolet. Siehe hier: Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete" Rechnen kann man auch ohne Bibliothek mit integer. Wenn man die Werte irgendwie an den Pins baucht (als Eingang und/oder als Ausgang), dann verwendet man die numeric_std-Bibliothek zum Konvertieren. Schön grafisch dargestellt ist das hier: http://www.lothar-miller.de/s9y/categories/16-Numeric_Std 2. Taktteilung > clk_100ms <= clk_100ms; > clk_10ms <= (clk_100ms / teiler_5); Du bist hier auf einem FPGA und nicht auf einem Mikrocontroller. Du mußt objektorientiert Denken. Ein FPGA ist ein riesiges Steckbrett mit Look-up-Tables und Flip-Flops (1-Bit-Speicher). Die kannst Du frei miteinander verdrahten. AND, OR, XOR, NOT etc. lässt sich direkt in den Loop-up-Tables abbilden. Darauf bauen Addierer, Subtrahierer, Multiplexer u.ä. auf. Für Schieberegister, Zähler und State-Machines werden die Flip-Flops gebraucht. Zeitliche Zusammenhänge werden mit Zählern abgebildet, die mit dem Systemtakt arbeiten (und es gibt nur einen Systemtakt!). 3. divide-et-impera Du hast zwei Teilprobleme: * die Signalgenerierung * die Signalselektion Trenne sie! Für das erste Problem nimmt man in Deinem Fall einen Taktteiler (bzw. mehrere hintereinander) und für das Zweite einen Multiplexer. Duke
Nico M. schrieb: > Ups, ich merk gerade der Teiler müsste ja durch 10 teilen... Ja, hoffentlich anhand einer Simulation. Genau dieses simple Design lässt sich nämlich ganz einfach elementar simulieren: Takt rein und Bildchen angucken...
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.