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).
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.
Synchronen Prozess draus machen. Register = Flipflop
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.
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...
Wenn dir schon klar ist, daß A und B Register sein müssen, warum setzt du es dann nicht so um?
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!
Hier ist ein Diagram von dem, was ich implementieren will.
@ 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
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.
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
Andreas Fischer wrote:
> Wieso brauchen kombinatorische Signale einen Anfangswert ?
Beispiel:
1 | process(a) |
2 | begin
|
3 | -- b <= '0';
|
4 | |
5 | if a = '1' then |
6 | b <= '1'; |
7 | end if; |
8 | 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.
> 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.
> 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.
@ 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
> 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.
@ 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
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.
@ 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
1 | ALU_OP : process (A_reg, B_reg, u_instruction) |
2 | begin
|
3 | |
4 | CASE u_instruction is |
5 | |
6 | when op_lda => |
7 | alu_out <= A_reg; |
8 | |
9 | when op_ldb => |
10 | alu_out <= A_reg; |
11 | |
12 | when op_add => |
13 | ALU_out <= (A_reg + B_reg); |
14 | --------------------------------------------------------------------------
|
15 | |
16 | -- Noch mehr uinstrutions
|
17 | |
18 | --------------------------------------------------------------------------
|
19 | |
20 | |
21 | when others => ALU_Out <= (others => '0'); |
22 | |
23 | end CASE; |
24 | |
25 | end process ALU_OP; |
Die Flags kommen da nicht rein. Z und C kann man einfach so dekodieren
1 | Z <=0 when alu_out =0 else '1'; |
2 | C <= alu_out(8); |
MFG Falk
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.
Andreas Schwarz wrote: > Andreas Fischer wrote: >> Wieso brauchen kombinatorische Signale einen Anfangswert ? > > Beispiel: >
1 | > process(a) |
2 | > begin |
3 | > -- b <= '0'; |
4 | >
|
5 | > if a = '1' then |
6 | > b <= '1'; |
7 | > end if; |
8 | > end process; |
9 | >
|
> > 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!
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.
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.
@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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.