Forum: FPGA, VHDL & Co. Lauflicht mit individuellen Muster


von Tetramam (Gast)


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.

von Peter (Gast)


Lesenswert?

du kannst sie auch einfach 1->2->3->4->5->6->8 laufen lassen musst dann 
nur definieren das
1 -> LED1
2 -> LED3
3 -> LED5
...
ist.

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


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

von Iulius (Gast)


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;

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


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...

von Iulius (Gast)


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.

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


Lesenswert?

> Nur 3 FF ?
Na gut, das ist nicht die ganze Wahrheit...
Es sind insgesamt 11 Makrozellen nötig:
1
Macrocells     Pterms         Registers    Pins          Function Block Inputs  
2
11/72  (16%)   10/360  (3%)   3/72  (5%)   9/34  (27%)   12/216  (6%)

von Iulius (Gast)


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 :)

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


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

von Tetramam (Gast)


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;

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


Lesenswert?

Probiers mal so:
1
  TAKTGEN: process  BEGIN  -- kein z 
2
    clk <= '1';
3
    wait for 50 ns;
4
    clk <= '0'
5
    wait for 50 ns;
6
  end process;

von Tetramam (Gast)


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;

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


Lesenswert?

> Error: testbench1.vhd(69): near "wait": expecting ';'
Dann mach ihm den ";" halt hin...
1
      clk <= '0';

von Tetramam (Gast)


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;

von Duke Scarring (Gast)


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

von Tetramam (Gast)


Lesenswert?

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

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


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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...

von Tetramam (Gast)


Lesenswert?

Der Takt ist von einer realen Schaltung mit 1MHz.

von Tetramam (Gast)


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;

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


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 :-/

von Tetramam (Gast)


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?

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.