الواجب الحسابي

Lyoshenka ، Lyoshenka ، هل لي معروفا!
تعلم ، Alyoshenka ، جدول الضرب!
أغنيا بارتو


المهمة الأولى للصف الأول. يتم إعطاء عدد موجب. تحتاج إلى ضرب به رقم آخر ، غير معروف مقدما. والسؤال هو ، كيف سينصح المشرفون النبيل بذلك؟ سيقول بالتأكيد مطور متمرس ، كما يقول الرجل ، وضع المضاعف ولا تقلق أدمغتي. وربما سيكون من الخطأ بشكل أساسي! إلى جانب الوحوش من Alterra و Xilinx ، هناك أيضًا عائلة رائعة مثل iCE-40 من Lattice . فائقة الصغر تستهلك. رخيصة جدا. نعم ، المشكلة هي أنها صغيرة بشكل مؤلم ، وللأسف ، لا توجد مضاعفات هناك. لقد صادفت هذا منذ حوالي 4 سنوات عندما قمت بتحويل برنامج ترميز ADPCM معين من المجمّع adsp-2185 إلى مثل هذا البلور.

لا ، من دون مضاعف للأغراض العامة (لاثنين من المتغيرات) هناك بالتأكيد لا يمكن القيام به. كان علي أن أجعلها مع الأقلام وأخذ نصف البلورة. المشكلة هي أنه درس في كل خطوة ، أي لا نوافذ على الإطلاق. وإلى جانب تكاثر المتغيرات في الخوارزمية ، كانت هناك معاملات ثابتة ، والتي كان لا بد من ضربها. ولم يكن هناك طريقة لاستخدام المضاعف لهذا ، لم يكن هناك نافذة متبقية. وبما أن الصراع في المشروع مر بكل خلية ، بالطبع كنت مهتمًا جدًا بكيفية تفاديها ، واستخدام خصائص هذه المعاملات يجعل المخطط الأمثل للضرب بها (ليس مضاعفًا للأغراض العامة ، ولكن جهاز للتضاعف من خلال رقم معين!). حسنًا ، مثل الحلم التام ، أصبح حقيقة - بحيث تحقق مخططات الضرب من خلال معاملات مختلفة الاستفادة القصوى من بعض الموارد البلورية الشائعة.

لذلك ، من مهمة الصف الأول ، انتقلنا بسلاسة إلى مهمة المهندس والرياضيات. كيفية بناء مخطط الضرب الأمثل لعدد معين معين؟

دعنا نتذكر قليلا كيف ضاعفنا عموما الرقم أ ب.

  1. بادئ ذي بدء ، اضبط النتيجة على صفر.
  2. دعنا نذهب أكثر من بت
  3. إذا كان في التفريغ 0 ، نحن لا نفعل شيئا.
  4. إذا كان في البتة 1 ، فإننا ننتقل إلى B بعدد البتات المقابل ونضيف إلى النتيجة.

الإجمالي ، كلما كانت الوحدات A أقل في الأرقام ، كلما كان ضربها أسهل. ضرب 2 أو 4 أو 8 أمر سهل. هناك حاجة فقط التحول. من الأصعب قليلاً ضرب 3 أو 5 أو 10. سوف يستغرق إضافة واحدة. حتى أصعب للتكاثر في 11. والمزيد من الوحدات ، وأصعب.

حسنا ، ماذا عن الضرب بـ 255؟ ما يصل إلى 8 وحدات ، مهمة كابوس ، أليس كذلك؟ وهنا التماثيل! دعونا نجعل خدعة صعبة مع آذاننا. اضرب B لدينا ب 256 (أي ، حوّلها إلى 8 أرقام) وطرحها من النتيجة. يبدو أنه على الرغم من المظهر الهائل ، فإن الضرب في 255 يكون سهلاً مثل الضرب في 10. كما أنه من السهل الضرب بـ 254 ، و 240 ، و 224 (إذا كنت تريد ، تحقق!).

في المجموع ، الطرح يساعد الضرب. تذكر هذه الفكرة القيمة. في هذه الأثناء ، ندعو صعوبة الرقم إلى الحد الأدنى لعدد عمليات الإضافة (أو الطرح) اللازمة للضرب به. لا تؤخذ التحولات في الاعتبار. لأنه في سياق المشكلة (لدينا دوائر ، وليس برمجة!) يتم الحصول عليها مقابل لا شيء. فلنضع بيانًا واضحًا ومفيدًا:

