مدخل إلى محاكاة تصميمات الهاردوير

عام 0 geek4arab
Spread the love

بدأنا في الدرس السابق بعمل مثال بسيط بلغة الـ VHDL و هو وحدة المعالجة و المنطق Arithmetic Logic Unit – ALU و قد قمنا بإستعراض بعض الأشياء التي تظهر في التقرير الذي يخرجه لنا برنامج الـ Xilinx ISE Webpack عن التصميم الذي قمنا به من مساحة و التأخير الذي يستغرقه و الطاقة المستهلكة و غير ذلك .. و قد أجلنا الكلام عن محاكاة التصميم إلى هذا الدرس

تخيل أنك بيدك الآن دائرة تكاملية Integrated Circuit تقوم بإختبارها .. ستقوم أولاً بتوصيلها مثلاً على لوحة إختبار Bread Board .. ربما تقوم بتوصيل بعض الدوائر التكاملية الأخرى أو لا تقوم بذلك حسب الإختبار الذي تريده .. ربما نجد معك أيضاً أثناء الإختبار جهاز راسم الإشارات Oscilloscope  لتشاهد الإشارات الداخلة و الخارجة .. و ربما يكون بجانبك ورقة تكتب فيها ملاحظاتك و قياساتك .. و سوف نسمي هذا كله مقعد الإختبار Test Bench .. تذكر أننا في الدرس الأول و الثاني شددنا على مفهوم أن اللغات الوصفية و التي منها لغة الـ VHDL لا تخاطب الهاردوير و إنما تخاطب الذي سيقوم بتصميم الهاردوير .. و بما أننا في هذه المرة لن نقوم بتصميم الهاردوير و إنما سنقوم بإختبار الهاردوير .. فسوف نحتاج أيضاً إلى لغة وصفية تصف للرجل الجالس على مقعد الإختبار Test Bench ماذا سيفعل بالضبط لكي يقوم بإختباره .. فسوف نصف له كيف سنقوم بتركيب الدوائر التكاملية التي صممناها (مثل وحدة المعالجة و المنطق في الدرس السابق) و نصف له أين يقوم بتوصيلها و هل سيقوم بتوصيل بعض الدوائر الأخرى أم لا و هكذا .. ثم نصف له بعد ذلك خطوات التجربة .. هل سيقوم مثلاً بإدخال بعض المدخلات لوحدة المعالجة و المنطق ثم يقوم بإختبار هل النتيجة ستخرج كما ينبغي أم لا و ما هي الأشياء التي سوف يجربها و كيف سيتصرف عند رؤية أي مخرج من المخرجات و هكذا .. في قائمة Hierarchy التي في أيمن الشاشة قم بتحديد الملف الذي وضعت فيه كود وحدة المعالجة و المنطق ALU و إضغط عليه بالزر الأيمن و إختر New Source ثم قم بتحديد VHDL TestBench : و قم بتسمية الملف الجديد بأي شئ ثم إضغط Next حيث ستقوم بإختيار الوحدة التي تريد أن تقوم بعمل محاكاة و إختبار لها .. قم بتحديد الملف الذي تريد محاكاته .. و في هذه الحالة ليس لدينا إلا ملف واحد فقط و وحدة واحدة فقط و هي وحدة المعالجة و المنطق .. إضغط Next ثم إضغط Finish .. سيفتح لك صفحة بها بعضاً من كود الـ VHDL به المحاور الآتية .. أولاً إعتبر نفسك تتعامل مع لوحة إختبار Bread Board .. ستقوم بوضع الدائرة التكاملية Integrated Circuit التي قمت بتصميمها في لوحة الإختبار ثم تقوم بتوصيل بعض الأسلاك على الأرجل التي تريد أن تختبرها في الدائرة التكاملية .. ثم ستقوم بالتعامل مع تلك الأسلاك و التي ستقوم بتوصيلها على بعض الأقفال لكي تدخل عن طريقها البيانات و تضع المخرجات على جهاز راسم للإشارات Oscilloscope أو على بعضاً من الديودات المضيئة LEDs .. هذا بالضبط الذي سوف تفعله في الكود الوصفي لعملية الإختبار و المحاكاة .. ستقوم بإستخدام الوحدة التي تريدها ليس عن طريق تكوينها الداخلي و إنما ستسخدمها و تختبرها على أنها مكون بداخل دائرة و التي شبهناها بلوحة الإختبار .. إنظر إلى الكود التالي :

