Arithmetische Hausaufgaben

Lyoshenka, Lyoshenka, tu mir einen Gefallen!
Lernen Sie, Aljoschenka, die Multiplikationstabelle!
Agnia Barto


Erste Aufgabe fĂŒr einen ErstklĂ€ssler. Es wird eine positive Zahl angegeben. Sie mĂŒssen eine andere Zahl damit multiplizieren, die im Voraus nicht bekannt ist. Die Frage ist, wie werden die edlen Dons dazu raten ??? Ein erfahrener Entwickler wird mit Sicherheit sagen, man sage, man setze den Multiplikator und mache sich keine Sorgen um mein Gehirn. Und vielleicht wird es von Grund auf falsch sein! Denn neben den Monstern von Alterra und Xilinx gibt es auch eine so wunderbare Familie wie den iCE-40 von Lattice . Ultra Mikrokonsum. Sehr billig Ja, das Problem ist, dass sie schmerzhaft klein sind, und leider gibt es dort keine Multiplikatoren. Ich bin darauf vor ungefĂ€hr 4 Jahren gestoßen, als ich einen bestimmten ADPCM-Codec vom Assembler adsp-2185 auf einen solchen Kristall portierte.

Nein, ohne einen Allzweckmultiplikator (fĂŒr zwei Variablen) wĂ€re das sicherlich nicht möglich gewesen. Ich musste es mit Stiften machen und er nahm den halben Kristall. Das Problem ist, dass er in jedem meiner Schritte dreschte, d.h. ĂŒberhaupt keine Fenster. Neben der Multiplikation der Variablen im Algorithmus gab es feste Koeffizienten, die ebenfalls multipliziert werden mussten. Und es gab keine Möglichkeit, den Multiplikator dafĂŒr zu verwenden, es gab einfach kein Fenster mehr. Und da der Kampf in dem Projekt durch jede Zelle ging, war ich natĂŒrlich sehr daran interessiert, wie man ausweicht und die Eigenschaften dieser Koeffizienten verwendet, um das optimale Multiplikationsschema mit ihnen zu erzielen (kein Allzweckmultiplikator, sondern ein MultiplikationsgerĂ€t mit einer bestimmten Zahl!). Nun, wie ein kompletter Traum wird wahr - so dass die Multiplikationsschemata mit verschiedenen Koeffizienten einige gemeinsame Kristallressourcen optimal nutzen.

Von der Aufgabe fĂŒr den ErstklĂ€ssler gingen wir nahtlos zur Aufgabe fĂŒr den Ingenieur und Mathematiker ĂŒber. Wie erstelle ich ein optimales Multiplikationsschema fĂŒr eine bestimmte Zahl?

Erinnern wir uns ein wenig daran, wie wir im Allgemeinen die Zahl A mit B multiplizieren.

  1. Setzen Sie das Ergebnis zunÀchst auf Null.
  2. Lassen Sie uns ĂŒber Bits A gehen .
  3. Wenn in Entladung 0, tun wir nichts.
  4. Wenn in Bit 1, verschieben wir B um die entsprechende Anzahl von Bits und addieren zum Ergebnis.

Insgesamt ist es umso einfacher, mit der Zahl zu multiplizieren, je weniger Einheiten A in den Ziffern enthalten sind. Das Multiplizieren mit 2, 4 oder 8 ist einfach. Es ist nur eine Schicht erforderlich. Etwas schwerer mit 3, 5 oder 10 zu multiplizieren. Es wird eine Addition dauern. Noch schwerer mit 11 zu multiplizieren. Je mehr Einheiten, desto schwerer.

Nun, was ist mit 255 multipliziert? Bis zu 8 Einheiten, eine Alptraumaufgabe, richtig? Und hier sind die Figuren! Machen wir eine knifflige Finte mit unseren Ohren. Multiplizieren Sie unser B mit 256 (d. H. Verschieben Sie es um 8 Stellen) und subtrahieren Sie es vom Ergebnis. Es stellt sich heraus, dass das Multiplizieren mit 255 so einfach ist wie das Multiplizieren mit 10. Es ist genauso einfach, mit 254, mit 240 und mit 224 zu multiplizieren (wenn Sie möchten, ĂŒberprĂŒfen Sie!).