صعوبة عدد أقل من أو تساوي عدد الوحدات في الترميز الثنائي.
في الواقع ، إذا ضاعفنا بصدق دون حيل الطرح ، كما علمنا في المدرسة ، فإن عدد الإضافات سيكون مساوياً لعدد الوحدات في ثنائي أ. وإذا بدأنا بالخداع وإلى جانب ذلك ، فإننا محظوظون ، فسنخفض عدد العمليات.

نتيجة مثيرة للاهتمام لهذا البيان:
صعوبة أي رقم n-bit دائمًا أقل من n .
بعد كل شيء ، فإن أكبر عدد من الوحدات في عدد من الأرقام هو n ، لعدد مثل 255. من ناحية أخرى ، فمن الواضح أن التركيز ، كما هو الحال في الضرب في 255 ، يمكننا تكرار الأرقام بأية سعة. هذا يفتح آفاقا لتحسين مضاعفات للأغراض العامة.

دعونا نعطي المنطق لدينا نظرة أكثر انتظاما. بادئ ذي بدء ، دعونا بالفعل لدينا نوع من مخطط الضرب بواسطة أ. نحن نأخذ كوحدة. ثم تتحرك كل المصطلحات وتضيف وتطرح بطريقة تكون النتيجة هي أ. المجموع ، إن مخطط الضرب على A ليس أكثر من تمثيل للرقم A كمجموع من الصلاحيات لاثنين حيث يمكن أن تكون المصطلحات مع علامة + وعلامة - . ويمكنك تجميع المصطلحات الإيجابية والسلبية معًا ، والقول إن المخطط يوصف باختلاف بعض الأرقام A + و A- ، مساوًا لـ A. هذا أمر سيء ... يمكن أن يكون أعضاء الفرق كبيرًا بشكل تعسفي. دعونا نفكر إذا كان هناك أي اعتبارات للحد منها؟
بادئ ذي بدء ، نلاحظ أن كل قوة من اثنين يمكن أن تدخل الدائرة مرة واحدة فقط. في الواقع ، إذا دخلت مرتين بنفس العلامة ، فيمكن استبدالها بقوة اثنين بوحدة أكبر. إذا دخلت مرتين بعلامات مختلفة ، يتم طرحها بشكل متبادل. في المجموع ، يشبه المخطط للغاية التمثيل الثنائي المعتاد لـ A. الاختلاف الوحيد هو أن "البتات" (التي سنطلق عليها فيما يلي اسم " trits" ) لا يمكن أن تأخذ اثنتين ، لكن ثلاث قيم: 1 و 0 و -1.

المجموع. إذا كانت A عبارة عن رقم ثنائي بت n ، فسيتم وصف مخطط الضرب به بالمجموع:

A=tm2m+tm12m1+....+t12+t0


حيث ti- trits ، بأخذ القيم 1 و 0 و -1 ، و m هو عدد غير معروف.

في ما يلي ، سوف نسمي هذا التعبير مخططًا ثلاثيًا أو ببساطة مخططًا أو مخطط ضرب للرقم A.

دعونا نحاول العثور على م . كما يتضح من المثال مع الضرب في 255 ، m ليست بأي حال أقل من n . دعونا نرى ما إذا كان يمكن أن يكون مساويا ل n + 1 .
دع A ، كما كان من قبل ، يكون رقمًا رقميًا موجبًا. ثم يتم تعريف مخطط الضرب على النحو التالي:

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


أذكر ذلك 2k+2k1+....+2+1=2k+11
لذلك ، لا يمكن بأي حال من الأحوال أن يكون أعلى رقم يساوي -1. في الواقع ، حتى لو كان كل الآخرين 1 ، فسيظل المبلغ -1. وبحالة A هو إيجابي. الآن ، دع السمة العليا هي 1. لكن في هذه الحالة ، يجب أن تكون السمة التالية -1. خلاف ذلك ، فإن المبلغ سيكون كبير جدا. في الواقع ، إذا كان العدد التالي هو 0 ، فلن يكون المجموع أقل من 2n+1(2n1+...+1)=2n+1(2n1)=2n+1
بينما ن بت ليست أكثر 2n1دولا. ولكن إذا كان العدد العلوي هو 1 ، والثاني -1 ، فسيكون مجموع العضوين الرئيسيين 2n+12n=2n. وبالتالي فإن trit العلوي هو 0.

