mikrocontroller.net

Forum: FPGA, VHDL & Co. Taktverschiebung


Autor: VHDL_Neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich dachte ich nutze die kalte Jahreszeit, um mich mal ein wenig in die 
VHDL-Programmierung einzuarbeiten und stelle schon ein 
"Anfängermysterium" fest.
Ich habe folgenden Quellcode erzeugt, der als Gesprächsbasis dienen 
soll:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY clkgen IS
    
    GENERIC (  CONSTANT length_s  : natural := 999
             );
             
    PORT    (  reset    : IN  std_logic;
               enable   : IN  std_logic;
               clkin_ms: IN  std_logic;
               clkout   : OUT std_logic
             );
END ENTITY clkgen;


ARCHITECTURE beh1 OF clkgen IS
    
    SIGNAL count_1ms : integer range 0 to length_s;
        
    BEGIN
       sig_gen : PROCESS (reset, clkin_ms, enable)
       variable clk : std_logic;
       BEGIN
          IF reset = '0' THEN
             count_1ms <=  0;
             clk  := '0';
          ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
              IF enable = '1' THEN
                  clk := '1';
              ELSE
                  clk := '0';
              END IF;
          END IF;
          clkout <= clk; 
       END PROCESS sig_gen;    
                 
    END ARCHITECTURE beh1;


Im ersten Schritt, wollte ich eigentlich nur ein enable-Signal 
auswerten, bei diesem enable-Signal soll in der nächsten Stufe ein 
Zähler hochgezählt werden und weitere Aktionen ausgeführt werden.
Zur Zeit interessiert mich aber nur das enable-Signal und dessen 
Auswirkungen.
Zur Frage: Müsste nicht clkout bei jedem enable auf High gesetzt werden, 
da clk doch eine Variable ist und der Wert sofort zugewiesen wird.
Bei der Simulation jedoch wird der Wert erst mit eintreten des nächsten 
clkin_ms'event (Steigende Flanke) gesetzt.
Der Ausgang müsste doch ein Abbild vom enable sein oder etwa nicht?

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

