mikrocontroller.net

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


Autor: Tetramam (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht lesenswert
> Vielleicht gibt es auch andere Möglichkeiten.
Wie wäre es mit einem Array?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

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

architecture Behavioral of Lauflicht is
  type Rom is array (0 to 7) of std_logic_vector(7 downto 0); 
  constant ledarray : Rom := 
  ("10000000",
   "00100000",
   "00001000",
   "00000010",
   "10000000",
   "00100000",
   "00001000",
   "00000010");
  signal cnt : integer range 0 to 7 := 0;
begin
   process begin
      wait until rising_edge(clk);
      if (cnt<7) then
         cnt <= cnt+1;
      else
         cnt <= 0;
      end if;
   end process;
   leds <= ledarray(cnt);
end Behavioral;

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

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.


entity lauflicht is
  port (   
      clk : in std_logic;
      led : out std_logic_vector (7 downto 0)) ;
end entity lauflicht;


architecture behavioral of lauflicht is
  
  signal counter : std_logic_vector (1 downto 0) := "00";
  signal richtung : std_logic := '0';
  
begin

  neue_position: process (clk)
  begin
    if rising_edge(clk) then
      if counter="11" then
        richtung <= not richtung;
      end if;
      counter <= counter + '1';
    end if;
  end process neue_position;
  
  led(0) <= (not counter(0)) and (not counter(1)) and (not richtung);
  led(2) <= counter(0) and (not counter(1)) and (not richtung);
  led(4) <= (not counter(0)) and counter(1) and (not richtung);
  led(6) <= counter(0) and counter(1) and (not richtung);
  
  led(7) <= (not counter(0)) and (not counter(1)) and richtung;
  led(5) <= counter(0) and (not counter(1)) and richtung;
  led(3) <= (not counter(0)) and counter(1) and richtung;
  led(1) <= counter(0) and counter(1) and richtung;
  
  
end architecture behavioral;



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

Bewertung
0 lesenswert
nicht 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...

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

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

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

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

Bewertung
0 lesenswert
nicht 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

Autor: Tetramam (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
 
ENTITY testbench1 IS
END testbench1;
 
ARCHITECTURE behavior OF testbench1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Lauflicht
    PORT(
         clk : IN  std_logic;
         leds : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';

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

   -- Clock period definitions
   constant clk_period : time := 10ms;
 
BEGIN
 
  -- Instantiate the Unit Under Test (UUT)
   uut: Lauflicht PORT MAP (
          clk => clk,
          leds => leds
        );

  TAKTGEN: prozess
  BEGIN
    clk <= '1';
    wait for 50 ns;
    clk <= '0'
    wait for 50 ns;
  end prozess TAKTGEN
   end process;

END;

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

Bewertung
0 lesenswert
nicht lesenswert
Probiers mal so:
  TAKTGEN: process  BEGIN  -- kein z 
    clk <= '1';
    wait for 50 ns;
    clk <= '0'
    wait for 50 ns;
  end process;

Autor: Tetramam (Gast)
Datum:

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

mein Testbench-File sieht jetzt so aus:
   LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
 
ENTITY testbench1 IS
END testbench1;
 
ARCHITECTURE behavior OF testbench1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Lauflicht
    PORT(
         clk : IN  std_logic;
         leds : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';

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

   -- Clock period definitions
   constant clk_period : time := 10ms;
 
BEGIN
 
  -- Instantiate the Unit Under Test (UUT)
   uut: Lauflicht PORT MAP (
          clk => clk,
          leds => leds
        );
TAKTGEN: process  BEGIN  -- kein z 
    clk <= '1';
    wait for 50 ns;
    clk <= '0'
    wait for 50 ns;
  end process;  
END;

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

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

Autor: Tetramam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Lothar!!!
Das war die Rettung. Kleiner Fehler --> viele Fehlermeldung

Hier noch mal das richtige testbench-file:
   LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
 
ENTITY testbench1 IS
END testbench1;
 
ARCHITECTURE behavior OF testbench1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Lauflicht
    PORT(
         clk : IN  std_logic;
         leds : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';

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

   -- Clock period definitions
   constant clk_period : time := 10ms;
 
BEGIN
 
  -- Instantiate the Unit Under Test (UUT)
   uut: Lauflicht PORT MAP (
          clk => clk,
          leds => leds
        );
TAKTGEN: process  BEGIN  -- kein z 
    clk <= '1';
    wait for 50 ns;
    clk <= '0';
    wait for 50 ns;
  end process;  
END;

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
###### testbench1.vhd(56):    constant clk_period : time := 10ms;
# 
# ** 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.
constant clk_period : time := 10 ms;

Duke

Autor: Tetramam (Gast)
Datum:

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

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

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Tetramam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Takt ist von einer realen Schaltung mit 1MHz.

Autor: Tetramam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es mal eingefügt, wie ich es mir empfohlen wurde.
Ist das so korrekt?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


architecture Behavioral of Lauflicht is
  type Rom is array (0 to 7) of std_logic_vector(7 downto 0); 
  constant ledarray : Rom := 
  ("10000000",
   "00100000",
   "00001000",
   "00000010",
   "10000001",
   "00000100",
   "00010000",
   "01000000");
  signal cnt : integer range 0 to 7 := 0;

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

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

process(clk)
begin
  if rising_edge(clk) then
    if ce='1' then
begin
   process begin
      wait until rising_edge(clk);
      if (cnt<7) then
         cnt <= cnt+1;
      else
         cnt <= 0;
      end if;
   end process;
   leds <= ledarray(cnt);
end Behavioral;
    end if;
  end if;
end process;


process(clk)
begin
  if rising_edge(clk) then
    if cnt=cnt_div-1 then
      ce  <= '1';
      cnt <= 0;
    else
      ce  <= '0';
      cnt <= cnt +1 ;
    end if;
  end if;
end process;

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

Bewertung
0 lesenswert
nicht 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:
   process begin
      wait until rising_edge(clk);
      if (ce='1') then      --------------- hier z.B.
         if (cnt<7) then
            cnt <= cnt+1;
         else
            cnt <= 0;
         end if;
      end if;
   end process;

BTW
Hin- und herkopieren reicht nicht aus:
ein wenig solltest du schon mitdenken :-/

Autor: Tetramam (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

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

ARCHITECTURE Behavioral OF Lauflicht IS
  type Rom is array (0 to 7) 
  of std_logic_vector(7 downto 0);                 
                                  
  constant ledarray : Rom :=                     
  ("10000000",                              
   "00100000",                              
   "00001000",
   "00000010",
   "10000001",
   "00000100",
   "00010000",
   "01000000");
  signal   cntled : integer range 0 to 7 := 0;        
  constant cnt_div: integer:=21;                     
  signal   cnt:     integer range 0 to cnt_div-1;   
  signal   ce:      std_logic;

BEGIN


PROCESS
BEGIN
  IF clk = '1' and clk'event THEN                  
    IF ce='1' THEN                        
        wait until clk = '1' and clk'event ;              
          IF (ce='1') THEN
            IF (cntled<7) THEN              
            cntled <= cntled+1;               
            ELSE                        
            cntled <= 0;                  
            END IF;
            leds <= ledarray(cntled);     
          END IF;
    END IF;
  END IF;
END PROCESS;


PROCESS
BEGIN
  IF clk = '1' and clk'event THEN    
  IF cnt=cnt_div-1 THEN                    
      ce  <= '1';                            
      cnt <= 0;                             
    ELSE                               
      ce  <= '0';                            
      cnt <= cnt +1 ;                         
    END IF;
  END IF;
END PROCESS;
END Behavioral;

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

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.