وبالتالي ، ثبت بيان مهم: م = ن .

بمعنى آخر ، لتمثيل أي مخطط للضرب بواسطة n- bit A ، فإن n + 1 تتمتع بقدرتان كافيتان - من 0 إلى n (واحدة أكثر من التمثيل الثنائي) ، مما يوفر لنا على الفور من اللانهاية.

يمكنك الآن محاولة حساب الصعوبات (انظر أعلاه) لأي أرقام محددة. أبسط شيء هو القيام بما نقوم به من خلال كتابة الأرقام الثنائية بالترتيب. أولاً فقط ، ليس لدينا هنا بعض البتات ، ولكننا نضع في الاعتبار (trites (ثلاث قيم ممكنة) ، وثانياً ، بعض توليفات trites تعطي أرقامًا سالبة ويجب التخلص منها ، ثالثًا ، يمكن أن تعطي بعض المجموعات أرقامًا متزامنة. هذا يعني أنه بالنسبة لهذا العدد ، هناك عدة مخططات.

سنكتب في الثعبان. ليس لأنني معجب به ، لكن لأنه مناسب جدًا للعمل معه في دفاتر jupyter. بادئ ذي بدء ، نكتب فئة TriScheme التي تعمل مع المخططات الثلاثية المقدمة أعلاه ، وظيفة allSchemes ، التي تحسب معها جميع المخططات للأرقام ذات حجم بت معين بواسطة تعداد بسيط ، ووظيفة printSchemes التي تقوم بطباعة النتيجة:

TriScheme
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) 


نحسب المخططات لجميع الأرقام ذات 4 بت:

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-]

يوجد هنا في بداية السطر رقم ، يليه صعوبة (الحد الأدنى لعدد العناصر غير الصفرية في الدائرة) ، ثم عدد الدوائر ، وأخيراً قائمة الدوائر.

في المخطط ، تشير + إلى 1 ، 0 - 0 ، و - - -1. البكر الأكبر على اليسار (كما في التهجئة المعتادة للأرقام).

يوضح الجدول ، أولاً ، أن الرقمين 13 و 11 فقط يواجهان صعوبة 3 (الحد الأقصى للأرقام المكونة من 4 بت ، كما هو موضح أعلاه). وثانيا ، أن عدد المخططات المختلفة لكل رقم كبير جدا. هذا يشير أولاً إلى أن الضرب هو في أغلب الأحيان عملية أبسط بكثير مما كنا نتعلمه في المدرسة. وثانياً ، بالنسبة لتطبيق أجهزة الضرب بعدة ثوابت باستخدام موارد بلورية شائعة ، فإن اختيار الدوائر كبير جدًا. أكثر إثارة للاهتمام هي البيانات على أرقام أطول. لذلك بالنسبة للأرقام 14 بت ، فإن الصعوبة القصوى هي 8. والحد الأقصى لعدد الدوائر هو 937.

كل شيء سيكون على ما يرام ، ولكن الخوارزمية المذكورة أعلاه مكلفة للغاية. التعقيد ينمو كما 3nاعتمادا على طول الأرقام ن . لمدة 8 أرقام التهم على الفور. لمدة 14 دقيقة. لمدة 16 ساعة. إذا كنت بحاجة إلى قراءة الدوائر من أجل جميع أرقام n ، للأسف ، لا يمكن القيام بأي شيء آخر سوى إعادة كتابتها إلى C وأخذ جهاز كمبيوتر أكثر قوة. ومع ذلك ، فإن الخوارزمية متوازية تمامًا ويمكن بالتأكيد تشغيلها على وحدة معالجة الرسومات أو على الكتلة.

لتصميم غدد معينة ، عادة ما تكون قوائم المخططات لأرقام محددة مطلوبة. وكل شيء مرغوب فيه ، وليس فقط الأمثل. قد يعتمد اختيار الشخص على الظروف (على سبيل المثال ، جهاز الضرب بعدة ثوابت). وهنا يمكنك تقديم خوارزمية أكثر إنسانية بكثير. مرة أخرى ، نتذكر المساواة الملحوظة: 2k+2k1+....+2+1=2k+11.