ENTITY ALU_Simulation IS

END ALU_Simulation;

هنا قمنا بتعريف وحدة فارغة على أنها لوحة الإختبار .. و قد جرى العرف ان لوحة الإختبار ليس لها مدخلات و مخرجات .. و سنقوم بوضع الوحدة المراد إختبارها بداخل هذه الوحدة الفارغة أو لوحة الإختبار ..

ARCHITECTURE behavior OF ALU_Simulation IS

COMPONENT ALU

PORT( A : IN  std_logic_vector(31 downto 0);

B : IN  std_logic_vector(31 downto 0);

ALU_OUT : OUT  std_logic_vector(31 downto 0);

Control : IN  std_logic_vector(2 downto 0));

END COMPONENT;

signal A : std_logic_vector(31 downto 0);

signal B : std_logic_vector(31 downto 0);

signal Control : std_logic_vector(2 downto 0);

signal ALU_OUT : std_logic_vector(31 downto 0);

BEGIN

هنا قمنا بتعريف التكوين الداخلي Architecture للوحة الإختبار .. فقلنا Architecture ثم أتبعناها بإسم التكوين الداخلي و الذي جرى العرف على أن يكون Behavioral في وصف التصاميم و Behavior في وصف المحاكاة و الإختبار ..  ثم قلنا Of و أتبعناها بإسم الوحدة التي سننسب هذا التكوين لها ثم كلمة Is .. و بين كلمة Is و كلمة Begin نضع التعريفات التي سنستخدمها في الكود .. قد نقوم بتعريف بعض الأسلاك مثلاً .. و يكون كل سلك له إسم يدل عليه .. قد نقوم بتعريف دائرة تكاملية Integrated Circuit و نقوم بإستخدامها في الكود .. قد نقوم بتعريف سلسلة حرفية String حيث سنقوم بكتابة فيها تقريراً عن الإختبار الذي سنقوم به .. قد نقوم بتعريف متغير من نضع فيه الوقت من نوع Time حيث سنضع فيه مثلاً الوقت الذي سنقوم بحسابه في أي شئ مثلاً أثناء الإختبار .. و سوف نقوم بمناقشة هذه الأشياء و هذه الأنواع من المتغيرات و كيفية إستخدامها لاحقاً إن شاء الله ..

و في هذا المثال قمنا بتعريف مكون Component إسمه ALU و الذي هو إسم الوحدة التي سنقوم بإختبارها (التي قمنا بتصميمها في الدرس السابق) .. و قمنا بكتابة بيانات مداخلها و مخارجها بنفس الطريقة التي قمنا بكتابتها عندما كنا نقوم بتعريف Entity .. و لكن بدلاً من كتابة كلمة Entity قمنا بكتابة كلمة Component و في النهاية كتبنا كلمة End Component و ليس End ALU ..

و بعدما قمنا بتعريف بعض الأسلاك  .. أو بمعنى أدق قمنا بتعريف بعض الإشارات .. السلك الأول إسمه A و هو في الواقع عبارة عن 32 سلكاً و لهذا قلنا أنه STD_LOGIC_VECTOR .. و كذلك بقية الأسلاك و التي هي في الواقع كل المخارج و المداخل للدائرة التكاملية لوحدة المعالجة و المنطق ALU .. حيث أن الإشارة A سوف نقوم بتوصيلها على المدخل A للدائرة التكاملية .. و كذلك بقية المداخل و المخارج ..

