Forum: FPGA, VHDL & Co. Taktverschiebung


von VHDL_Neuling (Gast)


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:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
USE ieee.std_logic_unsigned.all;
4
5
ENTITY clkgen IS
6
    
7
    GENERIC (  CONSTANT length_s  : natural := 999
8
             );
9
             
10
    PORT    (  reset    : IN  std_logic;
11
               enable   : IN  std_logic;
12
               clkin_ms: IN  std_logic;
13
               clkout   : OUT std_logic
14
             );
15
END ENTITY clkgen;
16
17
18
ARCHITECTURE beh1 OF clkgen IS
19
    
20
    SIGNAL count_1ms : integer range 0 to length_s;
21
        
22
    BEGIN
23
       sig_gen : PROCESS (reset, clkin_ms, enable)
24
       variable clk : std_logic;
25
       BEGIN
26
          IF reset = '0' THEN
27
             count_1ms <=  0;
28
             clk  := '0';
29
          ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
30
              IF enable = '1' THEN
31
                  clk := '1';
32
              ELSE
33
                  clk := '0';
34
              END IF;
35
          END IF;
36
          clkout <= clk; 
37
       END PROCESS sig_gen;    
38
                 
39
    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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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"

von VHDL_Neuling (Gast)


Lesenswert?

Hmmm.
Dann müsste es also so heißen:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
USE ieee.std_logic_unsigned.all;
4
5
ENTITY clkgen IS
6
    
7
    GENERIC (  CONSTANT length_s  : natural := 999
8
             );
9
             
10
    PORT    (  reset    : IN  std_logic;
11
               enable   : IN  std_logic;
12
               clkin_ms : IN  std_logic;
13
               clkout   : OUT std_logic
14
             );
15
END ENTITY clkgen;
16
17
18
ARCHITECTURE beh1 OF clkgen IS
19
    
20
    SIGNAL count_1ms : integer range 0 to length_s;
21
    SIGNAL clk : std_logic;   
22
    BEGIN
23
       sig_gen : PROCESS (reset, clkin_ms, enable)
24
       
25
       BEGIN
26
          IF reset = '0' THEN
27
             count_1ms <=  0;
28
             clk  <= '0';
29
          ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
30
              IF enable = '1' THEN
31
                  clk <= '1';
32
              ELSE
33
                  clk <= '0';
34
              END IF;
35
          END IF;
36
           
37
       END PROCESS sig_gen;    
38
       clkout <= clk;          
39
    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!?

von Falk B. (falk)


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

von VHDL_Neuling (Gast)


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:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
USE ieee.std_logic_unsigned.all;
4
5
ENTITY clkgen IS
6
    
7
    GENERIC (  CONSTANT length_s  : natural := 999
8
             );
9
             
10
    PORT    (  reset    : IN  std_logic;
11
               enable   : IN  std_logic;
12
               clkin_ms : IN  std_logic;
13
               clkout   : OUT std_logic
14
             );
15
END ENTITY clkgen;
16
17
18
ARCHITECTURE beh1 OF clkgen IS
19
    
20
    SIGNAL count_1ms : integer range 0 to length_s;
21
    SIGNAL clk : std_logic;   
22
    BEGIN
23
       sig_gen : PROCESS (reset, clkin_ms, enable)
24
       
25
       BEGIN
26
          IF reset = '0' THEN
27
             count_1ms <=  0;
28
             clk  <= '0';
29
          ELSIF  (clkin_ms'event AND clkin_ms = '1') THEN
30
              IF enable = '1' THEN
31
                 IF count_1ms = 999 THEN
32
                    count_1ms  <=  0 ;
33
                    clk  <= '1';
34
                 ELSE
35
                    count_1ms  <= count_1ms + 1;
36
                    clk  <= '0';
37
                 END IF;   
38
              END IF;
39
          END IF;
40
           
41
       END PROCESS sig_gen;    
42
       clkout <= clk;          
43
    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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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

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
Noch kein Account? Hier anmelden.