Forum: FPGA, VHDL & Co. Implementierung einer Figur


von zakar95 (Gast)


Lesenswert?

Hallo Leute!

Ich bin noch recht neu in VHDL und probiere mich gerade an ein paar 
Aufgaben und wollte euch diesbezüglich etwas fragen.

Zunächst einmal die Aufgabenstellung:

Insgesamt geht es darum, eine Figur zu bauen. Diese hat einen 
Bewegungsmelder, eine Lampe für Augen und einen Lautsprecher, der Laute 
abgeben kann. Weiterhin hat diese Figur einen Taktgeber, d. h. es gilt
1
entity figur is
2
    port (clock    : in STD_LOGIC;  -- the clock has every second a rising edge
3
          melder : in STD_LOGIC;  -- motion sensor
4
          lichter   : out STD_LOGIC; -- the lamps for the eyes
5
          lautsprecher : out STD_LOGIC  -- the speaker for chain rattling
6
         );
7
end figur;
Wenn eine steigende Flanke kommt, werden Eingaben überprüft. Die Figur 
soll sich aktivieren, wenn der Bewegungsmelder ein Signal bekommt, wobei 
der Lautsprecher dann ebenfalls sofort starten soll. 5 Sekunden später 
wiederum sollen die Augen dann beginnen, zu leuchten. Wenn der Melder 
kein Signal mehr meldet, so soll zuerst das Leuchten und die Laute des 
Sprechers noch 20 Sekunden fortgesetzt werden, anschließend wird der 
Lautsprecher ausgeschaltet und 15 Sekunden später wird dann das Leuchten 
der Augen ausgeschaltet.

Aktuell habe ich gemäß der Beschreibung nach eigener Interpretation es 
folgendermaßen implementiert:
1
architecture Behavioral of figur is
2
begin
3
    activate : process (clock)
4
    variable counter : integer range 0 to 40 := 0;
5
    begin
6
      if rising_edge(clock) then
7
        if (melder = 1) then
8
          lautsprecher <= '1';
9
          if (counter = 5) then
10
            lichter <= '1';
11
          end if;
12
        else
13
          if (counter = 25) then
14
            lautsprecher <= '0';
15
          end if;
16
          if (counter = 40) then
17
            lichter <= '0';
18
          end if;
19
        end if;
20
      end if;
21
      counter := counter + 1;
22
    end process;
23
end Behavioral;
Meine Idee hierbei war, einen counter als Variable zu benutzen (für die 
Sekunden). Mich würde nun einmal interessieren, ob der Ansatz so richtig 
ist bzw. was man genau wo verbessern kann.

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


Lesenswert?

