علوم البرمجة

ما هي لغات توصيف العتاد Hardware Description Languages

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

هنا يبرز نمطٌ آخر من اللغات المخصصة لأداء وظيفةٍ مغايرة: بدلًا من توصيف الخوارزمية المطلوبة فقط يجب أيضًا توصيف العتاد الذي سيقوم بتشغيل هذه الخوارزمية، أي أن تنفيذ البرنامج سيتضمن تشكيل عتادٍ معين يقوم بأداء المهمة المطلوبة. هذا النمط من اللغات هو ما يُعرف اليوم باسم “لغات توصيف العتاد Hardware Description Languages” المستخدمة على نطاقٍ واسع في مجال اصطناع المنطق الرقميّ Digital Logic Synthesis في الأجهزة الرقمية القابلة للبرمجة، خصوصًا المصفوفات الحقلية القابلة للبرمجة FPGAs.

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

تعريف لغات توصيف العتاد Definition of HDLs

لغات توصيف العتاد هي نمطٌ متخصص من لغات البرمجة والمستخدمة من أجل وصف بنية Structure وسلوك Behavior الدارات الإلكترونية وبشكلٍ خاص الدارات الرقمية. تنتمي لغات توصيف العتاد إلى نموذج البرمجة التزامنية Concurrent Programming، حيث تتيح هذه اللغات وصف الخصائص الزمنية للدارات الرقمية المراد إنشاؤها، كما أنها تتيح تنفيذًا تفرعيًا Parallel Execution لعدة وحدات Modules مع بعضها البعض بنفس الوقت ضمن نفس الشيفرة المصدرية.

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

من ناحية النص Syntax، تتشابه معظم لغات توصيف العتاد مع لغات البرمجة عالية المستوى، خصوصًا لغات C و ++C وجافا، كما أنها الأجيال الحديثة منها (مثل لغة SystemVerilog) تمتلك العديد من خصائص لغات البرمجة غرضية التوجه، مثل القدرة على إنشاء الصفوف Classes والأغراض التابعة لها.

تطور لغات توصيف العتاد Development of HDLs

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

خلال سبعينات القرن الماضي ظهرت النماذج الأولى للغات توصيف العتاد والمفاهيم المتعلقة بها، ومن الأمثلة الشهيرة هي معيار ISP الذي أتاح وصف العلاقة بين مداخل ومخارج تصميمٍ ما اعتمادًا على مفهوم “مستوى تبادل المسجل RTL: Register Transfer Level”. من الأمثلة الشهيرة الأخرى في تلك الحقبة هي لغة KARL المطورة بجامعة كايزرسلاوترن الألمانية والتي نتج عنها ظهور لغة التطوير المرئية ABL: A Block Diagram Language.

بكل الأحوال، ومع انتقال الصناعة الإلكترونية للاعتماد على مفهوم VLSI: Very Large Scale Integration ظهرت لغاتٌ أخرى والتي كان أولها لغة Verilog سنة 1985، وبعد ذلك بسنتين، ظهرت لغة VHDL، وخلال سنواتٍ عدة أصبحت تسيدت هذه اللغات عالم برمجة توصيف العتاد وأصبحت اللغات والمعايير الأقدم شبه مهملة، وأدى الاستثمار الكبير بهذه اللغات إلى تحوّلها لمعايير معتمدة، فلغة Verilog موصوفة عبر المعيار IEEE 1364، وكذلك لغة SystemVerilog التي ينظر لها على أنها النسخة الأشمل والأوسع من Verilog، فهي موصوفة باستخدام المعيار IEEE 1800. بالنسبة للغة VHDL فهي موصوفة تحت المعيار IEEE 1076.

بنية لغات توصيف العتاد Structure of HDLs

