Lauflicht mit individuellen Muster

Gast #1429795
Lesenswert?

Ich habe die Aufgabe gekriegt (im Studium) ein Lauflicht mit VHDL 
umzusetzen, um 8 LED's nach einem bestimmten Muster laufen zu lassen. 
Dabei sollen die Lauflichter nach folgender Reihenfolge aufleuchten:
von links nach rechts: 1->3->5->7 und dann von rechts nach links: 
8->6->4->2
und dann wieder von vorn.
Ich verwende hierfür CPLD XC9572XL und Modelsim als Simulator.
Mir hat als ersten Ansatz diese Seite: 
http://chip.uni-rostock.de/designs/lauflicht.html gut gefallen. Jedoch 
will ich kein Makro verwenden und daher soll alles in eine Datei und 
auch das ersetzen der Nullen und Einsen durch Rauten und Leerzeichen 
gefällt mir nicht.
Da ich mit VHDL noch nie gearbeitet habe, wollte ich euch um Hilfe 
bitten.
Vielleicht gibt es auch andere Möglichkeiten.
Moderator (Firma: Titel) Persönliche Seite #1429814
Lesenswert?

> Vielleicht gibt es auch andere Möglichkeiten.
Wie wäre es mit einem Array?
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4

5
entity Lauflicht is
6
    Port ( clk : in  STD_LOGIC;
7
           leds : out  STD_LOGIC_VECTOR (7 downto 0));
8
end Lauflicht;
9

10
architecture Behavioral of Lauflicht is
11
  type Rom is array (0 to 7) of std_logic_vector(7 downto 0); 
12
  constant ledarray : Rom := 
13
  ("10000000",
14
   "00100000",
15
   "00001000",
16
   "00000010",
17
   "10000000",
18
   "00100000",
19
   "00001000",
20
   "00000010");
21
  signal cnt : integer range 0 to 7 := 0;
22
begin
23
   process begin
24
      wait until rising_edge(clk);
25
      if (cnt<7) then
26
         cnt <= cnt+1;
27
      else
28
         cnt <= 0;
29
      end if;
30
   end process;
31
   leds <= ledarray(cnt);
32
end Behavioral;

BTW:
> 1->2->3->4->5->6->8
und die 7?   :-o
Gast #1429886
Lesenswert?

Och, immer so verschwenderisch.

Ich bevorzuge hier(cpld) die minimalistische Variante. 8 leds macht 8 
mögliche Positionen, also brauchen wir auch nur 3 bit.

1
entity lauflicht is
2
  port (   
3
      clk : in std_logic;
4
      led : out std_logic_vector (7 downto 0)) ;
5
end entity lauflicht;
6

7

8
architecture behavioral of lauflicht is
9
  
10
  signal counter : std_logic_vector (1 downto 0) := "00";
11
  signal richtung : std_logic := '0';
12
  
13
begin
14

15
  neue_position: process (clk)
16
  begin
17
    if rising_edge(clk) then
18
      if counter="11" then
19
        richtung <= not richtung;
20
      end if;
21
      counter <= counter + '1';
22
    end if;
23
  end process neue_position;
24
  
25
  led(0) <= (not counter(0)) and (not counter(1)) and (not richtung);
26
  led(2) <= counter(0) and (not counter(1)) and (not richtung);
27
  led(4) <= (not counter(0)) and counter(1) and (not richtung);
28
  led(6) <= counter(0) and counter(1) and (not richtung);
29
  
30
  led(7) <= (not counter(0)) and (not counter(1)) and richtung;
31
  led(5) <= counter(0) and (not counter(1)) and richtung;
32
  led(3) <= (not counter(0)) and counter(1) and richtung;
33
  led(1) <= counter(0) and counter(1) and richtung;
34
  
35
  
36
end architecture behavioral;
Moderator (Firma: Titel) Persönliche Seite #1429911
Lesenswert?

> Och, immer so verschwenderisch.
Das sieht nur so aus:  meine Lösung braucht nur 3 FFs ;-)
Die Synthese macht das schon richtig, und der Fitter optimiert sich das 
zurecht. Von Vorteil ist, dass das Muster ohne Probleme erkannt und 
geändert werden kann.

Und wenns zum Schluss (noch) nicht hineinpasst, dann kann/muss man ja 
nochmal Hand anlegen...
Gast #1429937
Lesenswert?

Nur 3 FF ?

Ich hätte auf den ersten Blick jetzt vermutet das es gar 64 benötigt, 
wenigstens aber 8.

