Forum: FPGA, VHDL & Co. Ursache für Latches und wie vermeiden?


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Dominic K. (domi1997)


Lesenswert?

Hallo zusammen
 Ich schreibe seit circa einem Semester an der Universität VHDL, doch 
werde ich das gefühl nicht los, dass ich teils eher schlecht als recht 
latches verhindere. Bisher habe ich die Werte, welche geändert werden in 
eine next_"variablenname" zischengespeichert und erst beim clock die 
daten gespeichert daher konnte ich dies relativ gut umgehen.

Leider hat dies bei folgendem Code nicht geklappt und alle signale und 
variablen erzeugen latches,daher die frage wie löse ich die Latches für 
folgende variablen und signale:
1
signal time_stamp : integer:=0;
2
signal next_time_stamp : integer:=0;
3
-- Begin Architecture
4
-------------------------------------------
5
begin
6
7
 timer : process (all)
8
   variable prescaler_counter: integer:=0;
9
  variable next_prescaler_counter: integer:=0;
10
   variable speed: integer := 168;
11
  
12
 begin 
13
  if(sw = '1') then
14
    next_prescaler_counter := prescaler_counter + 1;
15
    next_time_stamp        <= time_stamp +1;
16
    
17
    if(rising_edge(step_i)) and (prescaler_counter<speed) then
18
      prescaler_counter := next_prescaler_counter;
19
      note_flag <= '0';
20
    elsif(prescaler_counter = speed) then
21
      prescaler_counter := 0;
22
      note_flag <= '1';
23
      time_stamp <= next_time_stamp;
24
    end if;
25
  else
26
    prescaler_counter := 0;
27
    time_stamp<= 0;
28
    note_flag <= '0';
29
  end if;
30
 end process timer;
Funktionsbeschreib: Step ist ein clock der heruntergeteilt werden muss. 
Pro clock wird der prescaler um 1 erhöht bis halt der teilerwert 168 
erreicht wird und dann wird bis zum nächsten puls das flag Note_flag 
gesetzt und der timestamp um 1 erhöht um einen zähler zu haben mit 
enstsprechendem takt.

Danke im voraus für eure Antworten

von Dussel (Gast)


Lesenswert?

Da ich eigentlich beschäftigt bin, nur eine kurze Antwort: Du solltest 
rein kombinatorische und taktabhängige Signale nicht in einem Prozess 
haben.
(Mindestens) einen Prozess für kombinatorische Signale und (mindestens) 
einen rein taktabhängigen Prozess (von einem asynchronen Reset eventuell 
abgesehen). Dann wird es übersichtlicher.

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


Lesenswert?

Dominic K. schrieb:
> Ich schreibe seit circa einem Semester an der Universität VHDL, doch
> werde ich das gefühl nicht los, dass ich teils eher schlecht als recht
> latches verhindere.
Lass mich raten: du hast vorher C (oder sonst eine prozedurale 
Programmiersprache) programmiert und verwendest das dabei Gelernte jetzt 
für VHDL?

Das geht schief, denn du wendest dabei die völlig falsche Denkweise an.


Dominic K. schrieb:
1
 begin
2
   if(sw = '1') then
3
   :
4
     if(rising_edge(step_i)) and (prescaler_counter<speed) then
5
     :
6
     elsif(prescaler_counter = speed) then
7
     :
8
    end if;
9
  else
10
  :
11
  end if;
12
 end process timer;
Mich wundert, dass der das überhaupt zu irgendwas synthetisiert. Wo hast 
du diesen "gegatet-kombinatorisch-getakteten" Beschreibungsstil 
gefunden?


Dominic K. schrieb:
> Funktionsbeschreib: ....
Wie würdest du das in Hardware mit Zählern, vergleichern und Registern 
machen? Kannst du dafür eine Schaltplanskizze aufmalen?

> Step ist ein clock der heruntergeteilt werden muss.
Dieser Step wird aber niemals im FPGA als Taktquelle verwendet!

Takte sind in einem FPGA etwas ganz besonderes, denn sie werden auf dem 
Taktnetz an die angschlossenen Flipflops verteilt.

In einem Anfängerdesign (und in einem einfah zu wartenden 
Forgeschrittenendesign) gibt es nur 1 Takt, der kommt vom 
Quarzoszillator und der hat so ca. 50..100MHz.

Also ist dieser Step lediglich ein ganz normales Signal, das im FPGA 
erzeugt und auf dessen Änderung im FPGA reagiert wird.