Insgesamt hilft die Subtraktion bei der Multiplikation. Erinnern Sie sich an diesen wertvollen Gedanken. In der Zwischenzeit bezeichnen wir die Schwierigkeit einer Zahl als die minimale Anzahl von Additions- (oder Subtraktions-) Operationen, die erforderlich sind, um mit ihr zu multiplizieren. Schichten werden nicht berĂŒcksichtigt. Denn im Rahmen des Problems (wir haben Schaltkreise, keine Programmierung!) Werden sie umsonst beschafft. Formulieren wir eine offensichtliche, aber nĂŒtzliche Aussage:

Die Schwierigkeit einer Zahl ist kleiner oder gleich der Anzahl der Einheiten in der BinÀrnotation.
Wenn wir ehrlich ohne Subtraktionstricks multiplizieren, wie wir es in der Schule gelehrt haben, entspricht die Anzahl der Additionen der Anzahl der Einheiten in BinĂ€r- A. Und wenn wir anfangen zu tricksen und außerdem GlĂŒck haben, werden wir die Anzahl der Operationen reduzieren.

Eine interessante Konsequenz dieser Aussage:
Die Schwierigkeit einer n-Bit-Zahl ist immer kleiner als n .
Immerhin ist die grĂ¶ĂŸte Anzahl von Einheiten in einer n- stelligen Zahl n fĂŒr eine Zahl wie 255. Andererseits ist klar, dass der Fokus wie bei der Multiplikation mit 255 fĂŒr Zahlen beliebiger Bittiefe wiederholt werden kann. Dies eröffnet Perspektiven fĂŒr die Optimierung von Universalmultiplikatoren.

Lassen Sie uns unsere Argumentation regelmĂ€ĂŸiger betrachten. Lassen Sie uns zunĂ€chst bereits eine Art Multiplikationsschema von A haben. Wir nehmen als Einheit. Dann werden alle Terme so verschoben, addiert und subtrahiert, dass das Ergebnis das gleiche A ist. Insgesamt ist unser Multiplikationsschema mit A nichts anderes als eine Darstellung der Zahl A als die Summe von Zweierpotenzen, in der die Terme sowohl mit dem + -Zeichen als auch mit dem - -Zeichen sein können. Und Sie können die positiven und negativen Terme gruppieren und sagen, dass das Schema durch die Differenz einiger Zahlen A + und A- , gleich A, beschrieben wird. Das ist schlecht ... Die Glieder der Differenz können beliebig groß sein. Überlegen wir, ob es irgendwelche Überlegungen gibt, um sie einzuschrĂ€nken.
ZunĂ€chst stellen wir fest, dass jede Zweierpotenz nur einmal in den Stromkreis eintreten kann. Wenn sie zweimal mit demselben Vorzeichen eintritt, kann dies durch eine Zweierpotenz durch eine Einheit grĂ¶ĂŸer ersetzt werden. Tritt sie zweimal mit unterschiedlichen Vorzeichen ein, werden diese voneinander subtrahiert. Insgesamt ist das Schema der ĂŒblichen binĂ€ren Darstellung von A sehr Ă€hnlich . Der einzige Unterschied ist, dass seine "Bits" (im Folgenden werden wir sie Trits nennen ) nicht zwei, sondern drei Werte annehmen können: 1, 0 und -1.

Total Wenn A eine n- Bit-BinÀrzahl ist, wird das Multiplikationsschema durch die Summe beschrieben:

A=tm2m+tm−12m−1+....+t12+t0


wo ti- trits mit den Werten 1, 0 und -1 und m ist eine unbekannte Zahl.

Im Folgenden werden wir einen solchen Ausdruck ein ternĂ€res Schema oder einfach ein Schema oder ein Multiplikationsschema fĂŒr die Zahl A nennen.

Lassen Sie uns versuchen, m zu finden. Wie aus dem Beispiel mit der Multiplikation mit 255 hervorgeht, ist m keineswegs kleiner als n . Mal sehen, ob es gleich n + 1 sein kann .
A sei wie bisher eine positive n- stellige Zahl. Dann ist das Multiplikationsschema definiert als:

A=tn+12n+1+tn2n+tn−12n−1....+t12+t0