zakar95 schrieb:
> entity figur is
>   port (clock : in STD_LOGIC;  -- the clock has every second a rising edge
Das ist aber kein Design fürs echte Leben, oder? Denn dort hat ein FPGA 
einen Takt im Bereich ab 50MHz aufwärts...

> Die Figur soll sich aktivieren, wenn der Bewegungsmelder ein Signal
> bekommt, wobei der Lautsprecher dann ebenfalls sofort starten soll.
Und wenn sich der Bewegungsmelder für 0,9 Sekunden genau zwischen zwei 
Taktimpulsen regt?

> Meine Idee hierbei war, einen counter als Variable zu benutzen
Warum unnötigerweise eine Variable?
Siehe den Beitrag "Variable vs Signal"

> Wenn der Melder kein Signal mehr meldet, so soll zuerst das Leuchten und
> die Laute des Sprechers noch 20 Sekunden fortgesetzt werden
Solltest du dann bei aktivem Melder nicht irgendwie den Counter 
zurücksetzen?

Mein Tipp: simuliere dein Design einfach mal. Dort kannst du dann ganz 
einfach kontrollieren ob es funktioniert und wenn nicht, was wo schief 
läuft.

> was man genau wo verbessern kann.
Du kannst den Quelltext hier wie in der Bedieungsanleitung nach "Antwort 
schreiben - Wichtige Regeln- erst lesen, dann posten!" beschrieben mit 
den [vhdl]-Tags umrahmen...

von ElKo (Gast)


Lesenswert?

1
[...]
2
    variable counter : integer range 0 to 40 := 0;
3
[...]
4
      counter := counter + 1;
5
[...]
Kurze Zwischenfrage: Wenn der Counter überläuft, geht es bei VHDL 
automatisch bei 0 (bzw. beim Minimum) wieder los?

von chris (Gast)


Lesenswert?

Das Problem hatte ich genau hier

Beitrag "Re: VHDL Grundlagen"

schon mal.

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


Lesenswert?

ElKo schrieb:
> Kurze Zwischenfrage: Wenn der Counter überläuft, geht es bei VHDL
> automatisch bei 0 (bzw. beim Minimum) wieder los?
Nein.
1. Der Simulator gibt einem Fehler aus.
2. Die reale Hardware zählt bis 63 und läuft dann über auf 0.

von Gustl B. (-gb-)


Lesenswert?

Bei Integer zählt der Zähler in der Simulation einfach endlos weiter 
nach oben.

von ElKo (Gast)


Lesenswert?

Super. Danke für die Klarstellung.

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


Lesenswert?

Gustl B. schrieb:
> Bei Integer zählt der Zähler in der Simulation einfach endlos weiter
> nach oben.
Aber eben nicht bei einem eingeschränkten Integer wie hier. Da hält 
der Simulator mit einem Fehler bei 41 an. Und genau deshalb sollte man 
auch solche Bereiche (0 to 40) angeben, denn nur der Designer weiß, dass 
für diesen Zähler eine Wert von 1234567 unsinnig ist.

Im realen FPGA brauchen 0..40 letztlich einen 6 Bit breiten Zähler. Und 
weil kein Überlauf abgehandelt wird, zählt der Zähler auf diesen 6 Bits 
laufend weiter. Und da kommt nach 63 dann eben die 0.

zakar95 schrieb:
> Die Figur soll sich aktivieren...
Was soll denn passieren, wenn der Melder nach dem Abschalten schon nach 
15 Sekunden wieder aktiviert wird? Oder nach 25?

Du musst übrigens bedenken, dass der Melder auch mal 60 Sekunden belegt 
sein kann. Was soll dann passieren? Laut deiner Beschreibung muss 
solange dann sowohl die Leuchte wie auch der Lautsprecher aktiviert 
sein.

Ich würde hier jetzt erst mal die zusammengemantschte Aufgabe in 2 
Teilaufgaben trennen: das Leuchten und den Lautsprecher.
1. Lautsprecher
Für den Lautsprecher wird es ganz einfach: der bekommt einen eigenen 
Timer, der bei aktivem Melder laufend auf 20 gesetzt und bei inaktivem 
Melder heruntergezählt wird. Solange der Timer ungleich 0 ist wird der 
Lautsprecher aktiviert.
2. Leuchten
Diese Aufgabe packst du am einfachsten in einen Zustandsautomaten. In 
dessen Ruhezustand wird der Leuchtenzähler auf 0 gesetzt und gewartet, 
bis der Melder aktiviert wird. Im nächsten Zustand wird der Zähler 
hochgezählt und bei Erreichen des Verzögerungswertes die LEDs 
eingeschaltet. Dann wird im nächsten Zustand gewartet, bis das 
Meldersignal wieder inaktiv wird und die Leuchte verzögert abgeschaltet.

: Bearbeitet durch Moderator
von -gb- (Gast)


Lesenswert?

Lothar M. schrieb:
> Aber eben nicht bei einem eingeschränkten Integer wie hier. Da hält
> der Simulator mit einem Fehler bei 41 an. Und genau deshalb sollte man
> auch solche Bereiche (0 to 40) angeben, denn nur der Designer weiß, dass
> für diesen Zähler eine Wert von 1234567 unsinnig ist.

Nein. Gerade getestet mit VIVADO und dem dortigen Simulator.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.numeric_std.all;
4
5
entity spielwiese is Port(
6
  clk : in std_logic;
7
  output: out std_logic_vector(7 downto 0));
8
end spielwiese;
9
10
architecture Behavioral of spielwiese is
11
12
signal counter: integer range 0 to 15:=0;
13
14
begin
15
16
process begin
17
  wait until rising_edge(clk);
18
  counter <= counter +1;
19
end process;
20
21
output <= std_logic_vector(to_unsigned(counter,8));
22
23
end Behavioral;

Und die Testbench:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.numeric_std.all;
4
5
entity spielwiese_bench is
6
end spielwiese_bench;
7
8
architecture Behavioral of spielwiese_bench is
9
10
component spielwiese is Port(
11
  clk : in std_logic;
12
  output: out std_logic_vector(7 downto 0));
13
end component;
14
15
signal clk: std_logic:='0';
16
signal output: std_logic_vector(7 downto 0):=(others => '0');
17
18
begin
19
20
clk <= not clk after 5 ns;
21
22
uut: spielwiese port map(
23
  clk => clk,
24
  output => output);
25
26
end Behavioral;

von Duke Scarring (Gast)


Lesenswert?

-gb- schrieb:
> VIVADO und dem dortigen Simulator
Der taugt offensichtlich nix.

Bei Modelsim sieht es so aus:
1
# vsim spielwiese_bench
2
# Start time: 11:02:19 on Nov 02,2017
3
# ** Note: (vsim-3812) Design is being optimized...
4
#
5
# //  ModelSim SE-64 10.3d Oct  7 2014
6
# //
7
# //  Copyright 1991-2014 Mentor Graphics Corporation
8
# //  All Rights Reserved.
9
# //
10
# //  THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION
11
# //  WHICH IS THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS
12
# //  LICENSORS AND IS SUBJECT TO LICENSE TERMS.
13
# //
14
# Loading std.standard
15
# Loading std.textio(body)
16
# Loading ieee.std_logic_1164(body)
17
# Loading ieee.numeric_std(body)
18
# Loading work.spielwiese_bench(behavioral)#1
19
run -all
20
run -all
21
# ** Fatal: (vsim-3421) Value 16 is out of range 0 to 15.
22
#    Time: 155 ns  Iteration: 0  Process: /spielwiese_bench/uut/line__16 File: int.vhd
23
# Fatal error in Process line__16 at int.vhd line 18
24
#
25
# HDL call sequence:
26
# Stopped at int.vhd 18 Process line__16
27
#

Duke

von Gustl B. (-gb-)


Lesenswert?

Mag sein, dass der nichts taugt, ist aber einfach zu bedienen und gerade 
Anfänger die sich das VIVADO runterladen werden den verwenden, für die 
ist es nicht offensichtlich, dass das nichts taugt. So wie ich ja auch. 
Bei Integer finde ich das Verhalten sogar noch logisch, wieso sollte das 
irgendwann wieder bei 0 anfangen? Das ist ja nicht auf eine bestimmte 
Anzahl an Bits beschränkt. Wünschenswert wäre eine Warnung wenn ein 
beschränkter Integer über die Schranke läuft, aber ... wenn es diese 
Warnung gäbe, dann auch nur in der Simulation. In Hardware fängt der 
Zähler an wenn alle Bits 1 sind aber nicht wenn eine Schranke 
Beschränkung überschritten wird.
Wenn, dann will ich also, dass die Simulation genauso wie die Hardware 
funktioniert, also der die das Integer erst dann überläuft wenn alle 
Bits gesetzt sind. Und dafür gibt es die Post-Syntheses Functional 
Simulation, die nutze ich dann auch relativ häufig wobei auch die 
normale Simulation OK ist wenn man weiß was sie macht.

von Alexander F. (alexf91)


Lesenswert?

GHDL bricht auch ab:
1
./spielwiese_bench:error: bound check failure at spielwiese.vhd:18
2
./spielwiese_bench:error: simulation failed

von Duke Scarring (Gast)


Lesenswert?

Gustl B. schrieb:
> Mag sein, dass der nichts taugt, ist aber einfach zu bedienen und
> gerade
> Anfänger die sich das VIVADO runterladen werden den verwenden, für die
> ist es nicht offensichtlich, dass das nichts taugt.
Ja, leider. Schade das der Vivadosimulator sich nicht an den 
VHDL-Standard hält.

> Bei Integer finde ich das Verhalten sogar noch logisch, wieso sollte das
> irgendwann wieder bei 0 anfangen?
Es sollte wieder bei -2^31 anfangen. Das sieht zumindest der Standard 
vor.

> Wünschenswert wäre eine Warnung wenn ein
> beschränkter Integer über die Schranke läuft, aber ... wenn es diese
> Warnung gäbe, dann auch nur in der Simulation. In Hardware fängt der
> Zähler an wenn alle Bits 1 sind aber nicht wenn eine Schranke
> Beschränkung überschritten wird.
Richtig.

> Wenn, dann will ich also, dass die Simulation genauso wie die Hardware
> funktioniert, also der die das Integer erst dann überläuft wenn alle
> Bits gesetzt sind. Und dafür gibt es die Post-Syntheses Functional
> Simulation, die nutze ich dann auch relativ häufig wobei
Ich nicht. Ich erwarte vom Simulator eine korrekte Funktionsweise.
Wenn ich Überläufe zulassen will, dann nehme ich entweder 
signed/unsigned oder Modulo bei Integer.
Dann läuft die Verhaltenssimulation identisch zur Hardware. Ohne 
Fehlermeldung und ohne die unnötige Post-Synthesis-Simulation.

Duke

von Gustl B. (-gb-)


Lesenswert?

Ich hätte lieber, dass das Synthesetool auch beschränkte Integer richtig 
in Hardware umwandelt. Wieso sollte man sonst überhaupt Integers 
beschränken? Weil das eben keinen Sinn ergibt und ungenutzte Bits 
sowieso wegoptimiert werden könnte man die Beschränkung ganz weglassen. 
Ich beschränke schon, aber nur auf 2^n-1.

Aber wo wir schon dabei sind:
Wenn ich jetzt einen ungerade beschränkten Integer für die Zustände 
einer FSM verwende, also integer range 0 to 5.

Und dann verwende ich in der FSM auch alle 6 Zustände 0 bis 5, denke mir 
jawohl, es gibt jetzt keine Zustände die nicht abgedeckt sind und liege 
falsch, es werden nämlich 3 Bits für die Zustände verwendet, 8 Zustände 
und nur 6 sind abgedeckt. Klar mit when others wird das gelöst, aber was 
hat dann die Beschränkung gebracht?

von Duke Scarring (Gast)


Lesenswert?

Gustl B. schrieb:
> Und dann verwende ich in der FSM auch alle 6 Zustände 0 bis 5, denke mir
> jawohl, es gibt jetzt keine Zustände die nicht abgedeckt sind und liege
> falsch, es werden nämlich 3 Bits für die Zustände verwendet, 8 Zustände
> und nur 6 sind abgedeckt
Jupp und wenn der Synthesizer der Meinung ist auf one-hot zu kodieren 
hast Du 6 Bits und 58 ungültige Zustände. Da hilft auch when others 
nicht.

Meine Zustände haben übrigens Namen:
1
  type state_t is (IDLE, DOSOMETHING, DOSOMETHINGOTHER, READY);

Finde ich besser als
1
  type s16_type is ( S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16);
(und dabei handelte es sich um Code, mit dem Geld verdient wurde...)

Duke

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


Lesenswert?

Duke Scarring schrieb:
> -gb- schrieb:
>> VIVADO und dem dortigen Simulator
> Der taugt offensichtlich nix.
Die Defaultwerte sind da ganz offensichtlich völlig untauglich 
eingestellt.
Das hatten wir schon mal im 
Beitrag "Re: VGA Versuch - Problem beim Simulieren"
Ich habe das allerdings nicht weiter untersucht...

Gustl B. schrieb:
> Wieso sollte man sonst überhaupt Integers beschränken?
Weil nur du als Entwickler wei0t, dass ein VGA-Zähler nur auf 639 oder 
479 laufen muss. Sobald er größere Werte erreicht, ist das ein Fehler, 
denn das war nicht so geplant.

> Weil das eben
> keinen Sinn ergibt und ungenutzte Bits sowieso wegoptimiert werden
Aber erst weit hinten in der Toolchain mit vielen Meldungen zu "unused 
signals". Wenn man den range mit angibt, dann kann schon der Synthesizer 
die unnötigen Leitungen weglassen. Siehe 
Beitrag "Re: VGA Versuch - Problem beim Simulieren"

: Bearbeitet durch Moderator
von Gustl B. (-gb-)


Lesenswert?

Lothar M. schrieb:
> Weil nur du als Entwickler wei0t, dass ein VGA-Zähler nur auf 639 oder
> 479 laufen muss.

Ja, aber der Entwickler muss den Zähler dann auch im Code zurücksetzen.

Da mir das VIVADO da sowieso keinen Fehler ausspuckt habe ich sowas 
immer händisch in der Testbench abgeprüft oder eben auf die Signale 
geachtet und mal hingeguckt ob da Fehler passieren.

Also ja, wenn der Simulator da einen Fehler meldet sollte man das machen 
weil es aus Debugginggründen sinnvoll ist, das verstehe ich.

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.