تهدف لغات توصيف العتاد بشكلٍ أساسيّ إلى كتابة نصٍ برمجيّ ينتج عنه تشكيل دارةٍ إلكترونية، ولذلك فإنها تعتمد في جوهرها على مفهوم تقسيم البرنامج إلى وحداتٍ مختلفة، بحيث يمكن داخل كل وحدة تشكيل دارة إلكترونية أو مجموعة من الدارات الإلكترونية، وبذلك، يمكن لكل وحدة أن تكون بوابة منطقية بسيطة مثل بوابة الضرب المنطقيّ AND أو يمكنها أن تكون وحدة ذاكرة عشوائية، أو دارة ضرب، أو مسجل إزاحة، أو حتى وحدة معالجة متكاملة. يُطلق على هذه الوحدات اسم “Modules” في لغة Verilog بينما تُعرف باسم “الكيانات Entities” في لغة VHDL.

بشكلٍ أساسيّ، تتميز كل وحدة (أو كيان) بالخصائص التالية:

  • اسم Name
  • لائحة إشارات الدخل والخرج Input/Output Signals List
  • بنية الوحدة (الوظيفة التي ستقوم بها) Module Structure
  • محددات بداية ونهاية الوحدة

وظيفة أي وحدة/كيان هو وصف أمرين أساسيين:

  • السلوك Behavior: أي كيف الطريقة والمنهجية المتبعة لإنجاز الوظيفة المطلوبة.
  • البنية Structure: أي الدارة الإلكترونية التي ستقوم بتنفيذ الوظيفة المطلوبة.

لو أخذنا مثالًا بسيطًا يوّضح الفكرة السابقة، أي كيفية كتابة برنامجٍ بإحدى لغات توصيف العتاد والذي يتضمن وصفًا للسلوك وهيكلية الدارة، فإنه بالإمكان إجراء ذلك عبر برنامجٍ يهدف لإنجاز عملية الضرب المنطقيّ AND لعددين منطقيين كل منهما بدقة 1-بت وسيكون الخرج أيضًا بدقة 1-بت.

قبل طرح المثال، يجب توضيح نقطة هامة تتعلق بلغات توصيف العتاد، وهي قدرتها على التمييز بين النمطين الأساسيين من أنماط المنطق الرقميّ، وهنا نعني:

  • المنطقي التركيبيّ (التجميعي) Combinational Logic
  • المنطق التسلسليّ Sequential Logic

بعالم الدارات المنطقية، يقصد بالمنطق التركيبيّ كافة الدارات المنطقية التي تقوم بإنجاز عملياتٍ غير متزامنة والتي لا تتضمن أي نوعٍ من أنواع حفظ المعطيات ضمن الذواكر، وهذا يعني أن أي دارةٍ منطقية خرجها الحاليّ يعتمد على دخلها الحاليّ فقط تصنف على أنها دارة تركيبية Combinational Circuit. بالنسبة للمنطق التسلسليّ، فهو يصف الدارات المنطقية التي تأخذ بعين الاعتبار الإشارات الزمنية، بحيث قد يكون خرج الدارة الحاليّ هو الدخل السابق (كمثال)، كما أنها تصف الدارات المنطقية القادرة على حفظ المعلومات بما يُساهم بتشكيل وحدات الذواكر. أبسط أنماط دارات المنطق التسلسليّ هو القلابات Flip-Flops المستخدمة كبنيةٍ أساسية لتشكيل المُسجلات Registers ووحدات الذواكر.

توفر لغات توصيف العتاد أدواتٍ للمبرمجين ليكونوا قادرين على إنشاء داراتٍ إلكترونية تتبع لأحد النمطين، وعند تحليل النص المكتوب، ستتمكن بيئة البرمجة المستخدمة IDE من معرفة نوع الدارة المطلوب إنشاؤها وفيما لو كانت تركيبية أو تسلسلية.

بالعودة للبنة الأساسية في لغات توصيف العتاد، أي الوحدة/الكيان، فإنه يمكن توضيح كيفية عملها عبر أخذ مثالٍ بسيطٍ يهدف لتشكيل دارة ضرب منطقي AND لعددين كل منهما بدقة 1-بت والتي تشكل دارةٍ تركيبية بسيطة كونها لا تتضمن أي اعتباراتٍ زمنية والعلاقة بين خرج ودخل الدارة هي علاقة آنية. الصورة التالية توضح كيفية كتابة نص برمجي لإنشاء هكذا دارة باستخدام لغة Verilog والأجزاء المختلفة التي تتكون منها الوحدة Module:

كملاحظاتٍ سريعة على النص البرمجيّ البسيط السابق، فإن أول ما ستتم ملاحظته هو أن لغة Verilog تتيح للمستخدمين تحديد نوع الإشارات التي ستدخل للوحدة (أي دخل أو خرج) وكذلك طبيعتها المنطقية، أي إذا كانت إشارات مرتبطة بالزمن أو لا. الكلمة المفتاحية wire تعني أن هنالك ناقلًا يقوم بتوصيل هذه الإشارة إلى الوحدة. أخيرًا، الوظيفة المطلوبة إنشاؤها هي عملية ضرب منطقي للإشارتين data_a و data_b ومن ثم حفظ الناتج بإشارة الخرج result، وهو ما يتحقق عبر استخدام التصريح assign ورمز إشارة الضرب المنطقيّ، أي الرمز &. هذه الرموز والتصريحات ستجعل بيئة البرمجة قادرة على فهم طبيعة الدارة المطلوب تشكيلها وبالتالي سيتم تشكيل الملف الوصفي الذي سيؤدي بدوره لإنشاء الدارة المنطقية المنفذة للوظيفة الموصوفة بالنص البرمجيّ.

ماذا عن الإشارات الزمنية والمنطق التسلسليّ؟ لنعد للدارة البسيطة السابقة التي قمنا بتشكيلها، ولنقل أننا نريد الحصول على خرج هذه الدارة بشكلٍ متزامن، أي أننا نريد الحصول على الخرج عند كل نبضة من نبضات الساعة. هذا الأمر يمكن أن يتم بسهولة عبر إضافة تصريحات للنص السابق تساهم بتشكيل مسجلٍ بسيط دخله هو عبارة عن ناتج عملية الضرب المنطقيّ وخرجه هو أيضًا ناتج عملية الضرب، ولكنه لن يكون آنيًا، بل أن الخرج الحالي للمسجل هو الخرج السابق لدارة الضرب المنطقيّ. الصورة التالية توضّح كيفية إنشاء مثل هكذا دارة باستخدام لغة Verilog:

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

البرمجة المتزامنة Concurrent Programming

ذكرنا سابقًا أن لغات توصيف العتاد تتميز عن باقي لغات البرمجة بكونها تتيح وصف الأحداث من الناحية الزمنية بما يساهم بتشكيل دارات رقمية تسلسلية. الأمر المهم المتعلق بهذه الخاصية هي أنها لا تقتصر فقط على إمكانية تشكيل دارة واحدة يتم التحكم بها زمنيًا فقط، وإنما يمكن باستخدام لغات توصيف العتاد تشكيل أحداث مختلفة تعمل مع بعضها البعض بنفس الوقت، أي أنها أحداث “متزامنة/مترابطة Concurrent“، وهو ما يعني حوسبة تفرعية حقيقية Parallel Computing.

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

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

في المثال السابق هنالك كتلتين من نوع always@(posedge clock) وهذا يعني أن كافة العمليات التي تحدث داخل الكتلتين مقادتين عبر نفس الإشارة، وهي بحالتنا هذه نبضات الساعة. الأمر المهم معرفته هنا هو أن تنفيذ هاتين الكتلتين يحصل بنفس الوقت تمامًا، على الرّغم من وجودهما بشكلٍ متتالي ضمن الشيفرة المصدرية الخاصة بالبرنامج. بنفس الطريقة، وبالنظر لكتلة always الأولى سنجد أن التعليمات الخاصة بعمليات الضرب محاطة بالتصريحين begin و end، وهما عبارة عن وسيلة إضافية لإخبار بيئة البرمجة والمحاكاة أن ما بين هذين التصريحين هو عبارة عن عمليات تحصل مع بعضها البعض بنفس الوقت، على الرّغم من كونها مكتوبة ضمن الشيفرة المصدرية بشكلٍ متتالي. عند إجراء عملية اصطناع Synthesis للبرنامج السابق باستخدام إحدى بيئات التطوير الخاصة بلغات توصيف العتاد، فإننا سنحصل على دارةٍ تأخذ الشكل التالي:

مخطط RTL الناتج عن اصطناع البرنامج السابق