Manchmal unterschätzt man die Tools wirklich. In dem Fall ist die Lösung 
natürlich sinnvoller.
Gast #1430304
Lesenswert?

Das versteh ich nun garnicht...sicher das dies bei "optimized density" 
raus kommt ?

Denn es sind nur 10 Produkterme, also müsste es doch selbst im 
Extremfall höchstens auf 10 Makrozellen kommen ?

9 sinds ja eh mindestens wegen den 9 nötigen Pins.


Aber gut, das ist nun wirklich nebensächlich, ob 2 Makrozellen mehr oder 
weniger, wegen der Übersichtlichkeit sollte er wohl trotzdem eher die 
Array Methode nutzen.


Ich entwerf für solche Dinge wo sich das anbietet einfach die Funktion 
gerne selbst, das gibt einem irgentwie das Gefühl der Kontrolle, die man 
trotzdem oft nicht hat :)
Moderator (Firma: Titel) Persönliche Seite #1430329
Lesenswert?

> sicher das dies bei "optimized density" raus kommt ?
Jawoll.

> Ich entwerf für solche Dinge wo sich das anbietet einfach die Funktion
> gerne selbst, das gibt einem irgentwie das Gefühl der Kontrolle...
Ich bin eher aus der FPGA-Ecke, dort kann ich mir manuelles Tuning nur 
in Spezialfällen leisten...  ;-)


>>> Nur 3 FF ?
>>> Ich hätte auf den ersten Blick jetzt vermutet das es gar 64 benötigt,
> ...Gefühl der Kontrolle, die man trotzdem oft nicht hat :)
ACK
Gast #1431095
Lesenswert?

Wenn ich das richtig verstanden habe brauche ich auch ein Testbench um 
die Testsignale zu erzeugen. Leider habe ich das nicht so richtig 
hinbekommen.
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.std_logic_unsigned.all;
4
USE ieee.numeric_std.ALL;
5
 
6
ENTITY testbench1 IS
7
END testbench1;
8
 
9
ARCHITECTURE behavior OF testbench1 IS 
10
 
11
    -- Component Declaration for the Unit Under Test (UUT)
12
 
13
    COMPONENT Lauflicht
14
    PORT(
15
         clk : IN  std_logic;
16
         leds : OUT  std_logic_vector(7 downto 0)
17
        );
18
    END COMPONENT;
19
    
20

21
   --Inputs
22
   signal clk : std_logic := '0';
23

24
   --Outputs
25
   signal leds : std_logic_vector(7 downto 0);
26

27
   -- Clock period definitions
28
   constant clk_period : time := 10ms;
29
 
30
BEGIN
31
 
32
  -- Instantiate the Unit Under Test (UUT)
33
   uut: Lauflicht PORT MAP (
34
          clk => clk,
35
          leds => leds
36
        );
37

38
  TAKTGEN: prozess
39
  BEGIN
40
    clk <= '1';
41
    wait for 50 ns;
42
    clk <= '0'
43
    wait for 50 ns;
44
  end prozess TAKTGEN
45
   end process;
46

47
END;
Gast #1431130
Lesenswert?

Folgende Felermeldung kommt wenn ich Lothars Vorlage verwende:
1
 -- Compiling entity testbench1
2
# -- Compiling architecture behavior of testbench1
3
###### testbench1.vhd(56):    constant clk_period : time := 10ms;
4
# 
5
# ** Warning: [4] testbench1.vhd(56): (vcom-1207) An abstract literal and an identifier must have a separator between them.
6
###### testbench1.vhd(69):     wait for 50 ns;
7
# 
8
# ** Error: testbench1.vhd(69): near "wait": expecting ';'
9
###### testbench1.vhd(71): END;
10
# ** Error: testbench1.vhd(71): VHDL Compiler exiting
11
# ** Error: D:/Modeltech_xe_starter/win32xoem/vcom failed.
12
# Error in macro ./testbench1.fdo line 6
13
# D:/Modeltech_xe_starter/win32xoem/vcom failed.
14
#     while executing
15
# "vcom -explicit  -93 "testbench1.vhd""

mein Testbench-File sieht jetzt so aus:
1
   LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.std_logic_unsigned.all;
4
USE ieee.numeric_std.ALL;
5
 
6
ENTITY testbench1 IS
7
END testbench1;
8
 
9
ARCHITECTURE behavior OF testbench1 IS 
10
 
11
    -- Component Declaration for the Unit Under Test (UUT)
12
 