Daran erinnern 2k+2k−1+....+2+1=2k+1−1
Daher kann der höchste Trit in keiner Weise gleich -1 sein. Selbst wenn alle anderen 1 sind, ist die Summe immer noch -1. Und unter der Bedingung A ist positiv. Nun sei der oberste Trit 1. In diesem Fall sollte der nĂ€chste Trit -1 sein. Andernfalls ist die Menge zu groß. In der Tat, wenn der nĂ€chste Trit 0 ist, wird die Summe nicht weniger als sein 2n+1−(2n−1+...+1)=2n+1−(2n−1)=2n+1
WĂ€hrend n- Bit A nicht mehr ist 2n−1. Aber wenn der oberste Trit 1 und der nĂ€chste -1 ist, dann ist die Summe der beiden obersten Glieder 2n+1−2n=2n. Der oberste Trit ist also 0.

Damit ist eine wichtige Aussage bewiesen: m = n .

Mit anderen Worten, um ein Multiplikationsschema mit einem n- Bit A darzustellen, sind n + 1 Zweierpotenzen ausreichend - von 0 bis n (eine mehr als die binÀre Darstellung), was uns sofort vor der Unendlichkeit bewahrt.

Nun können Sie versuchen, die Schwierigkeiten (siehe oben) einer bestimmten Zahl zu berechnen. Das Einfachste ist, das zu tun, was wir tun, indem wir die BinĂ€rzahlen der Reihe nach schreiben. Nur erstens haben wir hier keine Bits, sondern Trites (drei mögliche Werte), zweitens geben einige Kombinationen von Trites negative Zahlen und sie mĂŒssen verworfen werden, drittens können einige Kombinationen ĂŒbereinstimmende Zahlen ergeben. Dies bedeutet, dass es fĂŒr eine solche Nummer mehrere Schemata gibt.

Wir werden in Python schreiben. Nicht weil ich so ein Fan von ihm bin, sondern weil es sehr praktisch ist, mit ihm in Jupyter-NotizbĂŒchern zu arbeiten. ZunĂ€chst schreiben wir die TriScheme-Klasse, die mit den oben eingefĂŒhrten ternĂ€ren Schemata arbeitet, die allSchemes-Funktion, die mit einer einfachen AufzĂ€hlung alle Schemata fĂŒr Zahlen einer bestimmten BitgrĂ¶ĂŸe berechnet, und die printSchemes-Funktion, die das Ergebnis ausgibt:

Tricheme
class TriScheme(): def __init__(self, buf:list): #    self.buf=[] for i in range(0, len(buf)): s=0 if (type(buf[i]) == int) or (type(buf[i]) == float): if buf[i] > 0: s=1 elif buf[i] < 0: s=-1 self.buf.append(s) def zero(self): #  self.buf=[0]*len(self.buf) def __repr__(self): #     s="" for i in range(1, len(self.buf)+1): if self.buf[-i]==1: s=s+"+" elif self.buf[-i]==0: s=s+"0" elif self.buf[-i]==-1: s=s+"-" return s def inc(self): #  (  ) for i in range(0, len(self.buf)): if (self.buf[i]+1) < 2: self.buf[i]+=1 break for j in range(0, i+1): self.buf[i]=-1 def __int__(self): #   m=1 s=0 for i in range(0, len(self.buf)): s+=self.buf[i]*m m=m*2 return s def isMax(self): #     s=0 for i in range(0, len(self.buf)): s+=self.buf[i] return (s == len(self.buf)) def isMaxDig(self): # ,   ,  n-  s=[0]*len(self.buf) s[0]=-1 s[-1]=1 return (self.buf == s) def ones(self): #     ( ) s=0 for i in range(0, len(self.buf)): if self.buf[i] != 0: s+=1 return s def minPos(self): #      for i in range(0, len(self.buf)): if self.buf[i] != 0: return i def allSchemes(dig): #        dig sch=[] for i in range(0, 2**dig): sch.append([]) ts=TriScheme([0]*(dig+1)) while True: sch[int(ts)].append(TriScheme(ts.buf)) if ts.isMaxDig(): break ts.inc() return sch def printSchemes(sch): #        _ _ for i in range(0, len(sch)): s=sch[i] a=[] for j in range(0, len(s)): a.append(s[j].ones()) m=min(a) print(i, m, len(s), s) #     4-  sch4=allSchemes(4) printSchemes(sch4) 


Wir berechnen die Schemata fĂŒr alle 4-Bit-Zahlen:

