mikrocontroller.net

Forum: FPGA, VHDL & Co. Ein einfaches Blinklicht


Autor: Herbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich bin VHDL-Anfänger und möchte ein Blinklicht (im Sekundentakt) 
implementieren. Ich habe den folgenden Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity LCD is
  port( CLK : in std_logic; -- 40 MHz
        LEDS : out std_logic_vector(7 downto 0));
end LCD;

architecture LCDARCH of LCD is
  -- miscrosecond clock
  signal CNT0 : unsigned(31 downto 0) := (others => '0');
  signal USCLK : std_logic := '1';
  signal USTM : unsigned(31 downto 0) := (others => '0');
  -- millisecond clock
  signal CNT1 : unsigned(31 downto 0) := (others => '0');
  signal MSCLK : std_logic := '1';
  signal MSTM : unsigned(31 downto 0) := (others => '0');
  -- second clock
  signal CNT2 : unsigned(31 downto 0) := (others => '0');
  signal SCLK : std_logic := '1';
  signal STM : unsigned(31 downto 0) := (others => '0');
begin
  -- generate clocks
  CLOCK: process(CLK)
  begin
    if CLK'event and CLK = '1' then
      CNT0 <= CNT0 + 1;
      if CNT0 = 20 then
        USCLK <= not USCLK;
      elsif CNT0 = 40 then
        CNT0 <= (others => '0');
        USCLK <= not USCLK;
        USTM <= USTM + 1;
        CNT1 <= CNT1 + 1;
      end if;
      if CNT1 = 500 then
        MSCLK <= not MSCLK;
      elsif CNT1 = 1000 then
        CNT1 <= (others => '0');
        MSCLK <= not MSCLK;
        MSTM <= MSTM + 1;
        CNT2 <= CNT2 + 1;
      end if;
      if CNT2 = 500 then
        SCLK <= not SCLK;
        LEDS <= (others => '0'); -- aus
      elsif CNT2 = 1000 then
        CNT2 <= (others => '0');
        SCLK <= not SCLK;
        STM <= STM + 1;
        LEDS <= (others => '1'); -- an
      end if;
    end if;
  end process CLOCK;
end LCDARCH;

(Das ganze heißt LCD, da das irgendwann mal eine LCD-Ansteuerung werden 
soll.) In der Simulation funktioniert das alles auch ganz super, aber 
wenn ich das ganze in Hardware synthetisiere (Actel PoASIC3E A3PE1500), 
blinken die LEDs nicht, sondern sind konstant hell. Woran kann das 
liegen? Über andere Anmerkungen oder Verbesserungen zu meinem Code freue 
ich mich natürlich auch.

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

Bewertung
0 lesenswert
nicht lesenswert
Herbert schrieb:
> Woran kann das liegen?
Was meinst du, wie schnell mit 40MHz auf 1000 gezählt ist?

> In der Simulation funktioniert das alles auch ganz super
Dann schau dort mal nach, wie lange so eine LED ein- und ausgeschaltet 
ist.

Autor: Herbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich dachte, ich zãhle mit den 3 coutern bis 40*1000*1000?

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

Bewertung
0 lesenswert
nicht lesenswert
> Ich dachte, ich zãhle mit den 3 coutern bis 40*1000*1000?
Ok, du hast recht, dein Code hat mich verwirrt...

Mir schwant übles (für die Zukunft): Du erzeugst dir irgendwie 
irgendwelche symmetrischen Takte..
      CNT0 <= CNT0 + 1;
      if CNT0 = 20 then
         USCLK <= not USCLK;
      ...
So macht man das in realer Hardware nicht. Sondern man macht einen Puls 
(=Clock-Enable), der genau 1 Takt vom Mastertakt lang aktiv ist.

Zähler schreibst du am besten als integer, dann wird das 
natürlichsprachlicher...

Ich schreibe deinen Code mal um (dass ich den auch kapiere):
architecture LCDARCH of LCD is
  -- prescaler /40
  signal PRESC: integer range 0 to 39;
  -- miscrosecond enable
  signal USCLK : std_logic := '0';
  signal USTM  : integer range 0 to 999 := 0;
  -- millisecond enable
  signal MSCLK : std_logic := '1';
  signal MSTM  : integer range 0 to 999 := 0;
  -- second enable
  signal SCLK  : std_logic := '1';
  signal STM   : integer := 0;
begin

  CLOCK: process(CLK)   --- Enables erzeugen
  begin
    if CLK'event and CLK = '1' then
      PRESC <= PRESC+ 1;
      USEN  <= '0';
      if PRESC= 39 then  --- !!!!  0...39 sind 40 Zählschritte
        PRESC <= 0;
        USEN  <= '1';
        USTM  <= USTM + 1;
      end if;

      MSEN <= '0';
      if USTM = 999 then  --- 0...999
        USTM <= 0;
        MSEN <= '1';
        MSTM <= MSTM + 1;
      end if;

      SEN  <= '0';
      if MSTM = 999 then  --- 0...999
        MSTM <= 0;
        SEN  <= '1';
        STM  <= STM + 1;
      end if;
    end if;
  end process CLOCK;

  LED: process(CLK)   --- Enable verwenden
  begin
    if rising_edge(CLK) then
      if SEN='1' then  
         LEDS <= not LEDS;
      end if;
  end process;

Herbert schrieb:
> wenn ich das ganze in Hardware synthetisiere (Actel PoASIC3E A3PE1500),
> blinken die LEDs nicht, sondern sind konstant hell.
Hast du überhaupt irgendwelche Pinzuordnungen gemacht (User 
constraints)?