Ein Tipp: diese mit (all) abgekürzte Sensitivliste ist was, das Anfänger 
nicht verwenden sollten. Denn es verleitet dazu, sich keine Gedanken zum 
Design zu machen. Schreibe in die Sensitivliste mal nur die Signale, von 
denen du meinst, dass sie dort drin nötig sind. Oft gibt das dann den 
Impuls bei der Fehlersuche...

BTW: löse die Aufgabe ohne Variablen. Du brauchst sie hier sicher nicht. 
Denn Variablen sind für dich "false friends", weil du den Namen von C 
her kennst und meinst, in VHDL würden die das selbe machen.

Siehe den Beitrag "VHDL variable vs signal" und den darin 
enthaltenen Link auf Beitrag "Variable vs Signal"

: Bearbeitet durch Moderator
von Dominic K. (domi1997)


Angehängte Dateien:

Lesenswert?

Ich habe bisher in der tat Java, assembler und C programmiert :D aber 
versuche mich dazu zu zwingen meine denkweise umzuschalten auch wenn ich 
parallel zur Hardware description language auch programmiersprachen 
schreibe.

Mein grund für die Variablen war die Hoffnung die Schaltung weniger 
komplex zu machen weil diese ja nur lokal im Prozess sind und nicht wie 
ein signal übergreifend. Ich brauche lediglich das note_flag um zu 
wiesen, ob ein überlauf da ist und denn stamp um einen zähler zu haben, 
welcher zählt wie viele zyklen durch sind.

anliegend eine skizze wie ich das ganze als logik aufbauen würde aber 
halt sehr vereinfacht und hilft mir zumindest nicht um latches los zu 
werden.

von Dominic K. (domi1997)


Lesenswert?

ein besseres Beispiel wäre wohl folgendes Beispiel wo die 
Note_on,note,velocity und velocity_cache als latches gemacht werden. Der 
einzige case welchen ich nicht abdecke ist wenn sw 1 ist aber timestamp 
nicht gleich time_cache aber dort darf ich denn wert halt nicht ändern. 
Wie würdet ihr das lösen?
1
  player : process (all)
2
  variable time_step : integer := 0;
3
  begin
4
    if(sw = '1') then
5
      time_cache <= river(time_step,0);
6
      noteon_cache <= river(time_step,1);
7
      note_cache <= river(time_step,2);
8
      velocity_cache <= river(time_step,3);
9
      
10
      if(time_stamp = time_cache) then
11
        note_on <="100" & std_logic_vector(to_unsigned(noteon_cache,1));
