www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Frequenzteiler 1:1000


Autor: Martin Spider (akandra)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Community,

wie viele bin auch ich ein Frischling im VHDL und arbeite im Moment an 
einem einfachen Frequenzteiler 1:1000 der mir ein 1Mhz Takt in einen 
1kHz Signal umwandelt.
Laut Simmulation funktioniert es wie gewollt, allerdings hab ich lange 
wegen dem Counter herumprobieren müssen. Gibt es eventl. eine elegantere 
Lösung oder kann mein Code zu Problemen führen?

Vielen Dank für eure Hilfe und Zeit :)


Mfg
Martin

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_unsigned.all;

ENTITY clkgen IS
    PORT (
        clk_1us: IN STD_LOGIC;
        reset: IN STD_LOGIC;
        clk_1ms: OUT STD_LOGIC
    );
end clkgen;


ARCHITECTURE count_1k OF clkgen IS
    SIGNAL counter: STD_LOGIC_VECTOR(9 DOWNTO 0);
BEGIN
    PROCESS(clk_1us, reset)
    BEGIN
        
        IF (reset = '0') THEN                        -- asynchroner Reset
         counter <= (others => '0');
         clk_1ms <= '0';
            
        ELSIF (rising_edge(clk_1us)) THEN
            
            IF (counter < "1111100111") THEN         -- hochzählen bis 999
               counter <= counter + 1;
            ELSE                                     -- Zurücksetzen auf 0
               counter <= (others => '0');
            END IF;
                        
            IF (counter < "0111110100") THEN         -- '1' für counter < 499
               clk_1ms <= '1';
            ELSE                                     -- '0' sonst
                clk_1ms <= '0';
            END IF;
            
        END IF;
                    
    END PROCESS;
END ARCHITECTURE count_1k;
    

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> kann mein Code zu Problemen führen?

wenn du den erzeugten Takt wirklich als Takt weiterverwendest, ja.


machs doch stattdessen so :

clk_1ms <= '1' when counter = '1111100111' else '0'

außerhalb des process, also als concurrent statement
und dann bei der Verwendung :

if rising_edge(clk_1us) then
 if clk_1ms = '1'
...


Das wäre ein klassisches enable.

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1MHz sind nicht schnell in aktuellen Bauteilen, daher bekommst Du noch 
nicht die klassischen Probleme der Laufzeiten.

Deine Version mit einer Prüfung ">", "<" ist tunlichst zu vermeiden!
Das produziert einen deutlichen Aufwand an Logik. Um ein arithmetisches 
Größer zu prüfen, muss man z.B. die Zahlen voneinander subtrahieren und 
das Ergebnis auf >0 prüfen. Das bedeutet, dass neben dem Zähler noch 
weiter Volladierer benötigt werden.

Möchtest Du ein 1kHz Rechtecksignal erzeugen, so nimm einen Zähler bis 
500 und lass dein Ausgangssignal toggeln. Das Ende des Zählvorgangs 
prüfst Du mit einem "=".