Bewertung
0 lesenswert
nicht lesenswert
> Müsste nicht clkout bei jedem enable auf High gesetzt werden
> da clk doch eine Variable ist und der Wert sofort zugewiesen wird.
Nein, denn die wichtigste Bedingung ist ja, dass erst mal 
(clkin_ms'event AND clkin_ms = '1') eintreten muß, bevor dann die 
/Enable/-Geschichte ausgewertet wird.

Kurz und knackig: hier bräuchtest du niemals eine Variable.
Variablen können dich ganz hübsch aufs Glatteis führen...
Siehe dazu den Beitrag "Variable vs Signal"

Autor: VHDL_Neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm.
Dann müsste es also so heißen:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY clkgen IS
    
    GENERIC (  CONSTANT length_s  : natural := 999
             );
             
    PORT    (  reset    : IN  std_logic;
               enable   : IN  std_logic;
               clkin_ms : IN  std_logic;
               clkout   : OUT std_logic
             );
END ENTITY clkgen;


ARCHITECTURE beh1 OF clkgen IS
    
    SIGNAL count_1ms : integer range 0 to length_s;
    SIGNAL clk : std_logic;   
    BEGIN
       sig_gen : PROCESS (reset, clkin_ms, enable)
       
       BEGIN
          IF reset = '0' THEN
             count_1ms <=  0;
             clk  <= '0';
          ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
              IF enable = '1' THEN
                  clk <= '1';
              ELSE
                  clk <= '0';
              END IF;
          END IF;
           
       END PROCESS sig_gen;    
       clkout <= clk;          
    END ARCHITECTURE beh1;


Mit der Verschiebung muß ich dann wohl aber trotzdem leben, da clkout 
erst mit der nächsten steigenden Flanke vom clkin_ms ausgegeben wird.
Zumindest versteh ich das dann jetzt so, dass es keine Möglichkeit gibt, 
dem enable ohne zeitliche Verzögerung zu folgen!?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@VHDL_Neuling (Gast)

>Mit der Verschiebung muß ich dann wohl aber trotzdem leben, da clkout
>erst mit der nächsten steigenden Flanke vom clkin_ms ausgegeben wird.

Ja.

>Zumindest versteh ich das dann jetzt so, dass es keine Möglichkeit gibt,
>dem enable ohne zeitliche Verzögerung zu folgen!?

Doch, einfach rein kombinatorisch. Aber sag lieber, was das werden soll. 
Dann kann man dir helfen.

MFG
Falk

Autor: VHDL_Neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das man mir helfen will, hört sich doch mal richtig gut an.

Eine richtige Aufgabe ist es allerdings nicht, mehr so eine Art 
praktische Übung, an dem was man so liest. Ich denke nur nachlesen nützt 
nicht viel, wenn man davon nichts praktisch ausprobiert.

1.Schritt:
Wie ganz oben beschrieben - Ich möchte einfach das enable auswerten.

2.Schritt:
Wenn das enable-Signal auf high geht, soll ein Zähler hochgezählt 
werden. Da wohl häufig Zeiten, bzw. zeitliche Signale erzeugt werden 
müssen, denke ich das ein Zähler bis 1000 das sinnvollste wäre 
(Umrechnungsfaktoren der Zeiteinheiten)

3.Schritt/Erweiterung:
Besser erst nach dem zweiten Schritt

Da ich nun weiß das ich mit dem nicht unmittelbarem Folgen auf das 
enable-Signal leben muß, sieht mein erster Wurf (zum 2.Schritt) so aus:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY clkgen IS
    
    GENERIC (  CONSTANT length_s  : natural := 999
             );
             
    PORT    (  reset    : IN  std_logic;
               enable   : IN  std_logic;
               clkin_ms : IN  std_logic;
               clkout   : OUT std_logic
             );
END ENTITY clkgen;


ARCHITECTURE beh1 OF clkgen IS
    
    SIGNAL count_1ms : integer range 0 to length_s;
    SIGNAL clk : std_logic;   
    BEGIN
       sig_gen : PROCESS (reset, clkin_ms, enable)
       
       BEGIN
          IF reset = '0' THEN
             count_1ms <=  0;
             clk  <= '0';
          ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
              IF enable = '1' THEN
                 IF count_1ms = 999 THEN
                    count_1ms  <=  0 ;
                    clk  <= '1';
                 ELSE
                    count_1ms  <= count_1ms + 1;
                    clk  <= '0';
                 END IF;   
              END IF;
          END IF;
           
       END PROCESS sig_gen;    
       clkout <= clk;          
    END ARCHITECTURE beh1;


Frage dazu:
Passt das soweit?
Empfiehlt es sich, einen eigenen Prozess fürs Zählen und einen eigenen 
für die Zählerauswertung zu definieren?
Muß ich für den Fall dass enable=0 ist, ebenfalls eine Aussage treffen?

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

Bewertung
0 lesenswert
nicht lesenswert
> 2.Schritt: Wenn das enable-Signal auf high geht, soll ein Zähler
> hochgezählt werden.
Das sollte wohl heißen: Wenn ein Takt kommt und enable aktiv ist, 
soll...

> Passt das soweit?
Ja.
> Empfiehlt es sich, einen eigenen Prozess fürs Zählen und einen eigenen
> für die Zählerauswertung zu definieren?
Nicht, wenn du noch so einen überschaubaren Umfang hast.
> Muß ich für den Fall dass enable=0 ist, ebenfalls eine Aussage treffen?
Nein. Dann wird einfach der Zählerblock nicht ausgeführt.

BTW:
       sig_gen : PROCESS (reset, clkin_ms, enable)
Diese Sensitivliste ist überdefiniert. Der Prozess ist nur vom Reset und 
dem Takt abhängig. Wenn sich der Takt nicht ändert, bewirkt auch eine 
Änderung von enable nichts.


Du hast für meinen Geschmack zuviele Takte (oder wenigstens Namen davon) 
im Design. Im Idealfall ist nur 1 einziger Takt im ganzen Design. Alles 
andere sind Clock-Enables. Z.B. hättest du 30 MHz FPGA-Takt, daraus 
leitest du ein Enable für jede ms ab, und eines für jede Sekunde...
Aber wenn irgendwo eine Taktabfrage steht, dann findest du dort nur 
den Mastertakt 30 MHz.

Wo wir schon bei den Idealfällen sind: lass den Reset weg. den brauchst 
du nicht. Signale lassen sich bei der Definition initialisieren:
    SIGNAL count_1ms : integer range 0 to length_s := 0;
    SIGNAL clk : std_logic := '0';
Zum Thema Reset gibt es den Beitrag "Xilinx und die Resets"


        ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
Das könntest du kürzer und lesbarer so schreiben:
        ELSIF rising_edge(clk_ms) THEN

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.