12
        note <=  std_logic_vector(to_unsigned(note_cache,note'length));
13
        velocity<= std_logic_vector(to_unsigned(velocity_cache,velocity'length));
14
        time_step := time_step + 1;
15
      end if;
16
    else
17
      time_cache <= 0;
18
      noteon_cache <= 0;
19
      note_cache <= 0;
20
      velocity_cache <= 0;
21
      
22
      note_on <= "0000";
23
      note <= "0000000";
24
      velocity <= "0000000";
25
      time_step := 0;
26
    end if;
27
  end process player;

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


Lesenswert?

Dominic K. schrieb:
> anliegend eine skizze wie ich das ganze als logik aufbauen würde
Ja, aber wie gesagt: step_in ist kein Takt. Du musst was Anderes 
ausdenken, dein einziger Takt im ganzen Design Takt ist der 
Quarzoszillator am Takteingang des FPGAs.

Dominic K. schrieb:
> ein besseres Beispiel wäre wohl folgendes Beispiel wo die
> Note_on,note,velocity und velocity_cache als latches gemacht werden.
Ja, klar, wenn ein nicht getakteter, kombinatorischer Prozess etwas 
speichern muss, dann kann der Synthesizer dafür nur Latches nehmen. Und 
Latches sind nicht gefährlich, weil sie Latches sind, sondern weil sie 
auf jeden Glitch reagieren, wenn einer der beiden Signale hier seinen 
Wert ändert:
> if(time_stamp = time_cache) then
Denn wenn time_stamp bisher binär 01111111 war und dann auf 1000000 
hochzählt, dann können da für ein paar ps alle möglichen 
Bitkombinationen (11001001, 01010101, 10011001, 10101100 oder sonstwas) 
auftreten. Und der Vergleicher glitcht dann von sich aus auch noch und 
zackdiebohne hast du da ungewollt Werte abgespeichert. Ja, es kann sogar 
sein, dass je nach Dauer des Latchglitches wegen Laufzeiten und je nach 
Energiegehalt dann nur einzelne Bits von note_on, note und velocity mit 
"neuen" Werten gespeichert werden.

Also: wenn schon ein Latch, dann nur dort, wo du sicher sein kannst, 
dass das Ansteuersignal niemals glitcht und ausreichend lange anliegt.


Das allein wäre schon schlimm genug, aber das hier ist natürlich der
Schenkelklopfer, der dir im echten Leben blitzartig das Genick bricht:
>    time_step := time_step + 1;
Mein Glückwunsch!
Du hast die kombinatorsche Schleife entdeckt:
http://www.lothar-miller.de/s9y/archives/42-Kombinatorische-Schleifen.html
Weil dieses ungetaktete Hochzählen in einer if-Abfrage versteckt ist, 
sieht der Synthesizer das nicht und meldet nur ein Latch.


BTW: nimms mir nicht krumm, aber du bist das Paradebeispiel, warum ich 
meinen Praktikanten immmer einbläue, dass sie nicht programmieren, 
sondern Hardware beschreiben und es deshalb nicht VH-P-L, sondern 
VH-D-L heißt.

Siehe hier im Forum die jeweils ewig langen Diskussionen, ob VHDL nun 
formell eine Programmiersprache sei oder auch nicht.
Das Fazit dabei: wahrscheinlich ist es eine Programmiersprache, weil 
alle Kriterien für ein Programmiersprache erfüllt sind.

Allerdings ist "VHDL fürs FPGA" eben nicht "VHDL im Gesamten". Das sieht 
eher so aus wie dort skizziert:
Beitrag "Re: vhdl synthetisiarbar machen"

Und dann muss man natürlich wissen, welchen Teil des "gesamten und 
simulierbaren VHDL" man tatsächlich als "synthetisierbares VHDL" 
verwenden kann und wie man das hinschreiben muss, dass der Synthesizer 
kapiert, was man will. Wie das aussehen muss, steht übrigens im 
Handbuch/User-Guide zum Synthesizer.

Nur mal zum Abgleich des Kenntnistandes: hast du die üblichen 
Trainingseinhaiten mit Blinklicht und Lauflicht selber erfolgreich in 
Simulation und Synthese erledigt? Hast du selbst eine simple serielle 
Schnittstelle (Midi ist das ja auch) durchdacht und realisiert? Ist dir 
das Prinzip der Taktung von FPGAs und das Steuern von Submodulen per 
Clock-Enables usw. bekannt?

http://www.lothar-miller.de/s9y/archives/80-Hello-World!.html

http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

http://www.lothar-miller.de/s9y/categories/42-RS232

Mein Tipp: schreibe alles, was getaktet ist, in einen Prozess. Und alles 
nebenläufig (concurrent), was Kombinatorik ist. Dann steht in jedem 
Prozess nur der clk im der Sensitivliste, oder besser noch: du hast gar 
keine Sensitivliste und verwendest stattdessen ein wait until 
rising_edge(clk); im Prozess:
http://www.lothar-miller.de/s9y/archives/16-Takt-im-Prozess.html
Aber wie gesagt: es lohnt sich, das Manual zum Synthesizer anzusehen.

Dominic K. schrieb:
> Wie würdet ihr das lösen?
Bei mir würde der Prozess etwa so beginnen:
1
  player : process
2
  variable time_step : integer := 0;
3
  begin
4
    wait until rising_egde(clk50MHz);
5
    if(sw = '1') then
6
    :
7
    :
Oder ein wenig traditioneller eben so:
1
  player : process (clk50MHz)
2
  variable time_step : integer := 0;
3
  begin
4
    if rising_egde(clk50MHz) then
5
      if(sw = '1') then
6
      :
7
      :
Damit hätte ich schon mal hundertprozentig sicher ein synchrones Design 
ohne Latches.

Natürlich kommen dann andere Effekte wie z.B. Latency auf, aber die 
musst du sowieso beachten und abschätzen, ob sie an der jeweiligen 
Stelle weh tun.

: Bearbeitet durch Moderator
von Dominic K. (domi1997)


Lesenswert?

Danke für die Inputs werde mir diese heute abend genauer anschauen. Ich 
nehme dir das keines falls übel. Mir ist sehr wohl bewusst, dass ich von 
programmiersprachen vorgeorägt bin und mein eigentliches Problem der 
übergang zur Hardware description language ist. Daher ist die 
Fragenstellung auch so offen, da mir bewusst ist das sehr viel noch am 
basteln bin

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.