Ich habe eine nette Interviewfrage für VHDL gesehen - baue ein System, das eine Nummer erhält und erkennt, ob es ohne Rest durch 5 geteilt werden kann. Ich habe versucht, das mit einer Zustandsmaschine zu lösen (ich nehme an, sie möchten nicht, dass Sie Mod oder Rem verwenden ), und während ich anfänglich Erfolg hatte (Zahlen wie 5, 10, 15 und Zahlen wie 20, 40, 80 haben funktioniert) ), andere Nummern wie 130, 75 usw. sind für mich gescheitert.
Ich würde meine Zustandsmaschine zeigen, aber es ist ein komplettes Durcheinander (es ist kein Code, es ist eine Zeichnung), und wie gesagt, es funktioniert nicht einmal.
Grundsätzlich habe ich versucht, in Binärzahlen zu schreiben, die durch 5 teilbar sind, und eine Zustandsmaschine zu erstellen, die für sie funktioniert.
Ich würde mich freuen, wenn Sie mir zeigen könnten, wie man dieses Problem löst und wie man denkt, wenn man so etwas sieht.
Vielen Dank!
quelle
Antworten:
Es ist eigentlich recht einfach, einen Restvorgang seriell durchzuführen. Die Hauptannahme ist, dass die Daten zuerst in MSB eingehen, wenn sie seriell sind. Sie benötigen nur N Zustände, um ein Restmodulo N zu berechnen. Beginnen Sie im Zustand "0" und wenn Sie nach dem letzten Bit im Zustand "0" enden (es spielt keine Rolle, wie viele Bits es gibt), ist der Rest Null.
simulieren Sie diese Schaltung - Schaltplan erstellt mit CircuitLab
Überlegen Sie, wie Sie eine lange Teilung durchführen würden, wenn Sie nur den Rest im Auge behalten müssten:
quelle
2n mod 5
und der 1-Pfeil zeigt auf(2n + 1) mod 5
.state
,din
undN
an Ihren Code?Sie können auch eine Zustandsmaschine entwerfen, wenn die Daten LSB-first sind:
Die Existenz eines solchen deterministischen endlichen Automaten (DFA) folgt direkt aus der anderen Antwort , die den DFA für MSB-first beschreibt. Da von DFAs akzeptierte Sprachen regulär sind und reguläre Sprachen bekanntermaßen wegen Umkehrung geschlossen werden (siehe hier ), muss es einen DFA geben, der die folgende Sprache akzeptiert:
.L = { w ∈ { 0 , 1 }∗| umgekehrt(w ) 10 ist teilbar durch 5 }
Konstruktion
Kopieren Sie den MSB-first-DFA aus Dave Tweeds Antwort . Ich habe dafür das Automatentool JFLAP verwendet .
Wenden Sie den expliziten Transformationsalgorithmus für DFA-Umkehrungen an, z. B. wie in CS.SE: Entwerfen eines DFA und umgekehrt beschrieben .
Sie können das (nicht minimierte) Ergebnis dieses Schritts in der alten Revision dieser Antwort sehen.
In der Tat gibt der resultierende Automat die richtigen Antworten:
quelle
Eine Möglichkeit, die Zustandsmaschine (MSB first) zu entwickeln, ist folgende:
Die bisher erhaltene Nummer ist
N
. Angenommen, Sie kennen den RestM = N mod 5
.Es kommt ein neues Bit und der neue Wert ist jetzt
N' = N*2 + b
.Neuer Rest ist dann
M' = (N*2 + b) mod 5 = (M*2 + b) mod 5
.Dies ist einfach genug, um von Hand zu tabellieren:
Was mit der Zustandsmaschine in Dave Tweeds Antwort übereinstimmt.
quelle
Man hofft, dass sich die Interviewfrage eher mit der Frage befasst, wie Sie das Problem lösen würden, als mit den Vor- und Nachteilen von VHDL oder Verilog. Sobald Sie einen Algorithmus haben, sind die Sprachdetails unkompliziert.
quelle
Abhängig davon, wofür die VHDL geschrieben wird, können Sie einen Ansatz wählen, der sie als direkte kombinatorische Berechnung beschreibt. Das Empfangen einer Nummer kann bedeuten, dass sich die gesamte Nummer für einen Taktzyklus in einem Register befindet.
Sie können beispielsweise die Modifikation 5 des Werts notieren, den jedes der Bits darstellt, diese addieren und den Vorgang dann wiederholen, bis Sie weniger als 5 übrig haben. Implementieren Sie dies entweder kombinatorisch für alle Reduktionsschritte. oder verwenden Sie die Logik für eine kleine Anzahl von Zyklen erneut.
Wenn Sie jedoch den VHDL-Rem-Operator verwenden, ist dies möglicherweise die richtige Antwort. Vorausgesetzt, das Unternehmen verfügt über vernünftige Synthesewerkzeuge, die eine ziemlich effiziente Implementierung ermöglichen - ein bisschen mehr Fläche als State-Machine-Lösungen, aber voller Durchsatz und daher wahrscheinlich gute Energie pro Berechnung. Dies ist die Option, deren Implementierung am wenigsten Zeit und damit wahrscheinlich am wenigsten Geld für den Arbeitgeber kostet!
Um fair zu sein, es ist wahrscheinlich nicht die Antwort, die sie mit einer solchen Frage suchen - aber es ist auch eine Gelegenheit, ein echtes Designerlebnis zu präsentieren.
quelle
Wenn die Zahl in Blöcken dargestellt wird, die größer als ein Bit sind, kann es hilfreich sein, einige parallele Berechnungen zur Berechnung des Residuums mod 15 zu verwenden, mit der Maßgabe, dass die Berechnung genau 15 ergeben kann, wenn das Residuum Null ist. Ein einfacher Weg, um den Mod-15-Rest zu berechnen, besteht darin, zu beobachten, dass für jeden Wert von N> = 1 das Addieren der ganz linken 4N-Bits zu dem Teil einer Zahl darüber hinaus einen Wert ergibt, der mit dem ursprünglichen Mod 15 kongruent ist Dadurch kann das Problem in Abhängigkeit von den verfügbaren Ressourcen auf viele verschiedene Arten unterteilt werden.
Wenn man beispielsweise mit einem 32-Bit-Wert beginnt, kann dies als acht 4-Bit-Werte behandelt werden. Diese können paarweise zu vier 5-Bit-Werten addiert werden, die wiederum zu zwei 6-Bit-Werten oder einem 7-Bit-Wert kombiniert werden können. Addiert man die oberen drei Bits dieses 7-Bit-Werts zu den unteren 4-Bit-Werten, so erhält man einen 5-Bit-Wert von höchstens 21. Man kann also feststellen, ob der ursprüngliche Wert ein Vielfaches von 5 ist, indem man beobachtet, ob der Endwert ein Vielfaches von 5 ist eine von 0, 5, 10, 15 oder 20.
quelle
Ich kann mich nicht an meine VHDL erinnern, aber hier ist eine Skizze der Idee, die mir als erstes einfiel:
Die letzten Ziffern (in Basis 10) der ersten Zweierpotenzen sind 1, 2, 4, 8, 6, 2, ... und der Zyklus wird wiederholt. Daher sind die verbleibenden Modi 5 der Zweierpotenzen 1, 2, 4, 3, ....
Auf diese Weise könnten wir Bits aus dem LSB verschieben und die Restmodifikation 5 akkumulieren, die der Position entspricht, wann immer ein
1
Bit gesehen wird. Mache auch den Akkumulations-Mod 5 und es ist genug zu prüfen, ob die Summe am Ende Null ist.quelle
Wir können die Idee aus der Antwort hier verwenden , dass wir in Basis 4 ableiten können, dass eine Zahl nur dann durch 5 teilbar ist, wenn die alternierende Ziffernsumme ist. Wir deshalb
Versuchen wir die Zahl 166 = (10) (10) (01) (10): 2,2,1,2
2-2 + 1-2 = -1
Das ist <= 3 im absoluten Wert und nicht 0, weshalb wir in nur einer Iteration schließen können, dass 166 nicht gleichmäßig durch 5 geteilt wird.
Könnte sein, dass ein kleiner Speicher in Bezug auf die Geschwindigkeit / Anzahl der Gates billiger / besser ist als das Iterieren. Man kann natürlich das schlechteste vorberechnen (größtmögliches Ergebnis bei den erlaubten Eingaben) und das Design entsprechend planen.
quelle
Der MSB-Ansatz ist definitiv einfacher, aber ich habe es geschafft, das LSB-Zustandsdiagramm zu erstellen, ohne die MSB-Lösung generieren zu müssen. Ich habe nur ein paar Stunden gebraucht. Es stellt sich heraus, dass es dem von @ComFreek gezeigten entspricht, nur anders kommentiert.
Wir werden zwei Zahlen verfolgen. Zuerst werden wir die laufende Summe, Modulo 5 ("SUM") verfolgen. Zweitens verfolgen wir den Wert der nächsten Potenz von 2, die eingeschoben werden soll, Modulo 5 ("NEXT"). Ich werde jeden Zustand mit möglichen Werten für "SUM" oben und den entsprechenden "NEXT" -Werten darunter darstellen.
Wir beginnen mit dem Fall, in dem "SUM" modulo 5 0 ist:
Beachten Sie, dass ein Zustand wie
folgt aussieht: 3,2,4,1
1,4,3,2
entspricht:
1,3,4,2
2,1,3,4
Weil beide Zustände dies darstellen:
SUM = 1 und NEXT = 4 ODER
SUM = 2 und NEXT = 3 ODER
SUM = 3 und NEXT = 2 ODER
SUM = 4 und NEXT = 1.
Okay, jetzt müssen wir zusätzliche Zustände entwickeln, da die meisten Interviewer nicht von einem Zustandsdiagramm mit nur einem Zustand beeindruckt sein werden. Wir sind fertig, wenn jeder Zustand zwei Übergänge hat.
Immer wenn Sie in einen neuen Zustand wechseln, wird jede Zahl in "NEXT" verdoppelt und dann mit 5 moduliert. Für die "SUM" gelten folgende Regeln:
Beginnen wir also damit, die Übergänge auszufüllen, wenn das eingehende Bit 1 ist.
Okay, jetzt füllen wir die Nullen aus. Es wird nur ein Bundesstaat hinzugefügt, daher werden wir auch die Übergänge ausfüllen.
Und voila! Wir haben eine Zustandsmaschine, die das LSB zuerst akzeptiert, ohne die MSB-Lösung generieren zu müssen.
quelle
All das scheint so kompliziert! Es gibt eine einfache mathematische Methode, um festzustellen, ob eine binäre Ganzzahl durch fünf teilbar ist. Erinnern Sie sich zu Beginn, wie man in gewöhnlicher Dezimalarithmetik "Neunen austreibt"? Das Residuum Modulo 9 einer Dezimalzahl ist dasselbe wie das Residuum Modulo 9 der Summe seiner Ziffern. Dies funktioniert, weil 9 eins weniger als die Zahlenbasis ist.
Es gibt einen ähnlichen Vorgang, das "Auswerfen von Erhöhungen", bei dem die Zeichen alternierender Ziffern negativ gesetzt werden. Das funktioniert, weil elf eins größer als die Zahlenbasis ist.
Wenn wir also "Fünfer austreiben" wollen, könnten wir unsere ganze Zahl auf der Basis vier darstellen. Dann beginnen wir mit dem niedrigsten Ziffernpaar als Anfangssumme und subtrahieren es vom nächsten Ziffernpaar, um die nächste Summe zu erhalten. Nachdem Sie unsere Kandidatenzahl auf diese Weise durchlaufen haben, ist die Endsumme null oder durch 5 teilbar, wenn unsere ursprüngliche Ganzzahl durch 5 teilbar ist.
Beispiel 70: 01 00 01 10 -> 01 00 -1 -> 01 01 -> 00, teilbar durch 5 Beispiel 49: 11 00 01 -> 11 -1 -> 1 00 -> 1, NICHT teilbar durch 5
Beachten Sie, dass Sie zusätzliche Bits für das Vorzeichen der akkumulierten Differenz und für Fälle mitführen müssen, in denen eine Übertragung stattfindet.
Ein anderer Weg ist, einfach die Hexadezimalziffern zu addieren, um das Residuum Modulo 15 zu erhalten. Natürlich benötigen Sie einen letzten logischen Schritt, um die drei akzeptablen Ergebnisse von Null, Fünf und Zehn zu identifizieren.
Beispiel 70: 4 6 -> A, also ist 70 durch 5 teilbar (aber nicht durch 15) Beispiel 49: 3 1 -> 4, also ist 70 NICHT durch 5 teilbar.
Beachten Sie, dass Sie verschiedene Zahlenbasen verwenden können, um viele Teilbarkeitstests zu erstellen. In der Computerlogik sind jedoch diejenigen für Potenzen von 2 +/- 1 am einfachsten zu implementieren.
In der Dezimalarithmetik ist einer meiner Favoriten mein Test für Residuum Mod 7. Beachten Sie, dass 100 zwei größer als ein Vielfaches von 7 ist. Gruppieren Sie die Ziffern also in Paare (arbeiten Sie mit der Zahlenbasis 100) und addieren Sie die Hunderte ZWEIMAL aus den Einheiten. Hier arbeiten wir von links nach rechts ...
Beispiel: 98 76 -> 2 72 -> 76, daher ist 9876 nicht teilbar durch 7. Es ist 6 mod 7. Beispiel: 03 45 67 -> 51 67 -> 1 69 -> 71, so ist es 1 mod 7.
Natürlich nimm in Binärform einfach die Summe der Oktalziffern (3-Bit-Gruppen).
Entschuldigung, ich wünschte, ich wäre ein Verilog-Guru, aber das Rechnen ist alles, was ich in dieser Lebensphase anbieten kann. In Ron Doerflers "Dead Reckoning" finden Sie eine Menge solcher Tricks.
quelle
Eine VHDL-Interviewfrage sollte zu einem VHDL-Code führen.
Ich hatte Gelegenheit, einen ghdl llvm-Backend-Fehler mit einer Implementierung von Dave Tweeds Zustandsübergangstabelle zu finden, in der ghdls Autor die Implementierung in einer Funktion auf 17 Zeilen destillierte:
Der zugehörige Testfall ist recht klein, um das Debuggen zu vereinfachen, und verwendet Statusnamen, die mit VHDL kompatibel sind. Der Aufzählungstyp bleibt erhalten:
(erstellt mit Dia)
Die Idee dabei ist, dass die Funktion (oder sogar ein Beispiel für ein VHDL-Programm mit 27 Zeilen) kurz genug ist, um während eines Interviews eine VHDL-Antwort zu schreiben. Kein Grund zur Sorge, eine Interviewfrage zu verderben, die den Nachweis von Wissen und Können erfordert. Es wird von einem Interviewten erwartet, dass er eine Implementierung verteidigt, wenn er befragt wird.
(Der Fehler im llvm-Backend wurde heute in Commit 1f5df6e behoben .)
Zu beachten ist, dass die Zustandsübergangstabelle auch angibt, wo ein Quotientenbit eine '1' ist, die durch einen Übergang in einen Zustand mit einem niedrigeren Restwert (oder beiden Übergängen für r4) angezeigt wird, wenn 5 von der Dividende subtrahiert wird. Dies kann in einer separaten Tabelle (oder einer Tabelle eines Datensatztyps, der umständlich zu sein scheint) codiert werden. Wir machen dies historisch in Grafikhardware, die mit horizontalen Bildschirmauflösungen um ein Vielfaches von 5 Pixeln arbeitet.
Auf diese Weise erhalten wir ein div / mod5, das einen Quotienten und einen Rest ergibt:
Implementiert hier mit einer Erzeugungsanweisung, einer inneren Erzeugungsanweisung, die Quotientenbits erzeugt. Das Array remaindr stellt eine Ablaufverfolgung für den Statusübergang bereit:
Alles ohne Rechenoperation.
Es ist auch möglich, eine Prozedur zu implementieren, ohne dass alle Register die Parameter mit Modus ausnutzen. Das würde sich einer Mindestanzahl von Zeilen für ein Interview nähern.
Eine getaktete sequentielle Implementierung würde einen Bitzähler und eine Flusssteuerung erfordern (ein JK-Flipflop und ein paar Gatter).
Es gibt einen Kompromiss zwischen Zeit und Komplexität, der von der Dividendengröße abhängt, die Sie wahrscheinlich auch in einem Interview verteidigen müssen.
quelle