Forum: FPGA, VHDL & Co. Ein einfaches Blinklicht


von Herbert (Gast)


Lesenswert?

Hallo!

Ich bin VHDL-Anfänger und möchte ein Blinklicht (im Sekundentakt) 
implementieren. Ich habe den folgenden Code:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity LCD is
6
  port( CLK : in std_logic; -- 40 MHz
7
        LEDS : out std_logic_vector(7 downto 0));
8
end LCD;
9
10
architecture LCDARCH of LCD is
11
  -- miscrosecond clock
12
  signal CNT0 : unsigned(31 downto 0) := (others => '0');
13
  signal USCLK : std_logic := '1';
14
  signal USTM : unsigned(31 downto 0) := (others => '0');
15
  -- millisecond clock
16
  signal CNT1 : unsigned(31 downto 0) := (others => '0');
17
  signal MSCLK : std_logic := '1';
18
  signal MSTM : unsigned(31 downto 0) := (others => '0');
19
  -- second clock
20
  signal CNT2 : unsigned(31 downto 0) := (others => '0');
21
  signal SCLK : std_logic := '1';
22
  signal STM : unsigned(31 downto 0) := (others => '0');
23
begin
24
  -- generate clocks
25
  CLOCK: process(CLK)
26
  begin
27
    if CLK'event and CLK = '1' then
28
      CNT0 <= CNT0 + 1;
29
      if CNT0 = 20 then
30
        USCLK <= not USCLK;
31
      elsif CNT0 = 40 then
32
        CNT0 <= (others => '0');
33
        USCLK <= not USCLK;
34
        USTM <= USTM + 1;
35
        CNT1 <= CNT1 + 1;
36
      end if;
37
      if CNT1 = 500 then
38
        MSCLK <= not MSCLK;
39
      elsif CNT1 = 1000 then
40
        CNT1 <= (others => '0');
41
        MSCLK <= not MSCLK;
42
        MSTM <= MSTM + 1;
43
        CNT2 <= CNT2 + 1;
44
      end if;
45
      if CNT2 = 500 then
46
        SCLK <= not SCLK;
47
        LEDS <= (others => '0'); -- aus
48
      elsif CNT2 = 1000 then
49
        CNT2 <= (others => '0');
50
        SCLK <= not SCLK;
51
        STM <= STM + 1;
52
        LEDS <= (others => '1'); -- an
53
      end if;
54
    end if;
55
  end process CLOCK;
56
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.

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


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.

von Herbert (Gast)


Lesenswert?

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

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


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..
1
      CNT0 <= CNT0 + 1;
2
      if CNT0 = 20 then
3
         USCLK <= not USCLK;
4
      ...
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):
1
architecture LCDARCH of LCD is
2
  -- prescaler /40
3
  signal PRESC: integer range 0 to 39;
4
  -- miscrosecond enable
5
  signal USCLK : std_logic := '0';
6
  signal USTM  : integer range 0 to 999 := 0;
7
  -- millisecond enable
8
  signal MSCLK : std_logic := '1';
9
  signal MSTM  : integer range 0 to 999 := 0;
10
  -- second enable
11
  signal SCLK  : std_logic := '1';
12
  signal STM   : integer := 0;
13
begin
14
15
  CLOCK: process(CLK)   --- Enables erzeugen
16
  begin
17
    if CLK'event and CLK = '1' then
18
      PRESC <= PRESC+ 1;
19
      USEN  <= '0';
20
      if PRESC= 39 then  --- !!!!  0...39 sind 40 Zählschritte
21
        PRESC <= 0;
22
        USEN  <= '1';
23
        USTM  <= USTM + 1;
24
      end if;
25
26
      MSEN <= '0';
27
      if USTM = 999 then  --- 0...999
28
        USTM <= 0;
29
        MSEN <= '1';
30
        MSTM <= MSTM + 1;
31
      end if;
32
33
      SEN  <= '0';
34
      if MSTM = 999 then  --- 0...999
35
        MSTM <= 0;
36
        SEN  <= '1';
37
        STM  <= STM + 1;
38
      end if;
39
    end if;
40
  end process CLOCK;
41
42
  LED: process(CLK)   --- Enable verwenden
43
  begin
44
    if rising_edge(CLK) then
45
      if SEN='1' then  
46
         LEDS <= not LEDS;
47
      end if;
48
  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)?

von Herbert (Gast)


Lesenswert?

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

1
architecture LCDARCH of LCD is
2
  -- miscrosecond clock
3
  signal CNT0 : integer range 0 to 39 := 0;
4
  signal USCLK : std_logic := '0';
5
  signal USTM : integer := 0;
6
  -- millisecond clock
7
  signal CNT1 : integer range 0 to 39999 := 0;
8
  signal MSCLK : std_logic := '0';
9
  signal MSTM : integer := 0;
10
  -- second clock
11
  signal CNT2 : integer range 0 to 39999999 := 0;
12
  signal SCLK : std_logic := '0';
13
  signal STM : integer := 0;
14
begin
15
16
  CLOCK: process
17
  begin
18
    wait until CLK'event and CLK = '1';
19
    CNT0 <= CNT0 + 1;
20
    if CNT0 = 0 then
21
      USCLK <= '1';
22
      USTM <= USTM + 1;
23
    else
24
      USCLK <= '0';
25
    end if;
26
27
    CNT1 <= CNT1 + 1;
28
    if CNT1 = 0 then
29
      MSCLK <= '1';
30
      MSTM <= MSTM + 1;
31
    else
32
      MSCLK <= '0';
33
    end if;
34
35
    CNT2 <= CNT2 + 1;
36
    if CNT2 = 0 then
37
      SCLK <= '1';
38
      STM <= STM + 1;
39
    else
40
      SCLK <= '0';
41
    end if;
42
  end process CLOCK;
43
44
  LED: process
45
  begin
46
    wait until SCLK'event and SCLK = '1';
47
    LEDS <= not LEDS;
48
  end process LED;
49
end LCDARCH;

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

1
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?

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


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.
1
  signal CNT0 : integer range 0 to 39 := 0;
2
  :
3
  :
4
begin
5
6
  CLOCK: process
7
  begin
8
    wait until CLK'event and CLK = '1';
9
    CNT0 <= CNT0 + 1;  -- wie weit wird der CNT0 wohl zählen?
10
    if CNT0 = 0 then
11
      :
12
    else
13
      :
14
    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...  :-/
1
    wait until CLK'event and CLK = '1';
2
    :
3
    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...
1
  LED: process(CLK)   --- Enable verwenden
2
  begin
3
    if rising_edge(CLK) then
4
      if SEN='1' then  
5
         LEDS <= not LEDS;
6
      end if;
7
    end if;
8
  end process;
Oder versuch mal nachzuvollziehen, wie ich das meine...

von Herbert (Gast)


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:
1
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:
1
CLK : in std_logic;
und CLK an den Pin angeschlossen, an dem der Oszillator liegt.

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


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

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.