Fehler im VHDL-Quellcode

Gast #1475948
Lesenswert?

Ich habe ein VHDL-Quellcode zusammengesetllt, bei dem ein Signal 
heruntergetaktet wird und dieses Signal nutze ich um eine 
7-Segment-Anzeige anzusteuern.
Leider funktioniert dies nicht. Er zeigt eine 8 auf der 
7-Segment-Anzeige an und der Reseteingang startet den Vorgang des 
Zählens nicht.
Hat jemand eine Idee???
1
library IEEE;
2
  use IEEE.std_logic_1164.all;           -- importiere std_logic types
3
  use IEEE.std_logic_arith.all;         -- importiere add/sub vom std_logic_vector
4
  use IEEE.STD_LOGIC_UNSIGNED.ALL;
5

6
ENTITY sieben_segment IS
7
  PORT ( -- Eingänge
8
      clk               : IN  std_logic;      -- Eingangstakt
9
      reset              : IN  std_logic;      -- Zähler Rücksetzeingang
10
    --  updown             : IN  std_logic;      -- Zählrichtung up/down
11
      -- Ausgänge 
12
      a, b, c, d, e, f, g  : OUT std_logic);     -- Eingänge der 7-Segment-Anzeige
13
END sieben_segment;
14

15
ARCHITECTURE Behavioral OF sieben_segment IS
16
-- interne Signal Deklaration
17
  SIGNAL teiler: integer range 0 to 999999;       -- Signal teiler deklariert: Mit diesem Wert kann aus 1MHz Sekundentakt gemacht werden
18
  SIGNAL clk_neu : std_logic := '0';            -- Neues Taktsignal
19
  SIGNAL DD : std_logic_vector(3 DOWNTO 0);        -- Zähler - Mehrbitvektor 
20
  SIGNAL segm: STD_LOGIC_VECTOR(6 DOWNTO 0);      -- Segmente der 7-Segment-Anzeige - Mehrbitvektor
21

22
BEGIN
23

24
PROCESS BEGIN                             -- FREQUENZTEILER
25
wait until rising_edge(clk);                  -- Warten auf ansteigende Flanke des Taktsignals clk.
26
  if (teiler<999999) then                    -- Wenn teiler kleiner als 999999 dann
27
    teiler   <= teiler+1;                  -- wird teiler der Wert teiler+1 zugewiesen und
28
    clk_neu <= '0';                      -- clk_neu wird der Wert 0 zugewiesen
29
  else                                -- sonst
30
    teiler   <= 0;                        -- wird teiler der Wert 0 und
31
    clk_neu <= '1';                      -- clk_neu der Wert 1 zugewiesen
32
  end if;
33
END PROCESS;
34

35
PROCESS BEGIN                                -- VORWÄRTSZÄHLER
36
WAIT UNTIL rising_edge(clk_neu);                    -- warten auf ansteigende Flanke von clk_neu(0->1)
37
  IF (clk='1') THEN                           -- Wenn 1 Sekunde vorbei dann
38
    IF reset = '0' THEN                        -- WENN reset den Wert Null hat DANN
39
      DD <= (others => '0');                    -- setze alle Zählerbits auf Null
40
    ELSE                                  -- SONST
41
      DD <= CONV_STD_LOGIC_VECTOR(UNSIGNED(DD) + 1, 4);  -- DD nach oben zählen: n, n+1, n+2, ..., 15, 0, 1, ...
42
    END IF;
43
  END IF;
44
END PROCESS;
45

46
PROCESS BEGIN                            -- BCD_DECODER
47
IF (reset = '1') then                      -- WENN Signal reset den Wert 1 hat DANN
48
         segm <= "0000000";                  -- weise segm den Wert 0000000 zu
