LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
ENTITY stg IS
PORT (
clk : IN std_logic;
reset : IN std_logic;
aktpos : IN std_logic_vector(11 DOWNTO 0);
NotAus : IN std_logic;
Betrieb : IN std_logic;
ESL : IN std_logic; -- endschalter oben
ESR : IN std_logic; -- endschalter unten
cnt_clr : OUT std_logic;
m_li : OUT std_logic;
m_re : OUT std_logic;
m_an : OUT std_logic;
LEDR : OUT std_logic;
state: out integer range 0 to 10 --test
);
END stg;
ARCHITECTURE behv OF stg IS
BEGIN
Process (reset, clk, aktpos, NotAus, Betrieb, ESL, ESR) IS
Type STATE IS (Start, Motor_links, Motor_weiter_links, Motor_rechts,
Motor_weiter_rechts, Notschalter);
Variable zustandsvektor: STATE;
Begin
if reset = '1' then zustandsvektor := Start;
Elsif (clk'event AND clk ='1') Then
CASE zustandsvektor IS
When Start =>
IF NotAus ='1' Then zustandsvektor := Notschalter;
Elsif ESR ='1' Then zustandsvektor := Motor_links;
Elsif ESL ='1' Then zustandsvektor := Motor_rechts;
END IF;
When Motor_links =>
IF NotAus ='1' Then zustandsvektor := Notschalter;
Elsif aktpos < 624 Then zustandsvektor := Start;
Elsif ESR ='1' Then zustandsvektor := Motor_weiter_links;
END IF;
When Motor_weiter_links =>
IF NotAus ='1' Then zustandsvektor := Notschalter;
Elsif aktpos < 624 Then zustandsvektor := Start;
Elsif ESR='1' Then zustandsvektor := Motor_links;
END IF;
When Motor_rechts =>
IF NotAus ='1' Then zustandsvektor := Notschalter;
Elsif aktpos > 1324 Then zustandsvektor := Start;
Elsif ESL ='1' Then zustandsvektor := Motor_weiter_rechts;
END IF;
When Motor_weiter_rechts =>
IF NotAus ='1' Then zustandsvektor := Notschalter;
Elsif aktpos > 1424 Then zustandsvektor := Start;
Elsif ESL ='1' Then zustandsvektor := Motor_rechts;
END IF;
When Notschalter =>
IF Betrieb ='1' Then zustandsvektor := Start;
END IF;
End Case;
End if;
CASE zustandsvektor IS
WHEN Start =>
state <= 0;
m_an <= '1';
m_li <= '0';
m_re <= '0';
cnt_clr <= '1';
LEDR <= '0';
WHEN Motor_links =>
state <= 2;
m_an <= '1';
m_li <= '1';
m_re <= '0';
cnt_clr <= '0';
LEDR <= '0';
WHEN Motor_weiter_links =>
state <= 3;
m_an <= '1';
m_li <= '1';
m_re <= '0';
cnt_clr <= '1';
LEDR <= '0';
WHEN Motor_rechts =>
state <= 4;
m_an <= '1';
m_li <= '0';
m_re <= '1';
cnt_clr <= '0';
LEDR <= '0';
WHEN Motor_weiter_rechts =>
state <= 5;
m_an <= '1';
m_li <= '0';
m_re <= '1';
cnt_clr <= '1';
LEDR <= '0';
WHEN Notschalter =>
state <= 8;
m_an <= '0';
m_li <= '0';
m_re <= '0';
cnt_clr <= '0';
LEDR <= '1';
END CASE;
END PROCESS;
END behv;
-- kann mir einer sagen was genau der error bedeute, bzw warum ist state
kein signal.
Error (10477): VHDL error at stg.vhd(79): name "STATE" must represent
signal
Error (10517): VHDL type mismatch error at stg.vhd(79): STATE type does
not match integer literal
Polo schrieb:> state: out integer range 0 to 10 --testdang :-)
In VHDL kann man nicht den gleichen Namen für verschiedene Dinge, in
diesem Fall, einen Port und einen Typ, verwenden.
Übrigens hast noch einige weitere Fehler und unschönheiten in deinem
Design.
1) Mixe keine kombinatorische und getaktete Logik in einem Prozess. Wenn
du beides trennen möchtest, nimm 2 Prozesse.
2) Benutze keine Variable als speicherndes Element! Das geht schief. Mal
im Forum suchen nach "signal vs variable". Kurz: eigentlich müsste deine
Variable "zustandsvektor" in die Prozessensitivity List. Das geht jedoch
nicht, da Signale keine events haben, und damit auch keine Processe
triggern können. Folge: Deine Simulation wird falsche Ergebnisse
anzeigen!
3)
> if (clk'event AND clk ='1')
Schöner (und richtiger!) ist rising_edge(clk). Alles andere kann
Probleme bei der Simulation machen.
4) Deine Sensitivity List: Für einen getakteten Process schreib man
ausschließlich den Takt (und evtl. Reset) rein. Denn alle anderen
Signale ändern die Ausgänge nicht.
Hab ich was vergessen? :)
argh, wenn ich euch richtig verstehe, geht es nur darum dass der integer
port state heißt und der TYPE auch STATE heißt.
Ncch eine andere frage, der name des TYPE, kann beliebig gewählt werden,
der wird doch nur für "interne" zwecke genutzt werden, den könnte ich
auch TYPE Furz nennen oder?
Polo schrieb:> den könnte ich> auch TYPE Furz nennen oder?Könntest du, ja. Aber du ja Code schreiben willst, denn man in 2
Wochen noch lesen kann, wirst du das niemals tun ;-) Eine häufig
benutzte Konvention ist z. B. an den Typ ein _t an den Signalnamen
anzuhängen. Also das signal state und den typ state_t zu nennen. Wie
auch immer du es machst, aussagekräftige und korrekte Namen verwenden!
@klaus, zu deinem letzten post, ist mir schon bewusst dass man
aussagekräftige namen wählen sollte. :D
IF NotAus ='1' Then zustandsvektor := Notschalter;
Ich hatte zu erst
IF NotAus ='1' Then := Notschalter;
meintest du das damit, man soll keine variabeln als speichernde elemente
nehmen?
Man sagte mir nämlich ich müsse eine variable einbauen, jedenfalls wird
es in den vorlesungen so praktiziert.
Bezüglich dem CLK event, dass benutze ich immer aus meiner angefertigten
Schablone , die ich ebenfalls aus den vorlesungen habe.
Auf dein rising_edge(clk) wurde ich, jedenfalls erinnere ich mich nicht
daran, nie hingewiesen.
Punkt 4, ich weiss nicht was eine Sensitivity List ist. bzw. wo kommt
die in meinen code vor?
Aber danke erstmal dass du so ausführlich drauf eingehst :-)
Polo schrieb:> Man sagte mir nämlich ich müsse eine variable einbauen, jedenfalls wird> es in den vorlesungen so praktiziert.
Ohje, hab ich befürchtet. Ist nicht dein Fehler Polo, das Problem ist:
Dein Prof ist ne Pfeife und hat absolut keine Ahnung von VHDL! :-/
Warum ist diese Unfähigkeit von Profs bei Hardwarebeschreibung
eigentlich so verbreitet? Hat jemand der alten Hasen, die länger im
Geschäft sind als ich dafür ne Erklärung?
Ok, zurück zum Thema. Anstelle der Variable solltest du ein Signal
nehmen. Das musst du dann natürlich außerhalb des Prozesses deklarieren.
Polo schrieb:> Auf dein rising_edge(clk) wurde ich, jedenfalls erinnere ich mich nicht> daran, nie hingewiesen.
Gewöhn dich dran, dass es rising_edge() heißt um eine Flanke auf einem
Takt abzufragen ;-) Das ist erstens deutlich besser lesbar, zweitens
hat es auch handfeste Gründe: Wenn nämlich (zum Beispiel nach
Simulationsstart oder warum auch immer) ein Signal den Zustand von 'U'
nach '1' ändert, ist clk = '1' and clk'event auch true! Das selbe gilt
für beliebige andere Kombinationen von Zuständen, die eigentlich keine
Flanke sind.
Polo schrieb:> Process (reset, clk, aktpos, NotAus, Betrieb, ESL, ESR) IS
Dies hier am Prozessanfang ist die Sensitivity List. In der stehen alle
Signale, die sofort den "Ausgang" des Prozesses verändern würden. Das
bedeutet:
1) Alle Signale die ungetaktet gelesen werden gehören da rein.
2) Alle Signale die getaktet (= innerhalb von if rising_edge())
gehören nicht darein. Denn erst mit dem Takt ändern sich die
Ausgangssignale.
3) Und hier kommt das Problem mit Variablen: Eine Änderung von
"zustandsvektor" würde die Ausgänge des Prozesses verändern. Es wäre
also notwendig, dass der Process auf diese Variable "sensitiv" ist.
Genau das ist aber nicht möglich. Folge: der Simulator hat keine Chance,
die Simulation richtig zu machen.
Wieder danke für deine Mühen. Ich muss mir dein text erstmal ein paar
mal durchlesen und sacken lassen, alles verstehen tu ich noch nicht. Wir
beschäftigen uns seit 4 monaten erst mit Vhdl bzw. digitaltechnik,
nächstes semester geht es dann über zu C#.
Ob mein Prof wirklich eine pflaume ist, kann ich schlecht beurteilen, er
erklärt jedenfalls sehr verständlich und die vorlagen in den scripten,
haben fast alle diese variablen eingebaut wenn es um "simple" automaten
geht. Vielleicht macht er das auch um uns den einstieg etwas zu
vereinfachen!?
Mich würde folgendes noch interessieren wie sähe denn ahnand eines
einfachen bsp. die deklaration von Signalen außerhalb des Prozess.
Meinst du meine ein- und ausgänge die im PORT (...); beschrieben werden?
Eine andere frage aus einem anderen post von dir,
1) Mixe keine kombinatorische und getaktete Logik in einem Prozess. Wenn
du beides trennen möchtest, nimm 2 Prozesse.
Wie sähe das genau aus, bzw. wo mache ich das in meinem Code.
Bitte entschuldige wenn ich nicht konkret etwas mit den zwei begriffen
kombinatorische und getaktete Logik anfangen kann :-(
Polo schrieb:> Wir> beschäftigen uns seit 4 monaten erst mit Vhdl bzw. digitaltechnik,> nächstes semester geht es dann über zu C#.
Beim gleichen Prof? Wenn ja würde es einiges erklären...
Die (ungelogen) allerwichtigste Regel bei
Hardwarebeschreibungssprachen: Verbinde sie gedanklich nie mit einer
Programmiersprache! Nenne beides nicht mal im gleichen Satz! ;-) Beides
ist einfach grundverschieden. Bei Hardwarebeschreibungssprachen geht es
einzig darum, zu beschreiben, wie einzelne Gatter und Flipflops
miteinander verschaltet werden. Eine gute Grundregel ist immer: Man
versucht sich vorzustellen, wie man ein gegebenes Problem mit Gattern
und Flipflops lösen würde. Dabei kommt es nicht drauf an, sämtliche
Logikgleichungen aufzustellen, aber die grundsätzliche Struktur sollte
klar sein. Dann erst fängst du an, das Verhalten deiner ausgedachten
Schaltung in einer HDL zu beschreiben. Wenn man sich stattdessen von der
Softwaresichtweise nähert, macht man es sich unnötig schwer. Weil man
dann nicht sieht, worum es wirklich geht (nämlich FF miteinander
verdraten!).
Also vergiss alles, was du über Programmiersprachen weißt, und stell dir
vor, du würdest mit einen riesen Sack von digitalen Bausteinen
rumhantieren.
Polo schrieb:> Vielleicht macht er das auch um uns den einstieg etwas zu> vereinfachen!?
Ich glaube das Gegenteil ist der Fall. Er macht euch den Einstieg
schwerer. Er macht nur sich den Umstieg von der Softwarewelt leichter,
indem er vermeidet, VHDL zu lernen ;-)
Polo schrieb:> Wie sähe das genau aus, bzw. wo mache ich das in meinem Code.
1
architecturexofyis
2
3
signalstate:state_t;
4
5
begin
6
7
process(clk,reset)
8
begin
9
ifreset='1'then
10
...
11
elsifrising_edge(clk)then
12
casestateis
13
...
14
-- alles hier drin ist "getaktete Logik". Weil sich der Ausgang nur ändert, wenn eine taktflanke auftritt. In einem Prozess mit getakteter Logik steht nie weitere Logik. Also nach dem end if ist schluss!
15
endif;
16
endprocess;
17
18
19
process(state)
20
begin
21
casestateis
22
...
23
-- hier drin ist nur "kombinatorische Logik". Das heiß, die Ausgänge sind zu jedem Zeitpunkt einfach bestimmt, durch die Kombination der Eingangssignale. In diesem Prozess steht kein rising_edge().
24
endprocess;
25
endarchitecturex;
Die Stichworte um sich das genauer anzugucken sind 1 Prozess
Schreibweise, bzw. 2 oder 3 Prozessschreibweise. So nennt man die
verschiedenen Stiele einen Zustandsautomaten zu beschreiben. Aber das
ist erstmal noch nicht so wichtig. Deine Beschreibung von oben kommt der
2 Prozessschreibweise am nächsten. Lassen wir das erstmal auch so. Du
schreibst dann also ein ersten case Statement in den ersten Prozess, und
das zweite in den zweiten Prozess. Der erste Prozess beschreibt also nur
die (getakteten) Veränderungen deines Zustandssignals. Und der zweite
Prozess ist dafür Zuständig auf dem aktuellen Zustand (ungetaktet) die
Ausgänge zu bestimmen. Fertig :)
Bzw. ich sollte mal auswendig lernen, welche Artikel Lothar schon
geschrieben hat. Würde mir viel arbeit ersparen, und spitzenmäßig
erklären tun die Artikel auch :D
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html
Also, um nochmal das wort zu ergreifen für meinen Prof :D
Er macht ein Semester lang Digitaltechnik, darin behandeln wir moore und
mealy, hauptaugenmerk aber auf moore-automaten. Jetzt am schluss kommt
ein bisschen der aufbau eines "von neumann rechners".
In unseren Hausarbeiten müssen wir dann ,in der regel, die aufgaben mit
VHDL "beschreiben", dafür benutzen wir quartus 2.
Im nächsten semester, beschäftigen wir uns dann mit c#, das modul nennt
sich "rechner hardwarenahe programmierung". Was genau dort gemacht wird
im detail , weiß ich noch nicht aber c# ist bestandteil.
Um vielleicht meinen prof in schutz zu nehmen, kann es natürlich gut
sein dass ich gewisse sachen anders/falsch verstanden habe und das hier
nun widergebe und du daraus das vernichtende urteil bildest :D
Ich hatte die aufgabe erstmal ein zustandsüberführungsdiagramm zu
zeichnen anhand moore. Dies habe ich gemacht. Dann bin ich übergegangen
das umzusetzen, in den vorlesungen selber hieß es, dass wir unbedingt
drauf achten sollen das ganze in zwei schritten zu gliedern. Das heisst
alle zustände und deren verhalten anhand der eingabevektoren zu
beschreiben(evtl auch die zustände ohne Bedingungen bzw.
eingabevektoren) und dann das verhalten der zustände anhand der
ausgabevektoren zu beschreiben.
Begriffe wie ein-oder Zwei-Prozess schreibweise sind bisher noch nie
gefallen, aber vielleicht wird in späteren semestern noch drauf
eingegangen.
Nein, nein, ich gebe doch kein vernichtendes Urteil über deinen Prof ab
;-) In C# oder auch anderen Programmiersprachen mag er ein Genie sein,
das weiß ich nicht. Ich weiß nur, dass er in VHDL nie eine reale größere
Aufgabe gelöst hat. Glaub mir, das ist leider ein ständig
wiederkehrendes Muster in der VHDL Welt: Softwerker kommt an und meint
mal ebend schnell ne Hardwarebeschreibung machen zu können, weil er kann
ja schließlich schon programmieren. Ist ja nur ne andere Sprache... Da
ist dein Prof leider bei weitem nicht die Ausnahme... :-/