13
    COMPONENT Lauflicht
14
    PORT(
15
         clk : IN  std_logic;
16
         leds : OUT  std_logic_vector(7 downto 0)
17
        );
18
    END COMPONENT;
19
    
20

21
   --Inputs
22
   signal clk : std_logic := '0';
23

24
   --Outputs
25
   signal leds : std_logic_vector(7 downto 0);
26

27
   -- Clock period definitions
28
   constant clk_period : time := 10ms;
29
 
30
BEGIN
31
 
32
  -- Instantiate the Unit Under Test (UUT)
33
   uut: Lauflicht PORT MAP (
34
          clk => clk,
35
          leds => leds
36
        );
37
TAKTGEN: process  BEGIN  -- kein z 
38
    clk <= '1';
39
    wait for 50 ns;
40
    clk <= '0'
41
    wait for 50 ns;
42
  end process;  
43
END;
Gast #1431147
Lesenswert?

Danke Lothar!!!
Das war die Rettung. Kleiner Fehler --> viele Fehlermeldung

Hier noch mal das richtige testbench-file:
1
   LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.std_logic_unsigned.all;
4
USE ieee.numeric_std.ALL;
5
 
6
ENTITY testbench1 IS
7
END testbench1;
8
 
9
ARCHITECTURE behavior OF testbench1 IS 
10
 
11
    -- Component Declaration for the Unit Under Test (UUT)
12
 
13
    COMPONENT Lauflicht
14
    PORT(
15
         clk : IN  std_logic;
16
         leds : OUT  std_logic_vector(7 downto 0)
17
        );
18
    END COMPONENT;
19
    
20

21
   --Inputs
22
   signal clk : std_logic := '0';
23

24
   --Outputs
25
   signal leds : std_logic_vector(7 downto 0);
26

27
   -- Clock period definitions
28
   constant clk_period : time := 10ms;
29
 
30
BEGIN
31
 
32
  -- Instantiate the Unit Under Test (UUT)
33
   uut: Lauflicht PORT MAP (
34
          clk => clk,
35
          leds => leds
36
        );
37
TAKTGEN: process  BEGIN  -- kein z 
38
    clk <= '1';
39
    wait for 50 ns;
40
    clk <= '0';
41
    wait for 50 ns;
42
  end process;  
43
END;
Gast #1431931
Lesenswert?

1
###### testbench1.vhd(56):    constant clk_period : time := 10ms;
2
# 
3
# ** Warning: [4] testbench1.vhd(56): (vcom-1207) An abstract literal and an identifier must have a separator between them

Da steht auch da, was er haben möchte: ein Leerzeichen zwischen Zahl und 
Einheit.
1
constant clk_period : time := 10 ms;

Duke
Moderator (Firma: Titel) Persönliche Seite #1438595
Lesenswert?

> Wie kann ich den Takt von 1MHz runtertakten auf 1 Sekunde, damit man das
> Signal auch sieht?
Du programmierst einen Taktteiler, der dir im Takt von 1 Sekunde ein 
Clock-Enable generiert: Taktung FPGA/CPLD
Mit diesem Clock-Enable wird dann der Takt für dein Lauflicht 
freigegeben.

Allerdings brauchst du in einem CPLD einiges an wertvollen Makrozellen: 
für einen Teiler durch 1 Mio sind 20 FFs nötig  :-o
Moderator Persönliche Seite #1438598
Lesenswert?

Tetramam schrieb:
> Wie kann ich den Takt von 1MHz runtertakten auf 1 Sekunde, damit man das
> Signal auch sieht?

In der Testbench oder im realen Leben?

In der Testbench musst du ja nur die passenden wait-Anweisungen
spendieren im Takt-Prozess.

Im realen Leben musst du noch ein paar Flipflops spendieren und
einen Zähler aufbauen.

Edith: Lothar war schneller...
Gast #1438632
Lesenswert?

Ich habe es mal eingefügt, wie ich es mir empfohlen wurde.
Ist das so korrekt?
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4

5

6
architecture Behavioral of Lauflicht is
7
  type Rom is array (0 to 7) of std_logic_vector(7 downto 0); 
8
  constant ledarray : Rom := 
9
  ("10000000",
10
   "00100000",
11
   "00001000",
12
   "00000010",
13
   "10000001",
14
   "00000100",
15
   "00010000",
16
   "01000000");
17
  signal cnt : integer range 0 to 7 := 0;
18