49
      elsif (clk_neu'event and clk_neu = '1') then    -- SONST WENN warten auf ansteigende Flanke von clk_neu(0->1) DANN
50
    -- Wenn 1 Sekunde vorbei dann
51
  CASE DD IS                            -- Fallunterscheidung -> Wenn Kontrollausdruck DD
52
  WHEN "0000"=>segm<="0000001"; -- 0               den Testausdruck 0000 hat dann weise segm den Wert 0000001 zu, us.w.
53
  WHEN "0001"=>segm<="1001111";  -- 1
54
  WHEN "0010"=>segm<="0010010";  -- 2
55
  WHEN "0011"=>segm<="0000110";  -- 3
56
  WHEN "0100"=>segm<="1001100";  -- 4
57
  WHEN "0101"=>segm<="0100100";  -- 5
58
  WHEN "0110"=>segm<="0100000";  -- 6
59
  WHEN "0111"=>segm<="0001111";  -- 7
60
  WHEN "1000"=>segm<="0000000";  --  8
61
  WHEN "1001"=>segm<="0000100";  -- 9
62
  WHEN "1010"=>segm<="0000010";  -- A
63
  WHEN "1011"=>segm<="1100000";  -- b
64
  WHEN "1100"=>segm<="0110001";  -- C
65
  WHEN "1101"=>segm<="1000010";  -- d
66
  WHEN "1110"=>segm<="0010000";  --  E
67
  WHEN "1111"=>segm<="0111000";  -- F
68
  WHEN OTHERS=>segm<="0000000"; -- mögliche andere Fälle
69
  END CASE;
70
END IF;
71
END PROCESS;
72
-- Verbinde die internen Zähler mit den Ausgängen  
73
  a <= segm (6);
74
  b <= segm (5);
75
  c <= segm (4);
76
  d <= segm (3);
77
  e <= segm (2);
78
  f <= segm (1);
79
  g <= segm (0);
80
END Behavioral;
#1475964
Lesenswert?

Probier mal
1
PROCESS BEGIN                                -- VORWÄRTSZÄHLER
2
WAIT UNTIL rising_edge(clk_neu);                    -- warten auf ansteigende Flanke von clk_neu(0->1)
3
  IF (clk_neu='1') THEN                           -- Wenn 1 Sekunde vorbei dann
bei dem zweiten Prozess. Ich würde da clk_neu nehmen anstelle von clk.

Außerdem ist eine Awareness Liste beim PROCESS nötig:

z.B.:
1
PROCESS (clk_neu) BEGIN
beim zweiten PROCESS. Beim ersten wäre es wohl (clk).

Meine Meinung.
Moderator (Firma: Titel) Persönliche Seite #1475991
Lesenswert?

Ohne das genauer angeschaut zu haben, hast du eine Anfängerregel 
verletzt: Nur 1 Takt im Design. Ein Takt ist alles, was mit 'event oder 
rising_edge() oder falling_edge()zu tun hat.

Fazit: Dreh das mal etwa so um
1
WAIT UNTIL rising_edge(clk);  
2
  IF (clk_neu='1') THEN       -- Wenn 1 Sekunde vorbei dann
3

4
:
5
PROCESS BEGIN                            -- BCD_DECODER
6
  IF (reset = '1') then                      -- WENN Signal reset den Wert 1 hat DANN
7
       segm <= "0000000";                  -- weise segm den Wert 0000000 zu
8
  elsif (clk'event and clk = '1') then    -- SONST WENN 
9
    IF (clk_neu='1') THEN       -- Wenn 1 Sekunde vorbei dann
10
:

EIDT:
> Außerdem ist eine Awareness Liste beim PROCESS nötig:
Eine Sensitivliste ist nur bei einem Prozess ohne wait nötig.
Gast #1475993
Lesenswert?

Was ich so auf den ersten Blick feststelle:

* Ich würde mal einen sauberen/einheitlichen Codingstil verwenden. Alle 
Prozesse sind geclockt und sollten somit mal einen sauberen Resetzweig 
und Clockabfrage beinhalten:

z.B.

Prozess 1:  if reset= '1'then
              teiler  <=  0;  -- eventuell unsigned verwenden
              clk_neu <= '0';
            elsif clk = '1' and clk'event then
              *
              *
              *
            end if;

Prozess 1:  if reset= '1'then
             DD <=(others => '0');
            elsif clk_neu = '1' and clk_neu'event then
              *
              *
              *
            end if;

* Im Prozess zwei ist der Reset Low Sensitiv und im Prozess drei High 
Sensitiv!!!!!??

* In Prozess werden beide Clocks vermischt.

Meine Meinung, hoffe es hilft.

Gruss Hubert
Moderator (Firma: Titel) Persönliche Seite #1476017
Lesenswert?

Entweder alles so:
1
process begin
2
   wait until rising_edge(clk);          
3
   if reset='1' then
4
       :
5
   else
6
       :
7
   end if;
8
end process;
Oder alles so:
1
process (clk, reset) begin
2
   if rising_edge(clk) then
3
      if reset='1' then
4
       :
5
      else
6
       :
7
      end if;
8
   end if;
9
end process;
Oder alles so:
1
process (clk, reset) begin
2
   if reset='1' then
3
      :
4
   elsif rising_edge(clk) then
5
       :
6
   end if;
7
end process;
Aber wenigstens alles gleich.

Wobei ich die erste Variante (aus verschiedenen Gründen) bevorzuge  ;-)

EDIT:
> Du muss deinen Code aufräumen, vor allem die Resetbedingungen!
Am besten: den Reset gleich weglassen...
Gast #1476024
Lesenswert?

@Lothar

Aus welchen Gründen bevorzugts du die erste Variante?

Was mir noch auffällt:

Du willst ja mit clk_neu zählen und das Ergebnis in Abhängig von DD in 
"segm" dekodieren und speichern.

So wirst du immer um einen Zählschritt hinten nach sein. Soll heissen, 
wenn er z.B. auf 7 zählt wird er noch 6 speichern, dekodieren und 
darstellen.
Moderator (Firma: Titel) Persönliche Seite #1476037
Lesenswert?

> Aus welchen Gründen bevorzugts du die erste Variante?
Siehe dort:
http://www.lothar-miller.de/s9y/archives/16-Takt-im-Prozess.html

Und dazu kommt die bereits angesprochene Reset-Geschichte. Asynchrone 
Resets bringen urige Probleme mit sich. Siehe dazu den 
Beitrag "Re: FSM Problem(Ein zustand als Taktverzögerung)"

EDIT:
> So wirst du immer um einen Zählschritt hinten nach sein.
Richtig, aus diesem Grund sollte die ganze Decodiergeschichte eigentlich 
concurrent oder in einem kombinatorischen Prozess ablaufen.
Gast #1476858
Lesenswert?

Aktuell sieht der Code noch so aus: (und funktioniert immer noch nicht)
1
library IEEE;
2
  use IEEE.std_logic_1164.all;           -- importiere std_logic types
3
  use IEEE.std_logic_arith.all;         -- importiere add/sub vom std_logic_vector
4
  use IEEE.STD_LOGIC_UNSIGNED.ALL;
5

6
ENTITY sieben_segment IS
7
  PORT ( -- Eingänge
8
      clk               : IN  std_logic;      -- Eingangstakt
9
      reset              : IN  std_logic;      -- Zähler Rücksetzeingang
10
    --  updown             : IN  std_logic;      -- Zählrichtung up/down
11
      -- Ausgänge 
12
      a, b, c, d, e, f, g  : OUT std_logic);     -- Eingänge der 7-Segment-Anzeige
13
END sieben_segment;
14

15
ARCHITECTURE Behavioral OF sieben_segment IS
16
-- interne Signal Deklaration
17
  SIGNAL teiler: integer range 0 to 999999;       -- Signal teiler deklariert: Mit diesem Wert kann aus 1MHz Sekundentakt gemacht werden
18
  SIGNAL clk_neu : std_logic := '0';            -- Neues Taktsignal
19
  SIGNAL DD : std_logic_vector(3 DOWNTO 0);        -- Zähler - Mehrbitvektor 
20
  SIGNAL segm: STD_LOGIC_VECTOR(6 DOWNTO 0);      -- Segmente der 7-Segment-Anzeige - Mehrbitvektor
21

22
BEGIN
23

24
PROCESS BEGIN                             -- FREQUENZTEILER
25
wait until rising_edge(clk);                  -- Warten auf ansteigende Flanke des Taktsignals clk.
26
if (teiler<999999) then                    -- Wenn teiler kleiner als 999999 dann
27
    teiler   <= teiler+1;                  -- wird teiler der Wert teiler+1 zugewiesen und
28
    clk_neu <= '0';                      -- clk_neu wird der Wert 0 zugewiesen
29
  else                                -- sonst
30
    teiler   <= 0;                        -- wird teiler der Wert 0 und
31
    clk_neu <= '1';                      -- clk_neu der Wert 1 zugewiesen
32
  end if;
33
END PROCESS;
34

35
PROCESS BEGIN                                -- VORWÄRTSZÄHLER
36
WAIT UNTIL rising_edge(clk);                          -- warten auf ansteigende Flanke von clk_neu(0->1)
37
IF (clk_neu='1') THEN                         -- Wenn 1 Sekunde vorbei dann
38
    IF reset = '0' THEN                        -- WENN reset den Wert Null hat DANN
39
      DD <= (others => '0');                    -- setze alle Zählerbits auf Null
40
    ELSE                                  -- SONST
41
      DD <= CONV_STD_LOGIC_VECTOR(UNSIGNED(DD) + 1, 4);  -- DD nach oben zählen: n, n+1, n+2, ..., 15, 0, 1, ...
42
    END IF;
43
  END IF;
44
END PROCESS;
45

46
PROCESS BEGIN                            -- BCD_DECODER
47
IF (reset = '1') then                      -- WENN Signal reset den Wert 1 hat DANN
48
         segm <= "0000000";                  -- weise segm den Wert 0000000 zu
49
      elsif (clk'event and clk = '1') then          -- SONST WENN warten auf ansteigende Flanke von clk_neu(0->1) DANN
50
if (clk_neu='1') then                      -- Wenn 1 Sekunde vorbei dann
51
  CASE DD IS                            -- Fallunterscheidung -> Wenn Kontrollausdruck DD
52
  WHEN "0000"=>segm<="0000001"; -- 0               den Testausdruck 0000 hat dann weise segm den Wert 0000001 zu, us.w.
53
  WHEN "0001"=>segm<="1001111";  -- 1
54
  WHEN "0010"=>segm<="0010010";  -- 2
55
  WHEN "0011"=>segm<="0000110";  -- 3
56
  WHEN "0100"=>segm<="1001100";  -- 4
57
  WHEN "0101"=>segm<="0100100";  -- 5
58
  WHEN "0110"=>segm<="0100000";  -- 6
59
  WHEN "0111"=>segm<="0001111";  -- 7
60
  WHEN "1000"=>segm<="0000000";  --  8
61
  WHEN "1001"=>segm<="0000100";  -- 9
62
  WHEN "1010"=>segm<="0000010";  -- A
63
  WHEN "1011"=>segm<="1100000";  -- b
64
  WHEN "1100"=>segm<="0110001";  -- C
65
  WHEN "1101"=>segm<="1000010";  -- d
66
  WHEN "1110"=>segm<="0010000";  --  E
67
  WHEN "1111"=>segm<="0111000";  -- F
68
  WHEN OTHERS=>segm<="0000000"; -- mögliche andere Fälle
69
  END CASE;
70
END IF;
71
END IF;
72
END PROCESS;
73
-- Verbinde die internen Zähler mit den Ausgängen  
74
  a <= segm (6);
75
  b <= segm (5);
76
  c <= segm (4);
77
  d <= segm (3);
78
  e <= segm (2);
79
  f <= segm (1);
80
  g <= segm (0);
81
END Behavioral;
Gast #1476877
Lesenswert?

die passenden Warnungen:
WARNING:HDLParsers:1406 - "D:/Probe-Simulation/Probe/counter_updown.vhd" 
Line 65. No sensitivity list and no wait in the process
WARNING:Xst:819 - "D:/Probe-Simulation/Probe/counter_updown.vhd" line 
67: One or more signals are missing in the process sensitivity list. To 
enable synthesis of FPGA/CPLD hardware, XST will assume that all 
necessary signals are present in the sensitivity list. Please note that 
the result of the synthesis may differ from the initial design 
specification. The missing signals are:
   <clk>
WARNING:Xst:819 - "D:/Probe-Simulation/Probe/counter_updown.vhd" line 
65: One or more signals are missing in the process sensitivity list. To 
enable synthesis of FPGA/CPLD hardware, XST will assume that all 
necessary signals are present in the sensitivity list. Please note that 
the result of the synthesis may differ from the initial design 
specification. The missing signals are:
   <reset>
WARNING:NgdBuild:1012 - The constraint <INST "/" KEEP_HIERARCHY = TRUE> 
is
   overridden on the design object sieben_segment by the constraint 
<INST "/"
   KEEP_HIERARCHY = TRUE>.
WARNING:NgdBuild:1012 - The constraint <INST "/" KEEP_HIERARCHY = TRUE> 
is
   overridden on the design object sieben_segment by the constraint 
<INST "/"
   KEEP_HIERARCHY = TRUE>.
WARNING:NgdBuild:1012 - The constraint <INST "/" KEEP_HIERARCHY = TRUE> 
is
   overridden on the design object sieben_segment by the constraint 
<INST "/"
   KEEP_HIERARCHY = TRUE>.
Gast #1476896
Lesenswert?

Mit der kleinen Änderung des Resets im Prozess 3 habe ich das Programm 
zum Laufen gebracht. DANKE, Ihr seit klasse!!!
1
library IEEE;
2
  use IEEE.std_logic_1164.all;           -- importiere std_logic types
3
  use IEEE.std_logic_arith.all;         -- importiere add/sub vom std_logic_vector
4
  use IEEE.STD_LOGIC_UNSIGNED.ALL;
5

6
ENTITY sieben_segment IS
7
  PORT ( -- Eingänge
8
      clk               : IN  std_logic;      -- Eingangstakt
9
      reset              : IN  std_logic;      -- Zähler Rücksetzeingang
10
    --  updown             : IN  std_logic;      -- Zählrichtung up/down
11
      -- Ausgänge 
12
      a, b, c, d, e, f, g  : OUT std_logic);     -- Eingänge der 7-Segment-Anzeige
13
END sieben_segment;
14

15
ARCHITECTURE Behavioral OF sieben_segment IS
16
-- interne Signal Deklaration
17
  SIGNAL teiler: integer range 0 to 999999;       -- Signal teiler deklariert: Mit diesem Wert kann aus 1MHz Sekundentakt gemacht werden
18
  SIGNAL clk_neu : std_logic := '0';            -- Neues Taktsignal
19
  SIGNAL DD : std_logic_vector(3 DOWNTO 0);        -- Zähler - Mehrbitvektor 
20
  SIGNAL segm: STD_LOGIC_VECTOR(6 DOWNTO 0);      -- Segmente der 7-Segment-Anzeige - Mehrbitvektor
21

22
BEGIN
23

24
PROCESS BEGIN                             -- FREQUENZTEILER
25
wait until rising_edge(clk);                  -- Warten auf ansteigende Flanke des Taktsignals clk.
26
if (teiler<999999) then                    -- Wenn teiler kleiner als 999999 dann
27
    teiler   <= teiler+1;                  -- wird teiler der Wert teiler+1 zugewiesen und
28
    clk_neu <= '0';                      -- clk_neu wird der Wert 0 zugewiesen
29
  else                                -- sonst
30
    teiler   <= 0;                        -- wird teiler der Wert 0 und
31
    clk_neu <= '1';                      -- clk_neu der Wert 1 zugewiesen
32
  end if;
33
END PROCESS;
34

35
PROCESS BEGIN                                -- VORWÄRTSZÄHLER
36
WAIT UNTIL rising_edge(clk);                          -- warten auf ansteigende Flanke von clk_neu(0->1)
37
IF (clk_neu='1') THEN                         -- Wenn 1 Sekunde vorbei dann
38
    IF reset = '0' THEN                        -- WENN reset den Wert Null hat DANN
39
      DD <= (others => '0');                    -- setze alle Zählerbits auf Null
40
    ELSE                                  -- SONST
41
      DD <= CONV_STD_LOGIC_VECTOR(UNSIGNED(DD) + 1, 4);  -- DD nach oben zählen: n, n+1, n+2, ..., 15, 0, 1, ...
42
    END IF;
43
  END IF;
44
END PROCESS;
45

46
PROCESS BEGIN                            -- BCD_DECODER
47
IF (reset = '0') then                      -- WENN Signal reset den Wert 1 hat DANN
48
         segm <= "0000000";                  -- weise segm den Wert 0000000 zu
49
      elsif (clk'event and clk = '1') then          -- SONST WENN warten auf ansteigende Flanke von clk_neu(0->1) DANN
50
if (clk_neu='1') then                      -- Wenn 1 Sekunde vorbei dann
51
  CASE DD IS                            -- Fallunterscheidung -> Wenn Kontrollausdruck DD
52
  WHEN "0000"=>segm<="0000001"; -- 0               den Testausdruck 0000 hat dann weise segm den Wert 0000001 zu, us.w.
53
  WHEN "0001"=>segm<="1001111";  -- 1
54
  WHEN "0010"=>segm<="0010010";  -- 2
55
  WHEN "0011"=>segm<="0000110";  -- 3
56
  WHEN "0100"=>segm<="1001100";  -- 4
57
  WHEN "0101"=>segm<="0100100";  -- 5
58
  WHEN "0110"=>segm<="0100000";  -- 6
59
  WHEN "0111"=>segm<="0001111";  -- 7
60
  WHEN "1000"=>segm<="0000000";  --  8
61
  WHEN "1001"=>segm<="0000100";  -- 9
62
  WHEN "1010"=>segm<="0000010";  -- A
63
  WHEN "1011"=>segm<="1100000";  -- b
64
  WHEN "1100"=>segm<="0110001";  -- C
65
  WHEN "1101"=>segm<="1000010";  -- d
66
  WHEN "1110"=>segm<="0010000";  --  E
67
  WHEN "1111"=>segm<="0111000";  -- F
68
  WHEN OTHERS=>segm<="0000000"; -- mögliche andere Fälle
69
  END CASE;
70
END IF;
71
END IF;
72
END PROCESS;
73
-- Verbinde die internen Zähler mit den Ausgängen  
74
  a <= segm (6);
75
  b <= segm (5);
76
  c <= segm (4);
77
  d <= segm (3);
78
  e <= segm (2);
79
  f <= segm (1);
80
  g <= segm (0);
81
END Behavioral;
Moderator (Firma: Titel) Persönliche Seite #1476903
Lesenswert?

> und funktioniert immer noch nicht...
Mach mal eine Testbench, dann kommst du bald auf das "WARUM?"
Bei mir gehts... :-/

Um auf Duke Scarrings Frage zurückzukommen:
Hast du auch eine UCF-Datei?

EDIT:
> Mit der kleinen Änderung des Resets...
Allerdings hast du etliche Warnungen des Synthesizers einfach ignoriert. 
Daran solltest du noch arbeiten...  :-/
Angehängte Dateien:
Gast #1477260
Lesenswert?

Laut deinem Posting wo es funktioniert ist dein Reset Low Sensitiv. Da 
du den Code von Lothar verwendest muss der Prozess 2 wiefolgt 
funktionieren:
1
PROCESS BEGIN                   
2
  WAIT UNTIL rising_edge(clk);  
3
  IF (clk_neu='1') THEN         
4
    IF reset = '0' THEN    -- Polarität Reset                
5
      DD <= (others => '0');             
6
    ELSE                                 
7
      DD <= DD+1;  ---- wenn schon  std_logic_arith, dann so
8
------      DD <= CONV_STD_LOGIC_VECTOR(UNSIGNED(DD) + 1, 4);  
9
    END IF;
10
  END IF;
11
END PROCESS;

Also den auskommentieren reset einkommentieren! Den anderen löschen.
Moderator (Firma: Titel) Persönliche Seite #1477427
Lesenswert?

> Leider geht das auch nicht.(hatte ich ja bereits geschrieben)
Hast du das schon wieder auf 999999 korrigiert?
1
  if (teiler<99) then
Ich hatte den Wert nur für die Simulation so niedrig angesetzt.

> Mir ist aufgefallen, dass wenn ich IF reset = '0' THEN  schreibe, der
> svf-File um mehr als das doppelte größer wird als sonst.
Das SVF-File ist ein etwas ungeeigneter Ort, um die auslastung eines 
FPGAs festzustellen. Dafür gibt es entsprechende Analysetools.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren