Devoirs arithmétiques

Lyoshenka, Lyoshenka, faites-moi une faveur!
Apprenez, Alyoshenka, la table de multiplication!
Agnia Barto


PremiĂšre tĂąche pour une premiĂšre niveleuse. Un nombre positif est donnĂ©. Vous devez multiplier par lui un autre nombre, inconnu Ă  l'avance. La question est, comment les nobles Dons conseilleront-ils de le faire ??? Un dĂ©veloppeur expĂ©rimentĂ© dira sĂ»rement, disent-ils l'homme, mettre le multiplicateur et ne vous inquiĂ©tez pas mon cerveau. Et peut-ĂȘtre que ce sera fondamentalement faux! En plus des monstres d'Alterra et de Xilinx, il y a aussi une famille aussi merveilleuse que l' iCE-40 de Lattice . Ultra micro consommant. TrĂšs bon marchĂ©. Oui, le problĂšme est qu'ils sont douloureusement petits et, hĂ©las, il n'y a pas de multiplicateurs lĂ -bas. Je l'ai rencontrĂ© il y a environ 4 ans lorsque j'ai portĂ© un certain codec ADPCM de l'assembleur adsp-2185 vers un tel cristal.

Non, sans multiplicateur Ă  usage gĂ©nĂ©ral (pour deux variables), cela n'aurait certainement pas pu ĂȘtre fait. J'ai dĂ» le faire avec des stylos et il a pris la moitiĂ© du cristal. Le problĂšme est qu'il a battu Ă  chaque pas, c'est-Ă -dire pas de fenĂȘtres du tout. Et en plus de la multiplication des variables dans l'algorithme, il y avait des coefficients fixes, qui devaient Ă©galement ĂȘtre multipliĂ©s. Et il n'y avait aucun moyen d'utiliser le multiplicateur pour cela, il n'y avait tout simplement plus de fenĂȘtre. Et puisque la lutte dans le projet a traversĂ© chaque cellule, bien sĂ»r, j'Ă©tais trĂšs intĂ©ressĂ© par la façon d'esquiver, et en utilisant les propriĂ©tĂ©s de ces coefficients, faites le schĂ©ma optimal de multiplication par eux (pas un multiplicateur Ă  usage gĂ©nĂ©ral, mais un dispositif pour multiplier par un nombre donnĂ©!). Eh bien, comme un rĂȘve complet devenu rĂ©alitĂ© - de sorte que les schĂ©mas de multiplication par diffĂ©rents coefficients tirent le meilleur parti de certaines ressources cristallines communes.

Ainsi, de la tùche de la premiÚre année, nous sommes passés doucement à la tùche de l'ingénieur et du mathématicien. Comment construire un schéma de multiplication optimal pour un nombre spécifique donné?

Rappelons un peu comment on multiplie généralement le nombre A par B.

  1. Pour commencer, mettez le résultat à zéro.
  2. Passons en revue les bits A.
  3. Si en décharge 0, on ne fait rien.
  4. Si dans le bit 1, nous décalons B du nombre de bits correspondant et ajoutons au résultat.

Au total, moins il y a d'unités A dans les chiffres, plus il est facile de le multiplier. La multiplication par 2, 4 ou 8 est facile. Seul un changement est nécessaire. Un peu plus difficile à multiplier par 3, 5 ou 10. Il faudra un ajout. Encore plus difficile à multiplier par 11. Plus il y a d'unités, plus c'est difficile.

Eh bien, qu'en est-il de multiplier par 255? Jusqu'à 8 unités, une tùche cauchemardesque, non? Et voici les figurines! Faisons une feinte délicate avec nos oreilles. Multipliez notre B par 256 (c'est-à-dire, décalez-le de 8 chiffres) et soustrayez-le du résultat. Il s'avÚre que malgré le look formidable, multiplier par 255 est aussi facile que multiplier par 10. Il est tout aussi facile de multiplier par 254, et par 240, et par 224 (si vous voulez, vérifiez!).

Au total, la soustraction aide à la multiplication. Rappelez-vous cette pensée précieuse. En attendant, nous appelons la difficulté d'un nombre le nombre minimum d'opérations d'addition (ou de soustraction) nécessaires pour le multiplier. Les décalages ne sont pas pris en compte. Car dans le contexte du problÚme (nous avons des circuits, pas de programmation!) Ils sont obtenus pour rien. Formulons une affirmation évidente mais utile:

La difficulté d'un nombre est inférieure ou égale au nombre d'unités dans sa notation binaire.
En fait, si nous multiplions honnĂȘtement sans astuces de soustraction, comme nous l'avons enseignĂ© Ă  l'Ă©cole, le nombre d'additions sera Ă©gal au nombre d'unitĂ©s en binaire A. Et si on commence Ă  tromper et d'ailleurs, on a de la chance, alors on va rĂ©duire le nombre d'opĂ©rations.

Une conséquence intéressante de cette affirmation:
La difficulté de tout nombre à n bits est toujours strictement inférieure à n .
AprÚs tout, le plus grand nombre d'unités dans un nombre à n chiffres est n , pour un nombre comme 255. D'un autre cÎté, il est clair que la mise au point, comme en multipliant par 255, nous pouvons répéter pour les nombres de n'importe quelle capacité. Cela ouvre des perspectives d'optimisation des multiplicateurs à usage général.

Donnons Ă  notre raisonnement un aspect plus rĂ©gulier. Pour commencer, ayons dĂ©jĂ  une sorte de schĂ©ma de multiplication par A. Nous prenons comme unitĂ©. Ensuite, tous les termes se dĂ©placent, s'additionnent et se soustraient de telle maniĂšre que le rĂ©sultat est le mĂȘme A. Au total, notre schĂ©ma de multiplication par A n'est rien d'autre qu'une reprĂ©sentation du nombre A sous la forme de la somme de puissances de deux dans laquelle les termes peuvent ĂȘtre Ă  la fois avec le signe + et avec le signe - . Et vous pouvez regrouper les termes positifs et nĂ©gatifs, et dire que le schĂ©ma est dĂ©crit par la diffĂ©rence de certains nombres A + et A- , Ă©gaux Ă  A. C'est mauvais ... Les membres de la diffĂ©rence peuvent ĂȘtre arbitrairement grands. Pensons s'il y a des considĂ©rations pour les limiter?
Tout d'abord, nous notons que chaque puissance de deux ne peut entrer dans le circuit qu'une seule fois. En fait, si elle entre deux fois avec le mĂȘme signe, celui-ci peut ĂȘtre remplacĂ© par une puissance de deux par une unitĂ© de plus. Si elle entre deux fois avec des signes diffĂ©rents, ils sont mutuellement soustraits. Au total, le schĂ©ma est trĂšs similaire Ă  la reprĂ©sentation binaire habituelle de A. La seule diffĂ©rence est que ses «bits» (ci-aprĂšs nous les appellerons trits ) peuvent prendre non pas deux, mais trois valeurs: 1, 0 et -1.

Total Si A est un nombre binaire à n bits, le schéma de multiplication par celui-ci est décrit par la somme:

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


oĂč ti- trits, prenant les valeurs 1, 0 et -1, et m est un nombre inconnu.

À l'avenir, nous appellerons une telle expression un schĂ©ma ternaire ou simplement un schĂ©ma ou un schĂ©ma de multiplication pour le nombre A.

Essayons de trouver m . Comme le montre l'exemple avec multiplication par 255, m n'est en aucun cas infĂ©rieur Ă  n . Voyons si elle peut ĂȘtre Ă©gale Ă  n + 1 .
Soit A, comme précédemment, un nombre positif à n chiffres. Ensuite, le schéma de multiplication est défini comme suit:

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


Rappelez-vous que 2k+2k−1+....+2+1=2k+1−1
Par consĂ©quent, le trit le plus Ă©levĂ© ne peut en aucun cas ĂȘtre Ă©gal Ă  -1. En effet, mĂȘme si tous les autres sont 1, la somme sera toujours -1. Et par la condition A est positive. Maintenant, laissez le trit supĂ©rieur ĂȘtre 1. Mais dans ce cas, le trit suivant devrait ĂȘtre -1. Sinon, le montant sera trop important. En fait, si le prochain trit est 0, la somme ne sera pas infĂ©rieure Ă  2n+1−(2n−1+...+1)=2n+1−(2n−1)=2n+1
Alors que n- bit A n'est pas plus 2 $ ^ n - 1 $ . Mais si le trit supĂ©rieur est 1, et le -1 suivant, alors la somme des deux membres supĂ©rieurs est 2n+1−2n=2n. Donc, le trit supĂ©rieur est 0.

Ainsi, une déclaration importante est prouvée: m = n .

En d'autres termes, pour représenter tout schéma de multiplication par un n- bit A , n + 1 puissances de deux suffisent - de 0 à n (un de plus que la représentation binaire), ce qui nous sauve immédiatement de l'infini.

Vous pouvez maintenant essayer de calculer les difficultĂ©s (voir ci-dessus) de tout nombre spĂ©cifique. La chose la plus simple est de faire ce que nous faisons en Ă©crivant des nombres binaires dans l'ordre. PremiĂšrement, nous n'avons pas de bits ici mais des trites (trois valeurs possibles), deuxiĂšmement, certaines combinaisons de trites donnent des nombres nĂ©gatifs et elles doivent ĂȘtre rejetĂ©es, troisiĂšmement, certaines combinaisons peuvent donner des nombres coĂŻncidents. Cela signifie que pour un tel nombre, il existe plusieurs rĂ©gimes.

Nous allons Ă©crire en python. Non pas parce que je suis tellement fan de lui, mais parce qu'il est extrĂȘmement pratique de travailler avec lui dans des cahiers jupyter. Pour commencer, nous Ă©crivons la classe TriScheme qui fonctionne avec les schĂ©mas ternaires prĂ©sentĂ©s ci-dessus, la fonction allSchemes, qui calcule avec elle tous les schĂ©mas de nombres d'une taille de bit donnĂ©e par une Ă©numĂ©ration simple, et la fonction printSchemes qui imprime le rĂ©sultat:

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) 