Autor: Herbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pin-Zuweisungen habe ich gemacht. Es funktioniert so dennoch nicht. Aber 
es geht, wenn ich die Clocks separat generiere:

architecture LCDARCH of LCD is
  -- miscrosecond clock
  signal CNT0 : integer range 0 to 39 := 0;
  signal USCLK : std_logic := '0';
  signal USTM : integer := 0;
  -- millisecond clock
  signal CNT1 : integer range 0 to 39999 := 0;
  signal MSCLK : std_logic := '0';
  signal MSTM : integer := 0;
  -- second clock
  signal CNT2 : integer range 0 to 39999999 := 0;
  signal SCLK : std_logic := '0';
  signal STM : integer := 0;
begin

  CLOCK: process
  begin
    wait until CLK'event and CLK = '1';
    CNT0 <= CNT0 + 1;
    if CNT0 = 0 then
      USCLK <= '1';
      USTM <= USTM + 1;
    else
      USCLK <= '0';
    end if;

    CNT1 <= CNT1 + 1;
    if CNT1 = 0 then
      MSCLK <= '1';
      MSTM <= MSTM + 1;
    else
      MSCLK <= '0';
    end if;

    CNT2 <= CNT2 + 1;
    if CNT2 = 0 then
      SCLK <= '1';
      STM <= STM + 1;
    else
      SCLK <= '0';
    end if;
  end process CLOCK;

  LED: process
  begin
    wait until SCLK'event and SCLK = '1';
    LEDS <= not LEDS;
  end process LED;
end LCDARCH;

Irgendwie seltsam. Ich bekomme beim synthetisieren übrigens immer die 
folgende Warnung:

W  MT420  Found inferred clock LCD|SCLK_inferred_clock with period 25.00ns. A user-defined clock should be declared on object "n:SCLK"

Was bedeute diese?

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

Bewertung
0 lesenswert
nicht lesenswert
Herbert schrieb:
> Es funktioniert so dennoch nicht.
Was funktioniert nicht?

>  Aber es geht, wenn ich die Clocks separat generiere:
Der gepostete Code funktioniert mit Garantie nicht so, wie du es willst.
  signal CNT0 : integer range 0 to 39 := 0;
  :
  :
begin

  CLOCK: process
  begin
    wait until CLK'event and CLK = '1';
    CNT0 <= CNT0 + 1;  -- wie weit wird der CNT0 wohl zählen?
    if CNT0 = 0 then
      :
    else
      :
    end if;
Es gibt hier keinen automatischen Überlauf von 39 nach 0 !!!
CNT0 zählt in der realen Hardware bis 63 und läuft dann auf 0 über...
Rate mal, wie ich auf 63 komme (Als Tipp: wieviele Bits braucht die Zahl 
39)?

Bei den 999 ist es übrigens wesentlich weniger ungenau, denn der nächste 
Überlauf passiert da bei 1023.


> Was bedeute diese?
Dass du jetzt einen Takt verwendest, der nicht von einem Taktnetz kommt.
Und kaum zu glauben: gerade erst habe ich geschreiben, mir schwane 
Übles, und schon macht er es...  :-/
    wait until CLK'event and CLK = '1';
    :
    wait until SCLK'event and SCLK = '1';
Absolut unnötigerweise 2 Takte in 1 Design. Lies dir mal den 
Beitrag "Re: VHDL Einsteigerset" durch. Insbesondere 
den Abschnitt zum Anfängerdesign.

Probiers mal mit meinem Code...
  LED: process(CLK)   --- Enable verwenden
  begin
    if rising_edge(CLK) then
      if SEN='1' then  
         LEDS <= not LEDS;
      end if;
    end if;
  end process;
Oder versuch mal nachzuvollziehen, wie ich das meine...

Autor: Herbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was funktioniert nicht?
Es hat nicht geblinkt.

> Es gibt hier keinen automatischen Überlauf von 39 nach 0 !!!
Oh, stimmt. Das erklärt auch, warum es viel zu langsam geblinkt hat.

> Oder versuch mal nachzuvollziehen, wie ich das meine...
Jetzt verstehe ich, danke. Die Warnung erscheint aber auch für CLK:
W  MT420  Found inferred clock LCD|CLK with period 25.00ns. A user-defined clock should be declared on object "p:CLK"  -  LCD.srr

Muss ich den Systemtakt irgendwie besonders deklarieren? Bis jetzt habe 
ich nur:
CLK : in std_logic;
und CLK an den Pin angeschlossen, an dem der Oszillator liegt.

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

Bewertung
0 lesenswert
nicht lesenswert
Herbert schrieb:
> Muss ich den Systemtakt irgendwie besonders deklarieren?
> Bis jetzt habe ich nur: CLK : in std_logic; und CLK an den
> Pin angeschlossen, an dem der Oszillator liegt.
Ich kenne Actel FPGAs nicht, aber wenn der Pin ein Taktpin ist, dann 
sollte das automatisch gehen (zumindest klappt das bei Lattice und 
Xilinx). Evtl. mußt du da noch irgendwas deklarieren. Da hilft nur die 
Actel-Doku weiter.

>> Es gibt hier keinen automatischen Überlauf von 39 nach 0 !!!
> Oh, stimmt. Das erklärt auch, warum es viel zu langsam geblinkt hat.
Der Simulator hätte dir aber auch auf die Finger klopfen müssen... :-/

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.