Forum: FPGA, VHDL & Co. this signal is connected to multiple drivers.


von Hartmut K. (Gast)


Lesenswert?

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?
1
architecture Behavioral of test1_code is
2
3
signal D_int : STD_LOGIC_VECTOR (7 downto 0):="00000001";
4
begin
5
  shiften_rechts: process(T2)
6
  begin
7
    if rising_edge(T2) then
8
      D_int <= ( D_int(0) & D_int(7 downto 1));    
9
    end if;
10
  end process shiften_rechts;
11
  
12
  shiften_links: process(T)
13
  begin
14
    if rising_edge(T) then
15
      D_int <= (D_int(6 downto 0) & D_int(7));    
16
    end if;
17
  end process shiften_links;
18
  
19
  D<=D_int;
20
21
end Behavioral;

Oder würde man generell besser nur einen
1
 process(T,T2)
2
begin
3
if rising_edge(T) then
4
      D_int <= (D_int(6 downto 0) & D_int(7));  
5
elsif rising_edge(T2) then
6
      D_int <= ( D_int(0) & D_int(7 downto 1));    
7
end if
8
end
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!

von Jan M. (mueschel)


Lesenswert?

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

von Hartmut K. (Gast)


Lesenswert?

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?

von Jan M. (mueschel)


Lesenswert?

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)

von Hartmut K. (Gast)


Lesenswert?

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.

von Jan M. (mueschel)


Lesenswert?

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.

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


Lesenswert?

> 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
   if rising_edge(clk50M) then
4
      if (T1='1' and t1_old='0') then -- steigende Flanke T1
5
         D_int <= D_int(6 downto 0) & D_int(7);  
6
      end if;
7
      if (T2='1' and t2_old='0') then -- steigende Flanke T2
8
         D_int <= D_int(0) & D_int(7 downto 1);    
9
      end if;
10
      t1_old <= T1;
11
      t2_old <= T2;
12
   end if;
13
end process;

> 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.
1
process(clk50M)
2
begin
3
   if rising_edge(clk50M) then
4
      if (T1='1') then -- Enable T1
5
         D_int <= D_int(6 downto 0) & D_int(7);  
6
      end if;
7
      if (T2='1') then -- Enable T2
8
         D_int <= D_int(0) & D_int(7 downto 1);    
9
      end if;
10
   end if;
11
end process;

von Hartmut K. (Gast)


Lesenswert?

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.

von Jan M. (mueschel)


Lesenswert?

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

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


Lesenswert?

> 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
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity debounce is
6
    Port ( clk      : in   STD_LOGIC; -- der FPGA-Takt
7
           input    : in   STD_LOGIC;
8
           output   : out  STD_LOGIC;
9
           risedge  : out  STD_LOGIC;
10
           falledge : out  STD_LOGIC);
11
end debounce;
12
13
architecture Behavioral of debounce is
14
signal inputsr   : std_logic_vector(3 downto 0);
15
   process begin
16
      wait until rising_edge(clk);
17
      -- Pegel zuweisen 
18
      if (inputsr = "0000") then output<='0'; end if;
19
      if (inputsr = "1110") then output<='1'; end if;
20
      -- steigende Flanke --> Enable für 1 Taktzyklus gueltig
21
      riseedge <= '0';
22
      if (inputsr = "0111") then riseedge<='1'; end if;
23
      -- fallende Flanke --> Enable für 1 Taktzyklus gueltig
24
      falledge <= '0';
25
      if (inputsr = "1000") then falledge<='1'; end if;
26
      -- von rechts Eintakten
27
      inputsr <= inputsr(2 downto 0) & input;
28
   end process;
29
end Behavioral;


BTW:
Weil ich das auch nicht immer neu schreiben will, habe ich
das Zeug auf meiner HP abgelegt, siehe 
http://www.lothar-miller.de/s9y/categories/5-Entprellung

von Hartmut K. (Gast)


Lesenswert?

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

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


Lesenswert?

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

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.