0 0 1
1 1 5 [0000+, 000 + -, 00 + -, 0 + ---, + ----]
2 1 4 [000 + 0, 00 + -0, 0 + - 0, + --- 0]
3 2 7 [000 ++, 00 + - +, 00 + 0-, 0 + - +, 0 + -0-, + --- +, + - 0-]
4 1 3 [00 + 00, 0 + -00, + - 00]
5 2 8 [00 + 0 +, 00 ++ -, 0 + + -0 +, 0 + - + -, 0 + 0--, + - 0+, + - + -, + -0--]
6 2 5 [00 ++ 0, 0 + - + 0, 0 + 0-0, + - + 0, + -0-0]
7 2 7 [00 +++, 0 + - ++, 0 + 0- +, 0 + 00-, + - ++, + -0- +, + -00-]
8 1 2 [0 + 000, + -000]
9 2 7 [0 + 00 +, 0 + 0 + -, 0 ++ -, + -00 +, + -0 + -, + - + -, +0 ---]
10 2 5 [0 + 0 + 0, 0 ++ - 0, + -0 + 0, + - + - 0, + 0-0]
11 3 8 [0 + 0 ++, 0 ++ - +, 0 ++ 0-, + -0 ++, + - + - +, + - + 0-, +0 - +, + 0-0 -]
12 2 3 [0 ++ 00, + - + 00, + 0-00]
13 3 7 [0 ++ 0 +, 0 +++ -, + - + 0+, + - ++ -, + 0-0 +, +0 - + -, + 00--]
14 2 4 [0 +++ 0, + - ++ 0, + 0- + 0, + 00-0]
15 2 5 [0 ++++, + - +++, +0 - ++, + 00- +, + 000-]

Hier am Anfang der Zeile steht eine Zahl, gefolgt von ihrer Schwierigkeit (der minimalen Anzahl von Nicht-Null-Elementen in der Schaltung), dann der Anzahl von Schaltungen und schließlich einer Liste von Schaltungen.

In dem Schema bedeutet + 1, 0 - 0 und - - -1. Der Ă€lteste Stich links (wie bei der ĂŒblichen Zahlenschreibung)

Die Tabelle zeigt zum einen, dass nur die Nummern 13 und 11 die Schwierigkeit 3 ​​haben (das Maximum fĂŒr 4-Bit-Nummern, wie oben gezeigt). Und zweitens ist die Anzahl der verschiedenen Schemata fĂŒr jede Zahl ziemlich groß. Dies deutet zum einen darauf hin, dass die Multiplikation meistens viel einfacher ist, als wir es in der Schule gelernt haben. Und zweitens ist die Auswahl an Schaltungen fĂŒr die Implementierung von Vorrichtungen zum Multiplizieren mit mehreren Konstanten unter Verwendung gemeinsamer Kristallressourcen ziemlich groß. Noch interessanter sind die Daten zu lĂ€ngeren Zahlen. FĂŒr 14-Bit-Nummern betrĂ€gt die maximale Schwierigkeit 8, und die maximale Anzahl von Schaltkreisen betrĂ€gt 937.

Alles wĂ€re in Ordnung, aber der obige Algorithmus ist zu teuer. Ihre KomplexitĂ€t wĂ€chst mit 3nabhĂ€ngig von der LĂ€nge der Zahlen n . FĂŒr 8 Stellen zĂ€hlt sofort. FĂŒr 14 Minuten. FĂŒr 16 Stunden. Wenn Sie die Schaltkreise FÜR ALLE n- Bit-Nummern lesen mĂŒssen, können Sie leider nichts anderes tun, als sie in C umzuschreiben und einen leistungsfĂ€higeren Computer zu verwenden. Der Algorithmus ist jedoch perfekt parallelisiert und kann durchaus auf der GPU oder im Cluster ausgefĂŒhrt werden.

Zum Entwerfen bestimmter Verschraubungen sind normalerweise Listen von Schemata fĂŒr bestimmte Nummern erforderlich. Und ALLES ist wĂŒnschenswert und nicht nur optimal. Die Wahl kann von den UmstĂ€nden abhĂ€ngen (z. B. ein GerĂ€t zum Multiplizieren mit mehreren Konstanten). Und hier können Sie einen viel humaneren Algorithmus anbieten. Wir erinnern uns noch einmal an die bemerkenswerte Gleichheit: 2k+2k−1+....+2+1=2k+1−1.

