hallo!
Kann mir jemand erklären, wo diese Fehlermeldung herkommt? Ich habe mit
meinem kleinen Shift Programm weiter rumprobiert und möchte eigentlich
nur links und rechts schieben können. Denke mein Ziel ist im code
Fragment ersichtlich.
Nun verstehe ich aber nicht, was daran stört. Dürfen interne Signale
nicht aus 2 Prozessen verändert werden?
machen? Haben schreibweisen einen direkten Einfluss auf, das was nachher
'heraus' kommt? Sprich: kann man analog zu c schnellere oder kleinere
Strukturen programmieren?
danke euch!
> Dürfen interne Signale nicht aus 2 Prozessen verändert werden?
Jedes wie auch immer geartete Signal darf nur in einem einzigen Prozess
beschrieben werden. Denke daran: In Hardware läuft immer alles parallel,
dann würden beide Prozesse ständig auf das Signal schreiben!
Die zweite Variante ist genauso unmöglichzu synthetisieren: In Hardware
gibt es keine Elemente, die auf zwei Takte reagieren können.
So wie ich das sehe, sind T und T2 doch gar keine richtigen Takte,
sondern Signale, die dein Schieberegister steuern? Dann darfst du gar
nicht mit rising_edge arbeiten.
Naja so eine 'Art' Takt. Es sind 2 entprellte Taster, die an 2
takteingänge angeschglossen sind.
Wie kann ich denn diese Taster sonst auf Druck abfragen?
Taster sind kein Takt sondern Signale. Was würde beispielsweise
passieren, wenn ein Benutzer beide Tasten innerhalb von z.B. 1 ns drückt
(bei Tastern eher unwahrscheinlich, aber das ist ja auch nur ein
Beispiel)? Deine Logik hätte die erste Flanke noch nicht vollständig
abgearbeitet, da kommt schon die zweite und deine ganze Logik wäre in
irgendeinem undefinierten Zustand.
Deswegen: Die Logik läuft immer mit einem festen Systemtakt, z.B. 50
MHz, sonst hast du ein asynchrones Design und Unmengen an Stolperfallen
(salopp gesagt, Anfänger kennen die Fallen nicht und sollten deswegen
keine asynchronen Designs benutzen, Profis kennen sie und benutzen
deswegen keine asynchronen Designs). Was ist nun eine steigende Flanke
an einem Eingangssignal, das mit einem festen Takt abgetastet wird? Ganz
einfach. Vorher war die Taste 0, jetzt ist sie 1. Also einfach den
momentanen Zustand mit dem vorhergehenden vergleichen und schon hast du
die Flanke erkannt. (Tipp: Der vorhergehende Zustand ist das um einen
Takt verzögerte Eingangssignal, also einfach ein FlipFlop)
Danke dir soweit. Leuchtet ein. Ich werde also mal einen Takt
dazubasteln und damit etwas rumexperimentieren. Müssen ja nicht 50 MHz
sein ich hoffe ein NE555 tuts auch.
Verstehe ich es richtig, daß dann auch 2 interne Signale T1, T2, die in
einem process(clk) je nach Tasterstellung gesetzt werden auch nicht für
einen process zum shiften herangezogen werden dürfen?
Wären ja auch 2 Signale die den Ausgangsvektor verändern können.
DAS leuchtet mir noch nicht ganz ein.
Ich würde mir ganz kleine Prozesse wünschen; so wie ich es jetzt
verstehe würde das dann ein recht großer clk-Prozess.
Ein 555 als Taktquelle könnte etwas problematisch sein, die meisten
Varianten haben weder einen genügend kleinen Jitter noch genügend steile
Flanken. Auf jedem gekauften Board wirst du aber einen passenden
Oszillator finden.
Das shiften machst du in einem getakteten Prozess, so ändert sich der
Ausgangsvektor immer nur mit einer Taktflanke:
if rising_edge(CLK) then
if T1_down = '1' then
shift_left
elsif T2_down = '1' then
shift_right
end if;
end if;
Dann musst du noch T1_down und T2_down definieren, z.B. in einem eigenen
getakteten Prozess mit
...
if last_T1 = 0 and T1 = 1 then
T1_down <= '1';
else
T1_down <= '0';
...
Achtung: Signale, die von außen in den FPGA kommen müssen zuerst noch
einsynchronisiert werden, damit sie passend zu den internen Taktflanken
kommen. Das macht man in der Regel mit zwei Flipflops durch die das
Signal hindurch muss.
Die nötigen Infos sollte dir aber auch jedes FPGA-Buch und teilweise
auch die Artikel hier im wiki liefern können.
> Ich würde mir ganz kleine Prozesse wünschen;
Wünschen war letzte Woche. Weihnachten ist vorüber ;-)
Du kannst mit FPGAs "nur" Logik und FFs verbauen. Ein FF hat genau 1
(einen) Takteingang und der kann nur in 1 (einer) Richtung sensitiv
sein.
Am einfachsten und sichersten machst du (vorerst) nur Designs mit
genau 1 (einem) Master-Takt und maximal 1 (einem) Reset.
1
process(clk50M)
2
begin
3
ifrising_edge(clk50M)then
4
if(T1='1'andt1_old='0')then-- steigende Flanke T1
5
D_int<=D_int(6downto0)&D_int(7);
6
endif;
7
if(T2='1'andt2_old='0')then-- steigende Flanke T2
8
D_int<=D_int(0)&D_int(7downto1);
9
endif;
10
t1_old<=T1;
11
t2_old<=T2;
12
endif;
13
endprocess;
> so wie ich es jetzt verstehe würde das dann ein recht großer clk-Prozess.
Nicht unbedingt.
Aber: jede Signalzuweisung (hier an D_int) darf nur in 1 dieser
getakteten Prozesse vorkommen. Sobald du von einem anderen Prozess aus
auch an D_int zuweisen willst, wird es diese Multi-Source-Geschichte
wieder geben.
Du solltest auch diese Flanken-Denkweise aufgeben. Besser ist es, eine
Enable-Denkweise einzunehmen. Dann wird, wenn etwas getan werden soll,
genau für 1 (Master-)Takt die entsprechende Funktion enabled.
Danke danke ich glaube das könnte in ein aha - Erlebnis münden.
Ich las im wiki und diversen posts immer wieder vom 'einsynchronisieren'
und daß Eingangssignale durch mind. 1 (2 manchmal) FFs sollen bevor sie
verwendet werden.
Da frage ich mich schon lange: wie zwinge ich sie dazu? Ist das eine
simple Notation? Wie sorge ich explizit dafür, daß ein Signal durch ein
FF 'geht'.
Lothars Post und eure allgemeinen Tips muss ich aber erst mal ein paar
Tage sacken lassen und verarbeiten. Die Einsynchronisierungsgeschichte
brennt mir aber schon seit einiger Zeit auf der Zunge so daß ich danach
noch fragen wollte.
P.S: Also ich persönlich kann mich über das Forum nicht beschweren -
kann weder über arrogante noch überflüssige Antworten klagen. Danke euch
dafür.
>Wie sorge ich explizit dafür, daß ein Signal durch ein FF 'geht'.
Indem du es in vhdl beschreibst. Was ist ein FF? Etwas, das das
Eingangssignal nur bei jeder Taktflanke an den Ausgang übernimmt, also
ganz simpel:
if rising_edge(CLK) then
d_out <= d_in;
end if;
Das gibt dann natürlich relativ schnell ein Chaos mit verschiedenen
Signalnamen, mit festen Pre- oder Postfixen lässt sich das aber schnell
regeln: signal_in wird zu sync1_signal, sync2_signal und schließlich
reg_signal - oder man schreibt sich gleich eine eigene Entity, die man
dann immer zu einsychronisieren benutzt.
> Die Einsynchronisierungsgeschichte brennt mir aber schon seit> einiger Zeit auf der Zunge so daß ich danach noch fragen wollte.
Da war noch die Geschichte mit den Atmel Controllern: in bestimmten
Stufen war bei den Classic-AVRs ein FF zu wenig. So konnte es sein, dass
ab und an ein Interrupt flöten ging oder die Capture-Zähler nicht alle
Impulse erwischten.
Mit einem Shrink wurden die Fehler behoben und jedes Signal von aussen
mit 2 FFs auf den internen Takt einsynchronisiert.
Zwischen jeder Taktdomäne müssen 2 FFs sitzen (z.B. Aussen - Innen; aber
auch Innen_Takt1 - Innen_Takt2 --> deshalb am besten nur 1 Takt im
FPGA). Die FFs beschreibst du am einfachsten als Schieberegister. Dann
kannst du auch ganz einfach eine Flankenerkennung reinprogrammieren.
Es ist nicht so schlimm wie es aussieht, denn es betrifft nicht alle
externen Signale, sondern nur die, deren Pegelwechsel eine Information
enthält.
So ist z.B. der Pegelwechsel bei Adress- oder Datenleitungen
uninteressant.
Wichtig ist aber, die Zustandsänderung z.B. von WRITE# oder READ#
zuverlässig ins FPGA zu bekommen.
Hier eine kampferprobte Art, ein externes Signal einzutakten und auf
Flanken zu reagieren:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entitydebounceis
6
Port(clk:inSTD_LOGIC;-- der FPGA-Takt
7
input:inSTD_LOGIC;
8
output:outSTD_LOGIC;
9
risedge:outSTD_LOGIC;
10
falledge:outSTD_LOGIC);
11
enddebounce;
12
13
architectureBehavioralofdebounceis
14
signalinputsr:std_logic_vector(3downto0);
15
processbegin
16
waituntilrising_edge(clk);
17
-- Pegel zuweisen
18
if(inputsr="0000")thenoutput<='0';endif;
19
if(inputsr="1110")thenoutput<='1';endif;
20
-- steigende Flanke --> Enable für 1 Taktzyklus gueltig
21
riseedge<='0';
22
if(inputsr="0111")thenriseedge<='1';endif;
23
-- fallende Flanke --> Enable für 1 Taktzyklus gueltig
Noch einmal nachgefragt: betrifft dies 'eintakten' auch den Takt selber
oder wird der von außen angelegt und wie er ist als interner Takt
herangezogen? Habe jetzt erst mal mit einem nackten Takt und
'eingetakteten' Tastenstellungen experimentiert. Wäre das so in Ordnung?
Desweiteren: wenn Signale wie read/write durch 2 FFs laufen geht das bis
zu einer Taktfrequenz, die viel kleiner als die Gatterlaufzeiten sind,
also bei einem 9572 so etwas wie maximal 100 MHz?
Gute Nacht wünsche ich
> Noch einmal nachgefragt: betrifft dies 'eintakten' auch den Takt selber
Nein, denn der (Master-)Takt ist an einen der Taktpins angeschlossen und
wird im FPGA über das Taktnetz (oder eines der Taktnetze) an alle FFs
verteilt.
> Desweiteren: wenn Signale wie read/write durch 2 FFs laufen geht das bis> zu einer Taktfrequenz, die viel kleiner als die Gatterlaufzeiten sind,> also bei einem 9572 so etwas wie maximal 100 MHz?
Autsch, das 9572 ist neu hier.
Bei CPLDs ist man (wegen der arg knappen FFs) bezüglich der Takte immer
mal wieder zu Kompromissen gezwungen. Aber bei einem CPLD lasse auch ich
mich gerne auf "Tricksereien" ein, denn bei gerade mal 72 FFs kann man
die entstehenden Probleme (noch) an einer Hand abzählen.
Meine Eintakterei bezieht sich (vorrangig) auf FPGAs, denn dort hat man
FFs im Überfluss, die bekommt man gar nie alle verdrahtet.