بمزيدٍ من التوضيح، فإنه يمكننا ملاحظة أن المخطط السابق ينفذ المهمة المطلوبة بالضبط: إجراء عمليتي ضرب، جعل نواتج الضرب متزامنة مع إشارة الساعة، تنفيذ عملية جمع وجعل ناتجها أيضًا متزامن مع إشارة الساعة. الصورة التالية توضح الأفكار السابقة:

مستوى انتقال المُسجّل RTL: Register Transfer Level

عند الحديث عن لغات توصيف العتاد فلابد من المرور على مفهوم مستوى انتقال (تبدّل) المسجل والمعروف باختصارًا باسم RTL. ببساطةٍ شديدة، يشير هذا المفهوم إلى تمثيلٍ مجرّد للدارة الإلكترونية المراد تشكيلها سواء كانت تتابعية أو تركيبية، وهو يصف الوظيفة التي ستقوم بها الدارة الإلكترونية وعلاقة إشارات الدخل بالخرج، إلا أن هذا التمثيل لا يأخذ النواحي الزمنية بعين الاعتبار، بمعنى أنها لا يمكن معرفة مدى التأخير الزمني للدارة عبر الحصول على تمثيل RTL.

يمثل الحصول على تمثيل RTL المرحلة الأولى من مراحل اصطناع الدارات الإلكترونية باستخدام لغات توصيف العتاد، فبعد كتابة النص البرمجيّ بلغةٍ مثل Verilog، فإن الخطوة الأولى هي تحليل النص للتأكد من خلوه من الأخطاء ومن ثم إجراء عملية اصطناع Synthesis والتي ستؤدي بالبداية لإنتاج ملفٍ توصيفيّ يعرف باسم Netlist، والذي يتضمن المعلومات الأساسية حول الدارة ووظيفتها والوحدات التي تشكلها. يمكن استخدام هذا الملف التوصيفيّ من أجل توليد مخطط RTL الخاص بالدارة الموصوفة بالنص البرمجيّ، والأهمية الكبيرة هنا هي استخدام مخططات RTL من أجل إجراء عمليات المحاكاة الوظيفية Functional Simulation للدارات التي تم إنشاؤها، أي التأكد من أن الدارة تقوم بإنجاز الوظيفة المطلوبة بغض النظر عن أدائها الزمنيّ، حيث لا يمكن إجراء عملية محاكاة زمنية للدارة اعتمادًا على مخططات RTL.

وحدات الاختبار Testbench

لا تقتصر القدرات الخاصة بلغات توصيف العتاد على البرمجة المتزامنة ووصف الأداء الزمنيّ، بل تمتلك أيضًا خاصيّة هامة جدًا لمن يريد استخدامها بمجال تصميم الدارات الإلكترونية: وحدات الاختبار والمُحاكاة Testbenches.

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

أشهر لغات توصيف العتاد Most Popular HDLs

يوجد في الوقت الحاليّ عددٌ كبيرٌ من لغات توصيف العتاد المستخدمة لمجالاتٍ مختلفة، مثل اصطناع الدارات الإلكترونية التشابهية Analog-Circuit Synthesis، اصطناع الدارات الإلكترونية الرقمية Digital-Circuit Synthesis أو حتى إنشاء اللوحات الإلكترونية المطبوعة. بالرّغم من ذلك، يمكن القول أن لغتي Verilog و VHDL تهيمنان على عالم لغات توصيف العتاد. بالنسبة للغة SystemVerilog فهي نسخة أكثر شمولية من Verilog وتتضمن قدراتٍ أكبر وأوسع، فضلًا عن توفيرها لأنماط متغيرات إضافية تتيح للمبرمجين خياراتٍ أكثر عند كتابة البرامج مقارنةً مع Verilog. أخيرًا، تتيح لغة SystemVerilog إجراء عمليات التحقق العتاديّ من التصميم Hardware Verification.

مصادر إضافية References

أخيرًا، فإنه يمكن استخدام المصادر التالية من أجل الحصول على معلوماتٍ إضافية فيما يتعلق بلغات توصيف العتاد:

مقالات ذات صلة

زر الذهاب إلى الأعلى