Im Kontext der Aufgabe bedeutet dies Folgendes. Angenommen, es sind mehrere Ă€ltere Trit-Schemata bekannt. Alle kleinen Trits, die an Position k beginnen, sind unbekannt und werden zuvor als gleich Null betrachtet. Wenn Sie dann die unbekannten Trits auf irgendeine Weise Ă€ndern, Ă€ndern Sie den Wert der Schaltung um nicht mehr als plus / minus 2k+1−1. Außerdem nimmt mit dem VorrĂŒcken zu den unteren Trits der Wert dieser Unsicherheit ab. Dies ermöglicht Ihnen die Suche nach Schemata anhand aufeinanderfolgender NĂ€herungen, Trit fĂŒr Trit.

Es sei eine positive Zahl A gegeben. Wir mĂŒssen alle Schemata dafĂŒr unter n- Bit-Zahlen finden. Der absolute Wert der Differenz zwischen A und dem Wert einer bestimmten Schaltung wird als Fehler der Schaltung bezeichnet. ZunĂ€chst nehmen wir ein n + 1- Bit-Schema, das n- Bit-Nummern beschreibt, die alle unbekannt sind und anfangs auf Null gesetzt werden. Und lassen Sie uns nacheinander Trits definieren, beginnend mit dem Ă€lteren. In der k- ten Position kann die Schaltung drei neue Muster erzeugen - mit Werten des k- ten Trits 1, 0 und -1. Wir lassen in der Liste der Schemata nur diejenigen von ihnen zur Fortsetzung, deren Fehler nicht ĂŒbersteigt 2k−1. Fahren Sie mit der resultierenden Liste der Schaltkreise mit dem Schritt an Position k-1 fort . Somit gibt es in der resultierenden Liste (an Position 0) ALLE möglichen Schemata, deren Wert A ist . Schreiben wir eine solche Funktion calcSchemes.

calcSchemes
 def calcSchemes(a, n=-1): m=1 nn=1 while m < a: nn+=1 m=m*2 if n < nn: n=nn sch=[TriScheme([0]*n)] for i in range(0, n): tmp=[] pos=ni-1 for j in range(0, len(sch)): for k in range(-1, 2): ts=sch[j] ts.buf[pos]=k d=abs(a - int(ts)) if d <= (2**pos - 1): tmp.append(TriScheme(ts.buf)) sch=tmp return sch 


Und schließlich der versprochene Verkauf von TrĂ€umen.

In diesem Projekt mussten zwei Koeffizienten multipliziert werden: 16351 und 16318. Mit calcSchemes finden wir die Schemata fĂŒr diese Koeffizienten:

Schemata
FĂŒr 16351
0 ++++++++ 0 +++++
0 +++++++++ - ++++
0 +++++++++ 0 - +++
0 +++++++++ 00 - ++
0 ++++++++++ 000- +
0 +++++++++ Angestellte
+ - +++++++ 0 +++++
+ - ++++++++ - ++++
+ - ++++++++ 0 - +++
+ - ++++++++ 00 - ++
+ - +++++++++ 000- +
+ - +++++++++ Angestellte
+0 - ++++++ 0 +++++
+0 - +++++++ - ++++
+0 - +++++++ 0 - +++
+0 - +++++++ 00 - ++
+0 - ++++++++ 000- +
+0 - +++++++ Angestellte
+00 - +++++ 0 +++++
+00 - ++++++ - ++++
+00 - ++++++ 0 - +++
+00 - ++++++ 00 - ++
+00 - ++++++ 000- +
+00 - ++++++ Angestellte
+000 - ++++ 0 +++++
+000 - +++++ - ++++
+000 - +++++ 0 - +++
+000 - +++++ 00 - ++
+000 - +++++ 000- +
+000 - +++++ AnhÀngsel
+0000 - +++ 0 +++++
+0000 - ++++ - ++++
+0000 - ++++ 0 - +++
+0000 - ++++ 00 - ++
+0000 - ++++ 000- +
+0000 - ++++ Angestellte
+00000 - ++ 0 +++++
+00000 - +++ - ++++
+00000 - +++ 0 - +++
+00000 - +++ 00 - ++
+00000 - +++ 000- +
+00000 - +++ AnhÀngsel
+ 000000- + 0 +++++
+000000 - ++ - ++++
+000000 - ++ 0 - +++
+000000 - ++ 00 - ++
+000000 - ++ 000- +
+000000 - ++ AnhÀngsel
+ 0000000-0 +++++
+0000000 - + - ++++
+ 0000000- + 0 - +++
+ 0000000- + 00 - ++
+ 0000000- + 000- +
+ 0000000- + abhÀngig
+00000000 - ++++
+ 00000000-0 - +++
+ 00000000-00 - ++
+ 00000000-000- +
+ 00000000-0000-