بعد كلمة Begin سنبدأ في وصف ما الذي سيفعله الرجل الجالس على مقعد الإختبار كما سنقوم بوصف دائرة الإختبار (و التي في هذه الحالة ليست إلا الدائرة التكاملية التي نريد إختبارها و الأسلاك موصلة على كل مداخلها و مخارجها) .. إنظر إلى هذا الكود :

Instance_ALU : ALU PORT MAP (

A => A,

B => B,

ALU_OUT => ALU_OUT,

Control => Control);

هنا قمنا بوضع الدائرة التكاملية التي قمنا بتعريفها كمكون Component في الأعلى قبل Begin .. الفرق بين تعريفها و وضعها في اللوحة هو كما لو قلت لك أن هناك شئ إسمه OpAmp و قمت بتعريفه لك مرة واحدة ثم وضعت عدة نسخ منه في دائرة معينة .. ففي التعريف نقوم فقط بتعريفه و تعريف مداخله و مخارجه و نذكره بين is و Begin .. و أما في وضعه في الدائرة فلن نذكر عن مداخله و مخارجه أية معلومات بل سنذكر فقط الأسلاك التي قمنا بتوصيلها بهذه المداخل أو هذه المخارج .. و بالطبع بما أننا قد نضع من هذه الدائرة التكاملية أكثر من واحدة في التصميم الواحد فإنه يفضل أن نقوم بوضع إسم لكل نسخة Instance .. و هنا قد إخترنا إسم Instance_ALU .. ثم أتبعناها بالرمز “:” ثم إسم الدائرة التكاملية ثم PORT MAP و نقوم بفتح قوس .. و بعد إغلاق القوس نقوم بوضع فاصلة منقوطة .. و بين القوسين نقوم بربط كل مدخل أو مخرج من مداخل و مخارج الدائرة التكاملية بسلكٍ من الأسلاك .. فقمنا بالربط المدخل A بالسلك A (الإسم هنا لا يدل على أي شئ .. يمكنك الربط بين المدخل A و بين السلك H مثلاً) .. و نذكر على اليسار إسم المدخل أو المخرج ثم علامة السهم ثم إسم السلك و بعدها نقوم بوضع فاصلة ..

و بعد أن قمنا بوصف دائرة الإختبار سنقوم بوصف خطوات الإختبار .. عندما نريد أن نضع خطوات متتابعة أو أي شئ له علاقة بالوقت فإننا نضعها في ما يسمى بالـ Process .. إنظر إلى هذا الكود :

stim_proc: process

begin

A <= x”12345678″;

B <= x”87654321″;

Control <= “000”;

wait for 20 ns;

Control <= “001”;

wait for 20 ns;

Control <= “010”;

wait for 20 ns;

Control <= “011”;

wait for 20 ns;

Control <= “100”;

wait for 20 ns;

Control <= “101”;

wait for 20 ns;

Control <= “110”;

wait for 20 ns;

Control <= “111”;

wait;

end process;

END Behavior;

عند تعريف تلك العملية Process قمنا بتسميتها بإسم stim_proc الذي قد جرى العرف على تسمية عمليات الإختبار به .. ثم كلمة process ثم كلمة begin .. و بين begin و end process ذكرنا خطوات الإختبار .. في البداية عند الزمن صفر قمنا بإدخال القيمة 12345678 (و هي قيمة ست عشرية Hexadecimal) على الإشارة A (و التي هي الأسلاك الموصلة على المدخل A في الدائرة التكاملية) .. و أدخلنا القيمة 87654321 على B .. ثم أدخلنا قيمة 000 إلى الإشارة Control و التي ستحدد العملية الحسابية التي ستقوم بها وحدة المعالجة و المنطق .. ثم إنتظرنا لمدة 20 نانوثانية  حيث قلنا wait for ثم أتبعناها ببعض الوقت .. و بعد هذه الفترة الزمنية سوف نقوم بتغيير العملية الحسابية ثم ننتظر نفس المدة حتى نجرب كل العمليات الحسابية .. و بعد أن ننتهى من العملية نقول wait ثم end process .. و بعد أن ننتهي من وصف العملية و وصف كل شئ نقوم بإغلاق التكوين الداخلي فنقول End Behavior ..