Nous calculons les schémas pour tous les nombres à 4 bits:

0 0 1 [00000]
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-]

Voici au début de la ligne un nombre, suivi de sa difficulté (le nombre minimum d'éléments non nuls dans le circuit), puis le nombre de circuits, et enfin une liste de circuits.

Dans le schéma, + désigne 1, 0 - 0 et - - -1. Le plus vieux trit sur la gauche (comme avec l'orthographe habituelle des nombres)

Le tableau montre tout d'abord que seuls les nombres 13 et 11 ont la difficultĂ© 3 (le maximum pour les nombres 4 bits, comme prouvĂ© ci-dessus). Et deuxiĂšmement, que le nombre de schĂ©mas diffĂ©rents pour chaque numĂ©ro est assez important. Cela suggĂšre, premiĂšrement, que la multiplication est le plus souvent l'opĂ©ration est beaucoup plus simple que ce qu'on nous a enseignĂ© Ă  l'Ă©cole. Et d'autre part, que pour la mise en Ɠuvre de dispositifs de multiplication par plusieurs constantes utilisant des ressources cristallines communes, le choix des circuits est assez large. Les donnĂ©es sur les nombres plus longs sont encore plus intĂ©ressantes. Ainsi, pour les nombres de 14 bits, la difficultĂ© maximale est de 8. Et le nombre maximal de circuits est de 937.

Tout irait bien, mais l'algorithme ci-dessus est trop cher. Sa complexitĂ© augmente Ă  mesure que 3 $ ^ n $ en fonction de la longueur des nombres n . Pour 8 chiffres compte instantanĂ©ment. Pendant 14 minutes. Pendant 16 heures. Si vous avez besoin de lire les circuits POUR TOUS les nombres de n bits, rien d'autre ne peut ĂȘtre fait que de le rĂ©Ă©crire en C et de prendre un ordinateur plus puissant. Cependant, l'algorithme est parfaitement parallĂ©lisĂ© et peut certainement ĂȘtre exĂ©cutĂ© sur le GPU ou sur le cluster.

Pour la conception de piĂšces de fer spĂ©cifiques, des listes de schĂ©mas pour des numĂ©ros spĂ©cifiques sont gĂ©nĂ©ralement requises. Et TOUT est souhaitable, et pas seulement optimal. Pour lequel choisir peut dĂ©pendre des circonstances (par exemple, un dispositif pour multiplier par plusieurs constantes). Et ici, vous pouvez proposer un algorithme beaucoup plus humain. Encore une fois, nous rappelons la remarquable Ă©galitĂ©: 2k+2k−1+....+2+1=2k+1−1.

Dans le contexte de la tĂąche, cela signifie ce qui suit. Supposons que plusieurs schĂ©mas trit supĂ©rieurs soient connus. Tous les trits mineurs commençant Ă  la position k sont inconnus et sont auparavant considĂ©rĂ©s comme Ă©gaux Ă  zĂ©ro. Ensuite, en changeant les trits inconnus de quelque façon que ce soit, nous changerons la valeur du circuit de plus / moins 2k+1−1. De plus, avec l'avancement vers les trits infĂ©rieurs, la valeur de cette incertitude diminue. Cela vous permet de rechercher des schĂ©mas par approximations successives, trit aprĂšs trit.

Soit un nombre positif A. Nous devons trouver tous les schĂ©mas pour cela parmi les nombres Ă  n bits. La valeur absolue de la diffĂ©rence entre A et la valeur d'un certain circuit est appelĂ©e l' erreur du circuit. Pour commencer, nous prenons un schĂ©ma n + 1- bits dĂ©crivant des nombres Ă  n bits, tous inconnus et initialement dĂ©finis comme Ă©tant nuls. Et commençons Ă  dĂ©finir les trits, un par un, en commençant par l'ancien. En position k- Ăšme, le circuit peut gĂ©nĂ©rer trois nouveaux motifs - avec des valeurs de k-trit 1, 0 et -1. Nous ne laissons dans la liste des rĂ©gimes de continuation que ceux d'entre eux dont l'erreur ne dĂ©passe pas 2 $ ^ k-1 $ . Avec la liste de circuits rĂ©sultante, passons Ă  l'Ă©tape Ă  la position k-1 . Ainsi, dans la liste rĂ©sultante (Ă  la position 0), il y aura TOUS les schĂ©mas possibles dont la valeur est A. Écrivons une telle fonction 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 


Et enfin, la vente promise des rĂȘves.

Dans ce projet, il y avait deux coefficients à multiplier: 16351 et 16318. En utilisant calcSchemes, nous trouvons les schémas de ces coefficients:

Schémas
Pour 16351
0 ++++++++ 0 +++++
0 +++++++++ - ++++
0 +++++++++ 0 - +++
0 +++++++++ 00 - ++
0 ++++++++++ 000- +
0 +++++++++ 0000-
+ - +++++++ 0 +++++
+ - ++++++++ - ++++
+ - ++++++++ 0 - +++
+ - ++++++++ 00 - ++
+ - +++++++++ 000- +
+ - +++++++++ 0000-
+0 - ++++++ 0 +++++
+0 - +++++++ - ++++
+0 - +++++++ 0 - +++
+0 - +++++++ 00 - ++
+0 - ++++++++ 000- +
+0 - +++++++ 0000-
+00 - +++++ 0 +++++
+00 - ++++++ - ++++
+00 - ++++++ 0 - +++
+00 - ++++++ 00 - ++
+00 - ++++++ 000- +
+00 - ++++++ 0000-
+000 - ++++ 0 +++++
+000 - +++++ - ++++
+000 - +++++ 0 - +++
+000 - +++++ 00 - ++
+000 - +++++ 000- +
+000 - +++++ 0000-
+0000 - +++ 0 +++++
+0000 - ++++ - ++++
+0000 - ++++ 0 - +++
+0000 - ++++ 00 - ++
+0000 - ++++ 000- +
+0000 - ++++ 0000-
+00000 - ++ 0 +++++
+00000 - +++ - ++++
+00000 - +++ 0 - +++
+00000 - +++ 00 - ++
+00000 - +++ 000- +
+00000 - +++ 0000-
+ 000000- + 0 +++++
+000000 - ++ - ++++
+000000 - ++ 0 - +++
+000000 - ++ 00 - ++
+000000 - ++ 000- +
+000000 - ++ 0000-
+ 0000000-0 +++++
+0000000 - + - ++++
+ 0000000- + 0 - +++
+ 0000000- + 00 - ++
+ 0000000- + 000- +
+ 0000000- + 0000-
+00000000 - ++++
+ 00000000-0 - +++
+ 00000000-00 - ++
+ 00000000-000- +
+ 00000000-0000-

Pour 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

Nous avons de la chance! Les deux facteurs ont des difficultés 3. Nous choisissons les schémas optimaux pour les deux:
Pour 16318 + 0000000-0000-0 et pour 16351 - + 00000000-0000- . Nous avons encore eu de la chance! Faites attention aux queues des régimes. Ils pour 16318 et 16351 ne diffÚrent que par un décalage à gauche d'une position. Ainsi, le dispositif multipliant par 16318 et 16351, ne comprend qu'un seul multiplexeur supplémentaire, commutant l'opérande décalé et non décalé à l'entrée de l'additionneur.

Voyons le résultat. Nous écrivons au veril trois options pour le dispositif de multiplication par 16318 et 16351:

  1. Option «école» (uniquement les ajouts et les quarts)
  2. Circuit optimal
  3. Schéma optimal utilisant des ressources partagées

Pour les trois options, nous effectuons la synthÚse et voyons combien de ressources cristallines seront dépensées pour chacune d'entre elles.

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 


Les trois options fonctionnent correctement, en multipliant Ă  0 Ă  l'entrĂ©e s par 16318 et Ă  1 Ă  16351. En mĂȘme temps, yosys donne 488 cellules pour la version scolaire, 206 pour la version optimale et 202 pour la variante avec des ressources partagĂ©es. il optimise, bien qu'il y ait encore une diffĂ©rence dans 4 cellules. Comme vous pouvez le voir, la diffĂ©rence avec l'option scolaire est trĂšs dĂ©cente.

Enfin, enfin. Peut-ĂȘtre, il semblerait inutile que quelqu'un clĂŽture un tel jardin, uniquement pour rĂ©aliser simplement que 16318 = 16384-64-2 et 16351 = 16384-32-1. Cependant, premiĂšrement, les chiffres peuvent ĂȘtre plus compliquĂ©s. DeuxiĂšmement, si l'appareil doit multiplier plusieurs nombres, il est loin d'ĂȘtre Ă©vident que des schĂ©mas optimaux doivent ĂȘtre pris. J'ai juste eu de la chance dans ce projet. En gĂ©nĂ©ral, un programme de recherche de circuits peut ĂȘtre trĂšs utile. J'espĂšre que l'article est utile Ă  quelqu'un. Et celui qui l'a lu, j'espĂšre ne paniquera pas si vous avez besoin de vous multiplier, mais il n'y a pas de multiplicateur.

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


All Articles