FĂŒr 16318
0 +++++++ 0 +++++ 0
0 ++++++++ - ++++ 0
0 ++++++++ 0 - +++ 0
0 ++++++++ 00 - ++ 0
0 +++++++++ 000- + 0
0 ++++++++ 0000-0
+ - ++++++ 0 +++++ 0
+ - +++++++ - ++++ 0
+ - +++++++ 0 - +++ 0
+ - +++++++ 00 - ++ 0
+ - +++++++ 000- + 0
+ - +++++++ 0000-0
+0 - +++++ 0 +++++ 0
+0 - ++++++ - ++++ 0
+0 - ++++++ 0 - +++ 0
+0 - ++++++ 00 - ++ 0
+0 - ++++++ 000- + 0
+0 - ++++++ 0000-0
+00 - ++++ 0 +++++ 0
+00 - +++++ - ++++ 0
+00 - +++++ 0 - +++ 0
+00 - +++++ 00 - ++ 0
+00 - +++++ 000- + 0
+00 - +++++ 0000-0
+000 - +++ 0 +++++ 0
+000 - ++++ - ++++ 0
+000 - ++++ 0 - +++ 0
+000 - ++++ 00 - ++ 0
+000 - ++++ 000- + 0
+000 - ++++ 0000-0
+0000 - ++ 0 +++++ 0
+0000 - +++ - ++++ 0
+0000 - +++ 0 - +++ 0
+0000 - +++ 00 - ++ 0
+0000 - +++ 000- + 0
+0000 - +++ 0000-0
+ 00000- + 0 +++++ 0
+00000 - ++ - ++++ 0
+00000 - ++ 0 - +++ 0
+00000 - ++ 00 - ++ 0
+00000 - ++ 000- + 0
+00000 - ++ 0000-0
+ 000000-0 +++++ 0
+000000 - + - ++++ 0
+ 000000- + 0 - +++ 0
+ 000000- + 00 - ++ 0
+ 000000- + 000- + 0
+ 000000- + 0000-0
+0000000 - ++++ 0
+ 0000000-0 - +++ 0
+ 0000000-00 - ++ 0
+ 0000000-000- + 0
+ 0000000-0000-0

Wir haben GlĂŒck! Beide Faktoren haben Schwierigkeiten 3. Wir wĂ€hlen die optimalen Schemata fĂŒr beide:
FĂŒr 16318 + 0000000-0000-0 und fĂŒr 16351 - + 00000000-0000- . Wir hatten wieder GlĂŒck! Achten Sie auf die SchwĂ€nze der Schemata. Sie unterscheiden sich fĂŒr 16318 und 16351 nur durch eine Linksverschiebung um eine Position. Das mit 16318 und 16351 multiplizierte GerĂ€t enthĂ€lt also nur einen zusĂ€tzlichen Multiplexer, der den verschobenen und nicht verschobenen Operanden am Eingang des Addierers schaltet.

Lassen Sie uns das Ergebnis sehen. Wir schreiben auf sehr drei Möglichkeiten fĂŒr das GerĂ€t der Multiplikation mit 16318 und 16351:

  1. Option "Schule" (nur ErgÀnzungen und Schichten)
  2. Optimale Schaltung
  3. Optimales Schema mit gemeinsam genutzten Ressourcen

FĂŒr alle drei Optionen fĂŒhren wir die Synthese durch und sehen, wie viele Kristallressourcen fĂŒr jede von ihnen ausgegeben werden.