و بالطبع لا تنسى أن تضع في بداية الكود المكتبات التي قمت بإستخدامها .. فبما أننا قد إستخدمنا الـ STD_LOGIC_VECTOR فإننا نحتاج إلى تلك المكتبة :

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

بعد  أن ننتهي من كتابة الكود نقوم الآن بتشغيله لكي تظهر أمامنا بيانات المخرجات التي ستخرج أثناء المحاكاة .. في الواقع فإنه يوجد أربعة أنواع أساسية من المحاكاة Simulation .. النوع الأول هو إختبار الوظيفي للتصميم Functional Test .. في هذا النوع من الإختبار لا يهمنا كم من الوقت سيستغرق التصميم لكي يخرج المخرجات بالشكل الصحيح و لكن كل الذي يهمنا هو ما المخرجات التي سيخرجها .. يسمى هذا النوع من الإختبارات Behavioral Simulation .. و يوجد نوع أخر من المحاكاة تظهر فيه المدة التي تأخذها الدائرة لكي تثبت المخرجات على الشكل الصحيح و هي مثل Post Map و Post Place and Rout و سوف نتحدث عنهم بشئ من التفصيل لاحقاً إن شاء الله .. و الآن لبدأ المحاكاة إنظر إلى هذه الصورة :

للذهاب إلى وضعية المحاكاة ستجد في الأعلى بجانب كلمة View خيارين .. إما وضعية التصميم Implementation و إما وضعية المحاكاة Simulation .. إختر وضعية المحاكاة .. و تحتها مباشرةً ستجد خيارات نوع المحاكاة و هي Behavioral و Post Translate و Post Map و Post Place And Rout .. قم بتحديد Behavioral و قم بتحديد الملف الذي به كود المحاكاة و الذي أسميناه هنا ALU_Simulation.vhd .. ثم إضغط على Simulate Behavioral Model من قائمة Processes .. سيظهر لك مثل هذا :

هنا ستجد رسم لإشارة كل الاسلاك التي قمت بوضعها في لوحة الإختبار .. في الأعلى ستجد خط به بيانات الزمن .. ستجد أنه كلما مر 20 نانوثانية تتغير قيمة الـ Control فتتغير معها قيمة الإشارة الخارجة من ALU_OUT .. يمكنك أن تعرض البيانات على أنها أرقام ثنائية Binary أو أرقام عشرية Decimal أو ست عشرية Hexadecimal عن طريق الضغط بالزر الأيمن على أسماء الإشارات التي على اليسار و إختيار Radix ثم تحديد الطريقة التي تريد أن تعرض بها البيانات ..

لاحظ هنا أننا في المحاكاة لم تظهر لنا أي تأخير في إخراج النتيجة .. فعندما كان يتغير قيمة أي مدخل فإن قيمة المخرج تتغير الحال .. و هذا كلام غير صحيح في الواقع .. فهذا النوع من المحاكاة أو الإختبار فقط يخبرنا عن المخرجات حتى نتأكد أنها ستخرج بالشكل الذي كنا نتوقعه و لكنها لا تخبرنا بأي تفاصيل أخرى .. و لكي تقوم بإظهار ما يتعلق بالتزامن و التأخير نقوم بإستخدام ما يسمى بالـ Post Map Simulation أحياناً أو Post Rout Simulation أحياناً أخرى .. و سوف نذكر تفاصيل هذا إن شاء الله في دروس قادمة ..

الكاتب geek4arab

geek4arab

مواضيع متعلقة

التعليقات مغلقة