SIGNAL   count_1khz : std_logic;
SIGNAL   count_exp  : STD_LOGIC;
SIGNAL   count      : STD_LOGIC_VECTOR(9 DOWNTO 0);
CONSTANT count_RLD  : STD_LOGIC_VECTOR(count'range):(others =>'0');
CONSTANT count_END  : STD_LOGIC_VECTOR(count'range):="0111110100";

if (rising_edge (clock)) then
   if(count_exp = '1') then
       count_1khz <= not count_1khz;
       count <= count_RLD;
   else
       count <= count +1;
   endif;
endif;

count_exp <= '1' when count = count_END else '0';

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

Bewertung
0 lesenswert
nicht lesenswert
Oder so:
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_unsigned.all;

ENTITY clkgen IS
    PORT (
        clk_1us: IN STD_LOGIC;
--        reset: IN STD_LOGIC; -- wozu ein Reset?
        clk_1ms: OUT STD_LOGIC
    );
end clkgen;

ARCHITECTURE count_1k OF clkgen IS
    SIGNAL counter: integer range 0 to 499 := 0;
    signal clk1ms: STD_LOGIC := '0';
BEGIN
    PROCESS(clk_1us)
    BEGIN
        IF (rising_edge(clk_1us)) THEN
            IF (counter < 499) THEN         -- hochzählen bis 499
               counter <= counter + 1;
            ELSE                            -- Zurücksetzen auf 0
               counter <= 0;
               clk1ms <= not clk1ms;
            END IF;
        END IF;
    END PROCESS;
    clk_1ms <= clk1ms;
END ARCHITECTURE count_1k;
Das gibt einen 50% Takt.
Der macht allerdings innerhalb eines CPLDs oder FPGAs keinen Sinn. Dort 
arbeitet man mit 1 Mastertakt und Clock-Enables. Und das wäre dann mein 
Ansatz:
ARCHITECTURE count_1k OF clkgen IS
    SIGNAL counter: integer range 0 to 999 := 0;
BEGIN
    PROCESS(clk_1us)
    BEGIN
       wait until rising_edge(clk_1us);
       IF (counter < 999) THEN
           counter <= counter + 1;
           clken_1ms <= '0';
        ELSE              
           counter <= 0;
           clken_1ms <= '1';
        END IF;
    END PROCESS;
END ARCHITECTURE count_1k;

EDIT:
@ mischu
> Deine Version mit einer Prüfung ">", "<" ist tunlichst zu vermeiden!
> Das produziert einen deutlichen Aufwand an Logik.
Das solltest du dir aber noch mal ansehen...
Ich habe das auch mal geglaubt. Aber in der Tat ist es so, dass nur 
selten mehr Logik verbraucht wird.

Autor: Martin Spider (akandra)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank, das hilft mir auf jeden Fall!

Noch dazu:
> Das gibt einen 50% Takt.
> Der macht allerdings innerhalb eines CPLDs oder FPGAs keinen Sinn. Dort
> arbeitet man mit 1 Mastertakt und Clock-Enables.

Ich stelle mit der Funktion den Haupttakt zu Verfügung, da ich einen 
1Mhz Oszillator habe, aber der "Mastertakt" bei 1kHz sein soll.

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Martin
Nur VHDL oder einer idealen Simulation macht es keinen Unterschied, ob 
Du Dein 1kHz Signal als Clockquelle nimmst, oder 1MHz mit einem 1kHz 
Enablepuls.
Auf der konkreten Hardware sieht dies häufig anders aus.
Clocksignale sind sehr kritisch bezüglich Flankensteilheit, Jitter und 
Laufzeiten. Daher sind in CPLDs/FPGAs sogenannte Clocknetzwerke 
aufgebaut. Das sind spezielle Leitungen die zum Verteilen eines Taktes 
an möglichst alle FlipFlops genutzt werden können. Leider gibt es davon 
nur sehr wenige Leitungen (so etwa 2-16 je nach Baustein).
Man nimmt gerne eine dieser Leitungen, um dem gesammten Chip einen 
Mastertakt vorzugeben. Sofern Du nur wenig Logik mit dem 1kHz Signal 
ansteuern willst, nur lokal geroutet wird. Wie gesagt, bei 1kHz wird es 
noch keine Probleme geben. Wenn Du aber morgen auf deutlich höhere 
Frequenzen umsteigst, wirst Du dich wundern.

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

Bewertung
0 lesenswert
nicht lesenswert
Martin Spider schrieb:
> Ich stelle mit der Funktion den Haupttakt zu Verfügung, da ich einen
> 1Mhz Oszillator habe, aber der "Mastertakt" bei 1kHz sein soll.
Dann nimm besser den 1 MHz als Mastertakt und lass alles andere über 
Clock-Enables laufen. Die Stromaufnahme steigt dadurch nicht 
(signifikant), weil ja trotz des hohen Mastertaktes die FFs nur im 1 kHz 
Takt umgeschaltet werden.

Autor: theo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hätte da auch mal ne Frage:
Wie verhält sich das den im Quellcode vom Lothar Miller, mit den 
vorbelegten Signalen auf 0?
Ist es nicht so, dass man dies vermeidet, da es ansonsten nicht 
synthesefähig ist?

Laß mich da gern eines besseren belehren.

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welcher Teil soll nicht synthesefähig sein ?


die Initialisierung des Integer auf 0 ist kein Problem, im FPGA starten 
eh alle FFs mit den Werten die man angibt, egal was.

Bei ASICs ist das ggf anders, vielleicht hast das von dort aufgeschnappt 
?

Autor: theo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso und demnach ist es dann auch bei dem weiter oben benannten Signal 
okay?:
signal clk1ms: STD_LOGIC := '0';

Wieder was gelernt.

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Martin Spider schrieb:
>> Ich stelle mit der Funktion den Haupttakt zu Verfügung, da ich einen
>> 1Mhz Oszillator habe, aber der "Mastertakt" bei 1kHz sein soll.
> Dann nimm besser den 1 MHz als Mastertakt und lass alles andere über
> Clock-Enables laufen. Die Stromaufnahme steigt dadurch nicht
> (signifikant), weil ja trotz des hohen Mastertaktes die FFs nur im 1 kHz
> Takt umgeschaltet werden.

Da hätte ich noch eine Frage.
Angenommen ich hätte einen 200MHz Takt aber mir würde es reichen wenn 
alles mit 100MHz läuft, dann kann ich ja überall mit CE arbeiten.
"Merkt" die Synthese bzw. das P&R dass ich nur mit 100MHz arbeiten will? 
Ich frage in Hinblick auf Static Timing Constraints usw. da es manchmal 
doch recht knifflig ist so wenig Logikstufen wie möglich zu haben um 
nicht zu langsam zu werden.

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

Bewertung
0 lesenswert
nicht lesenswert
> "Merkt" die Synthese bzw. das P&R dass ich nur mit 100MHz arbeiten will?
Das kommt darauf an...
> Ich frage in Hinblick auf Static Timing Constraints
Dafür gibt dann "Multi Cycle Constraints", dort gibst du z.B. an, dass 
eine FSM das Ergebnis der Logik erst 2 Takte später braucht.

Aber 200MHz auf dem ganzen Design sind grenzwertig. Da wäre bei Xilinx 
ein DCM das Richtige, um die hohe Frequenz auf 100MHz herunterzusetzen. 
Takte, die über den DCM verwaltet werden, können dann auch von der 
Toolchain richtig in die Timing Constraints eingerechnet werden.

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

Bewertung
0 lesenswert
nicht lesenswert
> vorbelegten Signalen auf 0?
> Ist es nicht so, dass man dies vermeidet, da es ansonsten nicht
> synthesefähig ist?
Nicht alle Tools können beliebige Vorgabewerte umsetzen (Xilinx kanns), 
aber 0 ist ein Defaultwert bei allen SRAM-basierten FPGAs.
Für andere Werte gilt: einfach ausprobieren  ;-)

Vorbelegt werden können natürlich nur getaktete Signale, denn nur dort 
ist ein Speicherglied beteiligt. Kombinatorische Signale werden sowieso 
sofort aus den Eingangswerten neu berechnet:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Test is
    Port ( i1  : in  STD_LOGIC;
           i2  : in  STD_LOGIC;
           i3  : in  STD_LOGIC;
           o1  : out  STD_LOGIC;
           o2  : out  STD_LOGIC;
           o3  : out  STD_LOGIC := '1';
           clk : in  STD_LOGIC);
end Test;

architecture Behavioral of Test is
signal o2c : std_logic := '1';
begin
   o1 <= i1;

   process begin
      wait until rising_edge(clk);
      o2c <= i2;
   end process;
   o2 <= o2c;

   process begin
      wait until rising_edge(clk);
      o3 <= i3;
   end process;
end Behavioral;
o1 kann (weil kombinatorisch) natürlich nicht vorbelegt werden.
o2 kann ebenfalls nicht vorbelegt werden. Allerdings gibt es ein lokales 
Signal o2c, das initialsiert werden kann.
o3 kann direkt vorbelegt werden.

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.