Verilog
 /*----------------------- ----------------------*/ module mul_163xx( input[15:0] di, input s, output[31:0] dq ); reg[31:0] dd; always @* if(s) dd= (di<<13)+(di<<12)+(di<<11)+(di<<10)+(di<<9)+(di<<8)+(di<<7)+(di<<4)+(di<<3)+(di<<2)+(di<<1) + (di<<6)+di; else dd=(di<<13)+(di<<12)+(di<<11)+(di<<10)+(di<<9)+(di<<8)+(di<<7)+(di<<4)+(di<<3)+(di<<2)+(di<<1) + (di<<5); assign dq=dd; endmodule /*---------------------------  -------------------------*/ module mul_163xx( input[15:0] di, input s, output[31:0] dq ); reg[31:0] dd; always @* if(s) dd= (di<<14) - (di<<5) - di; else dd=(di<<14) - (di<<6) - (di<<1); assign dq=dd; endmodule /*--------------    --------------*/ module mul_163xx( input[15:0] di, input s, output[31:0] dq ); wire[31:0] tail = (di<<5) + di; reg[31:0] dd; always @* if(s) dd= (di<<14) - tail; else dd=(di<<14) - (tail<<1); assign dq=dd; endmodule /*-------------------------------------------------------------*/ module mult_tb(); reg clk = 0; always #100 clk = ~clk; reg[15:0] di; wire[31:0] dq; reg s; mul_163xx mul ( .di (di), .dq (dq), .s (s) ); initial begin clk=0; s=0; $display("s=0"); di=1; @(posedge clk); $display("%d", dq); di=10; @(posedge clk); $display("%d", dq); di=100; @(posedge clk); $display("%d", dq); di=1000; @(posedge clk); $display("%d", dq); s=1; $display("s=1"); di=1; @(posedge clk); $display("%d", dq); di=10; @(posedge clk); $display("%d", dq); di=100; @(posedge clk); $display("%d", dq); di=1000; @(posedge clk); $display("%d", dq); $finish; end endmodule /*------------------------------PCF-------------------------------*/ set_io dq[0] A1 set_io dq[1] A2 set_io dq[2] P16 set_io dq[3] M13 set_io dq[4] A5 set_io dq[5] A6 set_io dq[6] A7 set_io dq[7] L13 set_io dq[8] A9 set_io dq[9] A10 set_io dq[10] A11 set_io dq[11] M14 set_io dq[12] P15 set_io dq[13] N16 set_io dq[14] A15 set_io dq[15] A16 set_io dq[16] B1 set_io dq[17] B2 set_io dq[18] B3 set_io dq[19] B4 set_io dq[20] B5 set_io dq[21] B6 set_io dq[22] B7 set_io dq[23] B8 set_io dq[24] B9 set_io dq[25] B10 set_io dq[26] B11 set_io dq[27] B12 set_io dq[28] B13 set_io dq[29] B14 set_io dq[30] B15 set_io dq[31] B16 set_io di[0] C1 set_io di[1] C2 set_io di[2] C3 set_io di[3] C4 set_io di[4] C5 set_io di[5] C6 set_io di[6] C7 set_io di[7] C8 set_io di[8] C9 set_io di[9] C10 set_io di[10] C11 set_io di[11] C12 set_io di[12] C13 set_io di[13] C14 set_io di[14] D4 set_io di[15] C16 set_io s D1 


Alle drei Optionen funktionieren ordnungsgemĂ€ĂŸ und werden mit 0 an den EingĂ€ngen mit 16318 und mit 1 bei 16351 multipliziert. Gleichzeitig gibt yosys 488 Zellen fĂŒr die Schulversion, 206 fĂŒr die optimale Version und 202 fĂŒr die Variante mit gemeinsam genutzten Ressourcen an. Es optimiert, obwohl es immer noch einen Unterschied in 4 Zellen gibt. Wie Sie sehen können, ist der Unterschied zur Schuloption sehr anstĂ€ndig.

Na endlich. Vielleicht scheint es unnötig, dass jemand einen solchen Garten umzĂ€unt, nur um einfach zu erkennen, dass 16318 = 16384-64-2 und 16351 = 16384-32-1. ZunĂ€chst können die Zahlen jedoch komplizierter sein. Zweitens, wenn das GerĂ€t mehrere Zahlen multiplizieren muss, ist es nicht selbstverstĂ€ndlich, dass optimale Schemata gewĂ€hlt werden sollten. Ich hatte einfach GlĂŒck bei diesem Projekt. Im Allgemeinen kann ein Schaltungssuchprogramm viel helfen. Ich hoffe, der Artikel ist fĂŒr jemanden nĂŒtzlich. Und derjenige, der es liest, wird hoffentlich nicht in Panik geraten, wenn Sie multiplizieren mĂŒssen, aber es gibt keinen Multiplikator.

Source: https://habr.com/ru/post/de485786/


All Articles