www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Problem: Latches oder unkorrektes Verhalten


Autor: Screamapilla (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich habe ein Problem beim Designen einer ALU. Und zwar gebe ich den 
Signalen, die im Anhang rot schattiert sind, einen Anfangswert um 
Latches zu vermeiden. Das Problem ist jedoch, dass den Signalen immer 
wieder diese Anfangswerte gegeben werden, wenn man den process ausführt 
was zu einem Fehlverhalten der ALU führt (siehe nächsten Anhang).

Autor: Screamapilla (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier z.B. versuche ich einen Wert in das Register A und dann einen Wert 
in das Register B zu laden, um diese dann zu addieren, jedoch springt 
der Inhalt der Register beim nächsten "clock event" wieder auf den 
Anfangswert X"00" zurück.

Ich wäre Dankbar für jede Hilfe bzw. Hinweis. Zumal ich denke, dass es 
sich um ein grundsätzliches Fehldenken bei mir handelt.

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Synchronen Prozess draus machen. Register = Flipflop

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genauer gesagt, mit diesem Code hast du da nur ganz normale 
kombinatorische Signale, keine Register. Register entstehen nur in einem 
getakteten Prozess. Siehe VHDL -> Grundregeln für synthetisierbaren 
VHDL-Code.

Autor: Screamapilla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, das ist mir klar. Es ist schon registriert was registriert sein 
muss, sprich A, B, usw. und der Kern der ALU, die ALU-core ist 
kombinatorik. Aber trotzdem funzt es nicht...

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn dir schon klar ist, daß A und B Register sein müssen, warum setzt 
du es dann nicht so um?

Autor: Screamapilla (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Weiter unten im Code habe ich ein clk getriggerten process wo ich die 
Signale registriere. Im Anhang habe ich eine vereinfachte Version der 
ALU. Ich habe den Code auch etwas umgeschrieben um ihn leserlicher zu 
machen aber so funktioniert das immer noch nicht.
Danke für eure Hilfe!

Autor: Screamapilla (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist ein Diagram von dem, was ich implementieren will.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Screamapilla (Gast)

>Dateianhang: Diagram.jpg (55,7 KB, 11 Downloads)

Bildformate

>Dateianhang: Code.jpg (64 KB, 38 Downloads)

Und Code wird als TEXT im Anhang gepostet.

>Hier ist ein Diagram von dem, was ich implementieren will.

Poste VOLLSTÄNDIGEN VHDL Code deine ALU als Anhang.

MFG
Falk

Autor: Andreas F. (chefdesigner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso brauchen kombinatorische Signale einen Anfangswert ?
Das, was Du als Prozess druchlaufen bezeichnest, ist ein Vorgang der nur 
einmal bei der Synthese läuft. Real hast Du nur eine einzige 
Möglichkeit, ein Signal zu belegen, je nach den Eingangswerten.

Da gibt es nichts mit "Latches vermeiden". Im Gegenteil: Hier wirst Du 
Latches benötigen, da die Ausgänge deiner "ALU" ja irgendwann stabil 
gemacht werden müssen, für die nächste Stufe.

Jetzt habe ich den Code eingesehen: Mach mal sofort die nicht
benötigten Signale aus der s-Liste, die unten nicht benötigt werden,
sonst triggert jede Änderung den "pocess" an und Du hast simulatorisch
deine Dualen zustände.

Ich glaube kaum, daß Du das bauen willst.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uups, hab den angehängten Code übersehen.

In einer ALU haben inout Signale NICHTS zu suchen. Inout wurd 
AUSSCHLIESSLICH im Toplevel verwendet, wenn Signale an Pins gehen und 
dort eben bidirektionale Signale benötigt werden. INNERHALB eines FPGAs 
wird NUR mit UNIDIREKTIONAEN Signalen gearbeitet.

Ausserdem ist dein Prozess MURKS. Trenne mal sauber ALU und das 
Datenverwaltungszeug.

MFG
Falk

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Fischer wrote:
> Wieso brauchen kombinatorische Signale einen Anfangswert ?

Beispiel:
process(a)
begin
  -- b <= '0';

  if a = '1' then
    b <= '1';
  end if;
end process;

Was passiert mit b wenn a nicht gleich '1' ist? Der vorherige Zustand 
muss beibehalten werden, mit einem Latch. Um das zu verhindern braucht 
man entweder einen else-Zweig in dem b einen Wert zugewiesen bekommt, 
oder man stellt eine Standardzuweisung an den Anfang des Prozesses. Für 
den Prozess ist das der Anfangswert des Signals.

> Jetzt habe ich den Code eingesehen: Mach mal sofort die nicht
> benötigten Signale aus der s-Liste, die unten nicht benötigt werden,
> sonst triggert jede Änderung den "pocess" an und Du hast simulatorisch
> deine Dualen zustände.

Zusätzliche Signale in der Sensitivity List sollten das Ergebnis der 
Simulation nicht ändern.

Autor: Screamapilla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In einer ALU haben inout Signale NICHTS zu suchen. Inout wurd
> AUSSCHLIESSLICH im Toplevel verwendet, wenn Signale an Pins gehen und
> dort eben bidirektionale Signale benötigt werden. INNERHALB eines FPGAs
> wird NUR mit UNIDIREKTIONAEN Signalen gearbeitet.

Versteh dich nicht ganz. Databus ist halt nun mal inout, kann ich nichts 
dafür.

> Ausserdem ist dein Prozess MURKS. Trenne mal sauber ALU und das
> Datenverwaltungszeug.

Ehm, ja, danke für deine Hilfe.

Autor: Screamapilla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Da gibt es nichts mit "Latches vermeiden". Im Gegenteil: Hier wirst Du
> Latches benötigen, da die Ausgänge deiner "ALU" ja irgendwann stabil
> gemacht werden müssen, für die nächste Stufe.

Der Ausgang der Alu-core, der Kombinatorik ist so lange stabil wie es 
die Eingänge (Rgister A und B) sind. Wieso sollte ich da noch Latches 
wollen?

> Jetzt habe ich den Code eingesehen: Mach mal sofort die nicht
> benötigten Signale aus der s-Liste, die unten nicht benötigt werden,
> sonst triggert jede Änderung den "pocess" an und Du hast simulatorisch
> deine Dualen zustände.

Wie schon jemand hier gesagt hat, ist das nicht relevant, und zudem 
bekomme ich sonst warnings.

> Ich glaube kaum, daß Du das bauen willst.

Du glaubst falsch.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Screamapilla (Gast)

>Versteh dich nicht ganz. Databus ist halt nun mal inout, kann ich nichts
>dafür.

Nicht? Wer entwickelt denn die CPU? Ausserdem ist das schlicht falsch. 
In deinem Bild hat die ALU als Eingang A und B und Ausgang ACC und die 
Flags. Thats it. Ein einfacher Dekoder, ein CASE Konstrukt, sonst nix.

MFG
Falk

Autor: Screamapilla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In deinem Bild hat die ALU als Eingang A und B und Ausgang ACC und die
> Flags. Thats it. Ein einfacher Dekoder, ein CASE Konstrukt, sonst nix.

Ich muss die ganze ALU machen, nicht nur die core. Und eine ALU ist 
erstens etwas mehr als ein Dekoder und zweitens wenn es so leicht für 
Dich wäre, hättest Du ja bestimmt schon das Problem entdeckt.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Screamapilla (Gast)

>Ich muss die ganze ALU machen, nicht nur die core. Und eine ALU ist
>erstens etwas mehr als ein Dekoder und zweitens wenn es so leicht für
>Dich wäre, hättest Du ja bestimmt schon das Problem entdeckt.

Hab ich auch. Aber dir gefällt das Problem ja nicht.

DEINE BESCHREIBUNG IST MURKS!

MFG
Falk

Autor: Screamapilla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch einmal: Databus ist inout, d.h. ich lese ihn und ich schreibe auf 
ihn, beides in der ALU.

In meiner Beschreibung gehe ich so ziemlich nach Lehrbuch: Bibliotheken, 
component, Signale, Prozess für Kombinatorik, Anfangswerte, ein sauberes 
case-when und ein synchroner Prozess (clk) in welchem die Register 
upgedatet werden mit asynchronem Reset.
Wenn das murks für dich wäre könntest Du auch sagen wo.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Screamapilla (Gast)

>Noch einmal: Databus ist inout, d.h. ich lese ihn und ich schreibe auf
>ihn, beides in der ALU.

Stimmt nciht mit deinem Bild überein. Halte dich an das Bild, 
struktureire dein prozesse bzw. Entitys genau so und du wirst wenig 
Probleme haben.

>In meiner Beschreibung gehe ich so ziemlich nach Lehrbuch: Bibliotheken,

Ohhhh, dafür gibts gleich mal ein Bienchen. Hast du fein gemacht.

Der Unterschied zwischen Tehorie und Praxis ist in der Praxis grösser 
als in der Theorie.

>component, Signale, Prozess für Kombinatorik, Anfangswerte, ein sauberes
>case-when und ein synchroner Prozess (clk) in welchem die Register
>upgedatet werden mit asynchronem Reset.
>Wenn das murks für dich wäre könntest Du auch sagen wo.

Rede ich russisch? Ja ne gawarju pa russki.

Die ALU sieht sinnvollerweise so aus
  ALU_OP : process (A_reg, B_reg, u_instruction)
  begin

    CASE u_instruction is

      when op_lda =>
        alu_out <= A_reg;
      
      when op_ldb =>
        alu_out <= A_reg;

      when op_add =>
        ALU_out <= (A_reg + B_reg);
--------------------------------------------------------------------------

-- Noch mehr uinstrutions

--------------------------------------------------------------------------  
      
        
      when others => ALU_Out <= (others => '0'); 

    end CASE;

  end process ALU_OP;

Die Flags kommen da nicht rein. Z und C kann man einfach so dekodieren
Z <=0 when alu_out =0 else '1';
C <= alu_out(8);

MFG
Falk

Autor: Screamapilla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da du Russe bist sag ich es Dir nochmal damit Du's verstehst (lese sich 
mit drutski akkzent): Ich dtue dschrrreiben auf dem Databüs und ich dem 
dtue auch lehsen. Dsogar derrr Bild zeigt dem so an, indem er Databüs 
mit Pfeil in dem beide Rrrrichtungen malt. Also meiner Salami in dirrr 
Gesicht.

Na ja, danke für Deine Zeit aber mit Hooligans komme ich nicht aus.

Autor: Andreas F. (chefdesigner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Schwarz wrote:
> Andreas Fischer wrote:
>> Wieso brauchen kombinatorische Signale einen Anfangswert ?
>
> Beispiel:
>
> process(a)
> begin
>   -- b <= '0';
> 
>   if a = '1' then
>     b <= '1';
>   end if;
> end process;
> 
>
> Was passiert mit b wenn a nicht gleich '1' ist? Der vorherige Zustand
> muss beibehalten werden, mit einem Latch.

Bei einer Kombinatorik hast Du doch keine Latches! Du beschreibst eine 
offene, nicht belegte Möglichkeit des Ergebnismultiplexers, die jeweils 
so belegt wird, wie die Variable im Syntheselauf steht. Was dort oben 
steht ist eine unvollständige und daher in den meisten falsch 
synthetisierte Syntax.  Daher muss man :

> man entweder einen else-Zweig in dem b einen Wert zugewiesen bekommt,
> oder man stellt eine Standardzuweisung an den Anfang des Prozesses.

Exakt, denn damit ist das System statisch eindeutig beschrieben. Es ist 
also egal, aus welcher Richtung man die Vorschrift betrachtet, der 
Ergebnismuxer ist komplett und eindeutig beschrieben. Den logischen 
Signalablauf im Zeitverhalten, der sich durch die Interpreation als flow 
ergibt, isi einzig für die Simulation wichtig. Man sollte immer darauf 
achten, daß das nicht auseinanderläuft!

Daher ist die Vorstellung, in den Ablauf, den die Hardware später 
vollziehen soll, einen Datenfluss mit Anfangswerten und sich zeitlich 
ändernden Signalen hinein zu interpretrieren, gefährlich! Alle Signale 
in einem synchronen Design sind ausnahmslos als statisch anzusehen und 
nur zum Taktzeitpunkt undefiniert. Alle Zustände der Schaltung, die auf 
Übergänge wirken, sind ebenfalls als statische Vorgaben zu sehen. Da 
gibt es keine weitere "historie", wie es die Simulation kann und tut. 
Daher ist die Methode:

> Für en Prozess ist das der Anfangswert des Signals.

Problematisch. Aus Simulationssicht ist das in der Tat ein Anfangswert, 
aus Synthesesicht ist das aber eine statische Alternative, um die 
nichtbelegten Pfade zu definieren. Den Begriff "Anfangswert" sollte mn 
nicht verwenden.


> Zusätzliche Signale in der Sensitivity List sollten das Ergebnis der
> Simulation nicht ändern.

Doch! Definiere einen Zähler als Variable, die mit +1 hochzählt. Nimm in 
die sensitivity-Liste einen x-beliebigen Takt und der Zähler zählt. Die 
Synthese wird aber das nicht bauen.

Immer darauf achten, daß SIM = SYN!

Nix flow, nix Anfangswert, nix Startzustand.

Auch für die Synthese sollte man startups durch Signalzuweisungen mit 
:="" im Anfangmoment vermeiden. Immer offen lassen und während des Bauen 
solange simulieren, bis alle Signale entweder druch implizite 
Ablaufzuweisungen oder durch Aufnahme in den Resetzweig sauber 
initialisiert werden, beor sie benutzt worden sind.

Alles andere sind Designtricks, die Fallen aufbauen!

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Fischer wrote:
> Was dort oben
> steht ist eine unvollständige und daher in den meisten falsch
> synthetisierte Syntax.

Das ist völlig korrekte Syntax, nur beschreibt man damit eben keine 
Kombinatorik, sondern ein Latch.

> Aus Simulationssicht ist das in der Tat ein Anfangswert,
> aus Synthesesicht ist das aber eine statische Alternative, um die
> nichtbelegten Pfade zu definieren. Den Begriff "Anfangswert" sollte mn
> nicht verwenden.

Zustimmung.

>> Zusätzliche Signale in der Sensitivity List sollten das Ergebnis der
>> Simulation nicht ändern.
>
> Doch! Definiere einen Zähler als Variable, die mit +1 hochzählt.

Das ist hier aber nicht der Fall. Der Prozess ist rein kombinatorisch, 
da kannst du in die Sensitivity List so viele überflüssige Signale 
reinschreiben wie du willst, es wird weder an der Simulation noch an der 
Synthese etwas ändern.

Autor: Andreas F. (chefdesigner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Richtig, hier bei reiner Kombinatorik kosten überlüssige Signale sicher 
nur Simulationszeit (gfs). Ich habe da etwas weiter gedacht: Die 
Empfehlung , die s-list zu clearen ist eine Frage das sauebren 
Arbeitsstiles und Lesbarkeit des Codes.

Autor: Sym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Screamapilla:

Der Code ist vor allem bei der Addition grob falsch. AluOut wird einem 
kombinatorischen Prozess wie eine Variable verwendet. Signale sind keine 
Variablen!

Was du machen musst: Alle Ausgänge des kombinatorischen Prozess müssen 
in jedem Fall einen Wert zugewiesen bekommen. In deinem Fall müssen die 
Signale Alu_out und Flags_tmp egal welches Case-Statement nun erfüllt 
ist, geschrieben werden.

Was die bidirektionalen Signale betrifft. Trenne diese in ein Eingangs-, 
Ausgangs- und Ausgangs_enable-Signal auf. Dazu noch einen Output-Treiber 
wie (if bus_oe = '1' then bus_b <= bus_o else 'Z';)
Z.B.: bus_i, bus_o und bus_oe; der bidir-Bus selbst ist dann bus_b

Wenn der Bus aus dem dem FPGA nicht hinausgeht, verwende keinen 
bidirektionalen Bus! Das erspart dir viele Probleme.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.