في سياق المهمة ، وهذا يعني ما يلي. لنفترض أن العديد من مخططات trit معروفة. جميع الأصناف البسيطة التي تبدأ من الموضع k غير معروفة وتعتبر سابقًا مساوية للصفر. بعد ذلك ، عند تغيير السمات غير المعروفة بأي طريقة ، سنقوم بتغيير قيمة الدائرة بما لا يزيد عن علامة زائد / ناقص 2k+11. علاوة على ذلك ، مع التقدم إلى المستويات الدنيا ، تقل قيمة عدم اليقين هذه. هذا يسمح لك بالبحث عن المخططات بتقريب متتالي ، trit بعد trit.

اسمحوا إعطاء عدد إيجابي أ . نحن بحاجة إلى إيجاد كل المخططات الخاصة به بين أرقام n . تسمى القيمة المطلقة للفرق بين A وقيمة دائرة معينة خطأ الدائرة. بادئ ذي بدء ، نأخذ مخطط n + 1- بت يصف أرقام n ، وكلها غير معروفة ويتم ضبطها في البداية على الصفر. ودعنا نبدأ في تحديد السمات ، واحدة تلو الأخرى ، بدءًا من أقدمها. في الموضع k ، يمكن للدائرة توليد ثلاثة أنماط جديدة - مع قيم للثلاثية 1 و 0 و -1. نترك في قائمة المخططات للاستمرار فقط تلك التي لا يتجاوز خطأها 2k1. مع قائمة الدوائر الناتجة ، دعنا ننتقل إلى الخطوة في الموضع k-1 . وبالتالي ، في القائمة الناتجة (في الموضع 0) سيكون هناك جميع المخططات الممكنة التي تكون قيمتها A. دعنا نكتب مثل هذه الوظيفة 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 


وأخيرا ، وعد بيع الأحلام.

في هذا المشروع ، كان هناك اثنين من المعاملات التي تحتاج إلى ضرب: 16351 و 16318. باستخدام calcSchemes ، نجد مخططات لهذه المعاملات:

مخططات
ل 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-

ل 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

نحن محظوظون! يواجه كلا العاملين صعوبة 3. نختار المخططات المثلى لكل من:
ل16318 + 0000000-0000-0 و 16351 - + 00000000-0000- . كنا محظوظين مرة أخرى! إيلاء الاهتمام لذيول المخططات. هم ل 16318 و 16351 تختلف فقط عن طريق التحول الأيسر من موقف واحد. وبالتالي فإن الجهاز الذي يتضاعف في 16318 و 16351 ، لا يتضمن سوى مُضاعِف إضافي واحد ، وهو تبديل المُعامل المُبدَّل وغير المُزَوَّد عند إدخال المُعلن.

دعنا نرى النتيجة. نكتب على veril ثلاثة خيارات لجهاز الضرب بحلول 16318 و 16351:

  1. خيار "المدرسة" (فقط الإضافات والتحولات)
  2. الدائرة المثلى
  3. مخطط الأمثل باستخدام الموارد المشتركة

بالنسبة إلى جميع الخيارات الثلاثة ، نقوم بإجراء التوليف ، ونرى عدد الموارد البلورية التي سيتم إنفاقها على كل منها.

فيريلوج
 /*----------------------- ----------------------*/ 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 


تعمل جميع الخيارات الثلاثة بشكل صحيح ، حيث تتضاعف عند 0 في المدخلات s بحلول عام 16318 ، وفي 1 في 16351. وفي الوقت نفسه ، تمنح yosys 488 خلية لإصدار المدرسة ، 206 للإصدار الأمثل ، و 202 للاختيار مع الموارد المشتركة. أنه يحسن ، على الرغم من أنه لا يزال هناك اختلاف في 4 خلايا. كما ترون ، فإن الفرق مع خيار المدرسة لائق جدًا.

حسنا اخيرا ربما ، قد لا يكون من الضروري أن يقوم شخص ما بسياج مثل هذه الحديقة ، فقط من أجل إدراك أن 16318 = 16384-64-2 ، و 16351 = 16384-32-1. ومع ذلك ، أولاً ، يمكن أن تكون الأرقام أكثر تعقيدًا. ثانياً ، إذا كان يجب على الجهاز ضرب عدة أرقام ، فمن غير الواضح أنه يجب أخذ المخططات المثلى. كنت محظوظا فقط في هذا المشروع. بشكل عام ، يمكن لبرنامج البحث عن الدوائر أن يساعد كثيرا. آمل أن تكون المقالة مفيدة لشخص ما. والشخص الذي قرأها ، آمل ألا يخاف إذا كنت بحاجة إلى الضرب ، لكن لا يوجد مضاعف.

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


All Articles