19
entity Lauflicht is
20
    Port ( clk : in  STD_LOGIC;
21
           leds : out  STD_LOGIC_VECTOR (7 downto 0));
22
end Lauflicht;
23

24
constant cnt_div: integer:=20;                  -- Teilerverhältnis
25
signal   cnt:     integer range 0 to cnt_div-1; -- Zähler für Teiler
26
signal   ce:      std_logic;
27

28
process(clk)
29
begin
30
  if rising_edge(clk) then
31
    if ce='1' then
32
begin
33
   process begin
34
      wait until rising_edge(clk);
35
      if (cnt<7) then
36
         cnt <= cnt+1;
37
      else
38
         cnt <= 0;
39
      end if;
40
   end process;
41
   leds <= ledarray(cnt);
42
end Behavioral;
43
    end if;
44
  end if;
45
end process;
46

47

48
process(clk)
49
begin
50
  if rising_edge(clk) then
51
    if cnt=cnt_div-1 then
52
      ce  <= '1';
53
      cnt <= 0;
54
    else
55
      ce  <= '0';
56
      cnt <= cnt +1 ;
57
    end if;
58
  end if;
59
end process;
Moderator (Firma: Titel) Persönliche Seite #1438705
Lesenswert?

> constant cnt_div: integer:=20;
Der zählt jetzt von 0 bis 19. Reicht dir das?
Du wollstest doch 1000000   :-o

>  signal cnt : integer range 0 to 7 := 0;
>  :
> signal   cnt:     integer range 0 to cnt_div-1; -- Zähler für Teiler
Du kannst nicht einfach den Namen cnt zweimal verwenden (einmal für 
den Enable und einmal für den Index).

Und wenn du dann einen geteilten Takt hast, dann solltest du den auch 
weiterverwenden:
1
   process begin
2
      wait until rising_edge(clk);
3
      if (ce='1') then      --------------- hier z.B.
4
         if (cnt<7) then
5
            cnt <= cnt+1;
6
         else
7
            cnt <= 0;
8
         end if;
9
      end if;
10
   end process;

BTW
Hin- und herkopieren reicht nicht aus:
ein wenig solltest du schon mitdenken :-/
Gast #1459740
Lesenswert?

Es waren noch viele Fehler drin daher habe ich den Quellcode noch einmal 
umgeschrieben. Es erscheint nur noch eine Fehlermeldung:
** Warning: [2] LauflichtTest.vhd(79): (vcom-1090) Possible infinite 
loop: Process contains no WAIT statement.
--> kann ich diese Fehlermeldung ignorieren?

Jetzt sieht der Quellcode folgendermaßen aus:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4

5
ENTITY Lauflicht is
6
    Port ( clk : in  STD_LOGIC;                  
7
           leds : out  STD_LOGIC_VECTOR (7 downto 0));  
8

9
ARCHITECTURE Behavioral OF Lauflicht IS
10
  type Rom is array (0 to 7) 
11
  of std_logic_vector(7 downto 0);                 
12
                                  
13
  constant ledarray : Rom :=                     
14
  ("10000000",                              
15
   "00100000",                              
16
   "00001000",
17
   "00000010",
18
   "10000001",
19
   "00000100",
20
   "00010000",
21
   "01000000");
22
  signal   cntled : integer range 0 to 7 := 0;        
23
  constant cnt_div: integer:=21;                     
24
  signal   cnt:     integer range 0 to cnt_div-1;   
25
  signal   ce:      std_logic;
26

27
BEGIN
28

29

30
PROCESS
31
BEGIN
32
  IF clk = '1' and clk'event THEN                  
33
    IF ce='1' THEN                        
34
        wait until clk = '1' and clk'event ;              
35
          IF (ce='1') THEN
36
            IF (cntled<7) THEN              
37
            cntled <= cntled+1;               
38
            ELSE                        
39
            cntled <= 0;                  
40
            END IF;
41
            leds <= ledarray(cntled);     
42
          END IF;
43
    END IF;
44
  END IF;
45
END PROCESS;
46

47

48
PROCESS
49
BEGIN
50
  IF clk = '1' and clk'event THEN    
51
  IF cnt=cnt_div-1 THEN                    
52
      ce  <= '1';                            
53
      cnt <= 0;                             
54
    ELSE                               
55
      ce  <= '0';                            
56
      cnt <= cnt +1 ;                         
57
    END IF;
58
  END IF;
59
END PROCESS;
60
END Behavioral;

Ist das so korrekt oder habe ich dort vielleicht noch etwas falsch 
verstanden?

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