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

المقالات السابقة في السلسلة:
- تطوير أبسط "البرامج الثابتة" FPGAs المثبتة في Redd ، وتصحيح الأخطاء باستخدام اختبار الذاكرة كمثال.
- تطوير أبسط "البرامج الثابتة" لأجهزة FPGA المثبتة في Redd. الجزء 2. رمز البرنامج.
- تطوير جوهرها الخاص لتضمينها في نظام المعالجات المستندة إلى FPGA.
- تطوير برامج للمعالج المركزي Redd على سبيل المثال من الوصول إلى FPGA.
- أول تجارب باستخدام بروتوكول الدفق على مثال اتصال وحدة المعالجة المركزية والمعالج في FPGA لمجمع Redd.
- ميلاد سعيد Quartusel ، أو كيف أن المعالج قد حان لهذه الحياة.
- طرق تحسين الكود ل Redd. الجزء 1: تأثير مخبأ.
- طرق تحسين الكود ل Redd. الجزء 2: الذاكرة غير المخزنة مؤقتًا وتشغيل الناقل الموازي.
قليلا من التفكير النظري
دعونا نقدر ما هو التردد الذي يمكن أن نضبطه دون ألم لسباق كل حديدنا. تسمح رقاقة SDRAM المستخدمة في المجمع بتردد حد يبلغ 133 MHz. لسرعات ساعة المعالج ، راجع
مقاييس الأداء Nios II . هناك ، لدينا FPGA Cyclone IV E ، تردد Nios II / f الأساسي البالغ 160 MHz مضمون. أنا لست من مؤيدي الضغط على جميع العصائر خارج النظام ، لذلك سنناقش العمل على تردد 100 ميغاهيرتز.
بصراحة ، ما زلت لم تستلهم منهجية حساب تحول تردد الساعة الوارد في القسم
32.7. اعتبارات الساعة ، PLL والتوقيت في دليل مستخدم IP Embedded Peripherals ، ولكن يبدو أنني لست الوحيد. على الأقل ، لم يؤدني البحث الطويل على الشبكة إلى المقالات التي قد تحتوي على أي نتائج محسوبة بالطريقة نفسها ، ولكن ليس للتردد الوارد في المستند الرئيسي (نفس MHz 50).
هناك مقال مثير للاهتمام سأقدم لك رابطًا مباشرًا
www.emb4fun.de/fpga/nutos1/index.html . يمكن للمرء أن يشير إلى ذلك ويقول "دعنا نفعل كمؤلف" ، إن لم يكن لأحد "ولكن": يستخدم مؤلف هذه المقالة كتلة PLL (باللغة الروسية - PLL ، وعلى المستوى المنزلي - محول تردد) ، مع إدخال رمزها الخاص في VHDL. كما ذكرت سابقًا في
مقالة حول Quartusel الممتعة ،
أتقيد بأيديولوجية أن نظام المعالج يجب أن يكون في المستوى الأعلى من التسلسل الهرمي للمشروع. لا يلزم إدخال أي لغة ، سواء كان VHDL أو Verilog. في الآونة الأخيرة ، تلقى هذا النهج الخاص بي تأكيدًا آخر: لدينا موظف جديد ، وهو طالب لا يتحدث Verilog حتى الآن ، ولكنه يقدم رمزًا رائعًا لمجمع Redd ، نظرًا لأن النهج المختار يسمح بذلك.
اتضح أننا نأخذ كأساس أن كل شيء يعمل لصالح المؤلف في تحول من 54 درجة ناقص (أي نوع من الشهادات الموضحة في المقالة ، الرابط الذي أعطيته الفقرة أعلاه).
بعد ذلك ، انتبه إلى مقالة أخرى مثيرة للاهتمام
asral.unimap.edu.my/wp-content/uploads/2019/07/2019_IJEECS_Chan_Implementation-Camera-System.pdf . كل شيء يعمل للمؤلفين في تحول من ناقص 65 درجة.
دعنا نحاول جعل نظامنا يستخدم قيمة من هذا النطاق. إذا لم يكن هناك عطل واحد خلال الاختبار اليومي لذاكرة الوصول العشوائي ، فسنترك هذه القيمة كمعارضة. لدينا الحق ، لأن "البرامج الثابتة" المطورة لـ Redd لن تذهب إلى العملاء ، ولكن سيتم استخدامها لتلبية الاحتياجات الداخلية وبكميات كبيرة. إذا كان هناك أي شيء ، فسيكون من الممكن دائمًا إصلاح كل شيء دون صعوبات غير ضرورية (تنشأ الصعوبات عندما يكون من الضروري تحديث "البرامج الثابتة" في آلاف الأجهزة المباعة ، وببساطة على العميل البعيد).
قطعة جديدة من تكوين الأجهزة
لسبب ما ، يبدو لي أن نظام المعالج لهذه المقالة أسهل في القيام به من البداية بدلاً من إعادة تشكيله من القديم. فقط كيف لإظهار "تطور ، تطور ، تريد الخلط" العملية ، في اشارة دائمة إلى المقالات السابقة ، أفضل أن تظهر كل ذلك مرة أخرى من البداية. في الوقت نفسه ، نقوم بإصلاح المواد. لذلك ، دعونا نبدأ.
في البداية ، تم عرض نظام فارغ تمامًا يحتوي على مصدر إشارة على مدار الساعة وإعادة التعيين.

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

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

هذه هي نفس الكتلة ، ولكن هنا لا يتعين علينا تضمين أي كود في Verilog أو VHDL. تم إدراج كل شيء بالفعل بالنسبة لنا! صحيح أن الإعداد لأنواع مختلفة من FPGAs يختلف قليلاً عن الآخر تمامًا. بتعبير أدق ، تكون المعلمات القابلة للضبط متماثلة إلى حد ما ، ولكنها موجودة في أماكن مختلفة اختلافًا جذريًا في مربعات حوار التكوين. نظرًا لاستخدام Cyclone IV E FPGA في مجمع Redd ، فسننظر في تكوين هذا الخيار.
في علامة التبويب الأولى ، استبدل تردد الإدخال بـ 50 ميجاهرتز (افتراضيًا كان 100) وانتقل إلى علامة التبويب التالية (انقر فوق التالي ، بالنسبة إلى Cyclone IV E ، يتعين علينا القيام بذلك عدة مرات).

قم بإلغاء تحديد المدخلات والمخرجات الإضافية. نحن لسنا بحاجة لهم:

نقوم بتخطي علامات التبويب القليلة التالية حتى نصل إلى ضبط المخرجات C0. هناك نحول زر الاختيار لضبط التردد وإدخال قيمة 100 ميغاهيرتز:

مع C1 ، الأمور معقدة بعض الشيء. أولاً ، حدد مربع الاختيار الذي يقول إنه يجب استخدامه أيضًا. ثانيا ، وضعنا بالمثل تردد 100 ميغاهيرتز. حسنا ، وثالثا ، وضعنا تحول التردد. أي واحد أن يسأل؟ ناقص 58 أو ناقص 65؟ بالطبع ، حاولت كلا الخيارين. كلاهما أكسبني. لكن الحجة حول الموضوع ناقص 58 تبدو أقل إقناعًا ، لذا فإنني هنا أوصي بإدخال القيمة ناقص 65 درجة (في حين أن الأتمتة ستخبرني أن القيمة الفعلية المحققة ستكون ناقص 63 درجة).

حسنا ، هذا كل شيء. يمكنك الآن التنقل خلال الزر "
التالي" حتى النهاية ، أو يمكنك فقط النقر فوق "
إنهاء" . نحن نربط المدخلات
inclk_interface و
inclk_interface_reset . سيتم استخدام الإخراج
c0 كساعة للنظام بأكمله.
يتم تصدير
c1 الإخراج لتسجيل مسافة السباق رقاقة
sdram . في المستقبل ، ستحتاج إلى تذكر توصيل ناقل البيانات بإدخال
pll_slave . بالنسبة للإعصار الخامس ، لن يكون هذا ضروريًا.

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

مع الحركة المعتادة لليد ، أضف كتلتين من ذاكرة الوصول العشوائي الداخلية FPGA. واحد هو منفذ مزدوج بسعة 16 كيلو بايت وواحد هو منفذ واحد بسعة 4 كيلو بايت. كيفية تسمية لهم وكيفية الاتصال ، وآمل أن يتذكر الجميع. آخر مرة أحببت فيها تسليط الضوء على الإطارات بالورود ، ربما لسهولة القراءة ، سأفعل ذلك في هذا المقال.

لا تنس تعيين عناوين كتل الذاكرة هذه في النطاق الشخصي وقفلها. اسمح لـ
CodeMemory بتعيين 0x20000000 و
DataMemory إلى 0x20004000.
حسنًا ، دعنا نضيف كتلة
SDRAM إلى النظام ، ونقوم بإعدادها ، وكذلك كتل
JTAG-UART لعرض الرسائل و
GPIO أحادي البت ، حيث سنقوم بقياس التردد الحقيقي للتأكد من زيادته. للإشارة ، إليك بعض الإعدادات غير الواضحة:



إجمالي ، حصلنا على مثل هذا النظام (لقد أبرزت ناقل البيانات ، لأنه يمسح عبر جميع الأجهزة الخارجية):

نقوم بتعيين متجهات إلى المعالج ، وتعيين العناوين تلقائيًا ، وتعيين أرقام المقاطعة تلقائيًا ، إلى نظام التوليد.
نحن نربط النظام بالمشروع ،
ونقوم بتجميع تقريبي ،
ونخصص أرقام الأرجل ، وهذه المرة نصنع ظاهريًا ليس فقط
CKE ، ولكن أيضًا
reset_n (كيف يتم ذلك ، قلت في
إحدى المقالات السابقة ، ابحث عن Virtual Pin هناك). نجعل التجميع النهائي ، وملء المعدات في FPGA. هذا كل شيء. لقد انتهينا من المعدات ، انتقل إلى جزء البرنامج.
أنشأنا BSP لبيئتنا
لإجراء تغيير ، فلنقم بإنشاء مشروع يستند إلى قالب لا لـ
Hello World Small ، ولكن من
Memory Test Small :

عندما تم إنشاؤه ، انتقل إلى محرر BSP. كالمعتاد ، أول شيء نقوم به هو إيقاف تشغيل SysID والتحقق من استخدام C ++ (على الرغم من أنني لن أغير هذه المرة نوع الملف ، لكن هذه العادة عادة بالنسبة لي):

ولكن أهم شيء يتعين علينا إصلاحه في علامة التبويب
Linker Script . أدرك التنفيذ أن ناقل التعليمة ينتقل فقط إلى ذاكرة
CodeMemory ، لذلك وضع
مقطعًا من التعليمات البرمجية (يسمى
.text ) في ذاكرة
CodeMemory . لكن مع الاهتمام بنا ، وضعت كل شيء آخر في أكبر منطقة بيانات ، والتي تقع في
SDRAM . كيف عرفت أننا سنمحو هذه الذاكرة بلا رحمة؟

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

تجارب البرنامج
نخرج من المحرر وننشئ BSP ونحاول تشغيل البرنامج لتصحيح الأخطاء. نحصل على النص التالي:

إذا ضغطت على Enter ، فلن تنجح. دخلت شيئا (نعم حتى الفضاء) ثم ضغطت على Enter. ثم سألوني:

ساعة بساعة ليست أسهل. وما عنوان للدخول؟ يمكنك فتح Platform Designer ورؤية القيمة هناك. لكنني عادة ما أنظر إلى نظام الملفات المرجعية العالمي. (المسار الكامل لمشروعي هو C: \ Work \ CachePlay5 \ software \ MemoryTest_bsp \ system.h). نحن مهتمون بخطين:

نفس النص#define ALT_MODULE_CLASS_new_sdram_controller_0 altera_avalon_new_sdram_controller #define NEW_SDRAM_CONTROLLER_0_BASE 0x0 #define NEW_SDRAM_CONTROLLER_0_CAS_LATENCY 3 #define NEW_SDRAM_CONTROLLER_0_CONTENTS_INFO #define NEW_SDRAM_CONTROLLER_0_INIT_NOP_DELAY 0.0 #define NEW_SDRAM_CONTROLLER_0_INIT_REFRESH_COMMANDS 2 #define NEW_SDRAM_CONTROLLER_0_IRQ -1 #define NEW_SDRAM_CONTROLLER_0_IRQ_INTERRUPT_CONTROLLER_ID -1 #define NEW_SDRAM_CONTROLLER_0_IS_INITIALIZED 1 #define NEW_SDRAM_CONTROLLER_0_NAME "/dev/new_sdram_controller_0" #define NEW_SDRAM_CONTROLLER_0_POWERUP_DELAY 100.0 #define NEW_SDRAM_CONTROLLER_0_REFRESH_PERIOD 15.625 #define NEW_SDRAM_CONTROLLER_0_REGISTER_DATA_IN 1 #define NEW_SDRAM_CONTROLLER_0_SDRAM_ADDR_WIDTH 0x18 #define NEW_SDRAM_CONTROLLER_0_SDRAM_BANK_WIDTH 2 #define NEW_SDRAM_CONTROLLER_0_SDRAM_COL_WIDTH 9 #define NEW_SDRAM_CONTROLLER_0_SDRAM_DATA_WIDTH 16 #define NEW_SDRAM_CONTROLLER_0_SDRAM_NUM_BANKS 4 #define NEW_SDRAM_CONTROLLER_0_SDRAM_NUM_CHIPSELECTS 1 #define NEW_SDRAM_CONTROLLER_0_SDRAM_ROW_WIDTH 13 #define NEW_SDRAM_CONTROLLER_0_SHARED_DATA 0 #define NEW_SDRAM_CONTROLLER_0_SIM_MODEL_BASE 0 #define NEW_SDRAM_CONTROLLER_0_SPAN 33554432 #define NEW_SDRAM_CONTROLLER_0_STARVATION_INDICATOR 0
حيث العشرية 33554432 تساوي ست عشري 0x2000000. لذلك ، يجب أن تبدو إجاباتي ونتائج العمل كما يلي:

عظيم ، ولكن هذا ليس جيدًا لاختبار يومي. أعيد كتابة الوظيفة
الرئيسية مثل هذا:
int main(void) { int step = 0; while (1) { if (step++%100 == 0) { alt_printf ("."); } if (MemTestDevice(NEW_SDRAM_CONTROLLER_0_BASE, NEW_SDRAM_CONTROLLER_0_SPAN)!=0) { printf ("*"); } } return (0); }
تشير النقاط إلى أن البرنامج لم "يتجمد". إذا كان هناك خطأ ، سيتم عرض علامة النجمة. من أجل الموثوقية ، يمكنك وضع نقطة توقف على ناتجها ، ثم لا تنام.
صحيح أن نقاط "اليسار" ارتفعت من مكان ما. اتضح أن يتم عرضها داخل وظيفة
MemTestDevice () . هناك أنا محوها استنتاجهم. كان الاختبار ناجحا. يمكن استخدام النظام الناتج ، على الأقل لتلبية الاحتياجات الداخلية (أي ، يتم تنفيذ هذه التطورات تحت مجمع Redd).
فحص أداء النظام
لكنني معتاد بالفعل على حقيقة أنه عند العمل مع المعدات لا يمكنك الوثوق بأي شيء. يجب فحص كل شيء بعناية. دعونا نتأكد من أننا نعمل بتردد مضاعف مقارنة بالمقالات السابقة. أضف الوظيفة المعروفة MagicFunction1 ().
اسمحوا لي أن أذكركم كيف تبدو. void MagicFunction1() { IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); IOWR (PIO_0_BASE,0,1); IOWR (PIO_0_BASE,0,0); }
سوف نسميها من
main () ، سنلتقط النبضات على مرسمة الذبذبات ، لكن هذه المرة سنهتم ليس فقط بجمالها ، ولكن أيضًا بالتردد (دعني أذكرك بأن كل قطرة ، حتى أعلى ، لأسفل ، هي أمر واحد ، حتى تتمكن من قياس المسافة بين القطرات ).

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

استنتاج
بدلاً من استخدام مذبذب التردد الثابت ، تعلمنا كيفية استخدام وحدة PLL مخصصة. صحيح أن الثوابت المكتشفة مخصصة لتردد 100 ميجاهرتز ، ولكن يمكن للجميع ضبطها على أي تردد آخر إما باستخدام حسابات معروفة أو بالتجربة والخطأ. لقد عززنا أيضًا مهارات إنشاء نظام معالج مثالي وتأكدنا من أن الذاكرة ذات التردد العالي تعمل بثبات ، وأن التردد زاد فعليًا.
بشكل عام ، يمكننا بالفعل إنتاج أي أشياء حسابية ، يمكننا حتى التبادل مع المعالج المركزي ، ولكن المعالج المركزي للمجمع سوف يتعامل مع الحسابات العادية بشكل أكثر كفاءة. تتم إضافة FPGA إلى Redd من أجل تنفيذ أي واجهات عالية السرعة أو التقاط (جيد أو تشغيل) تدفق المعلومات. لقد أتقنا بالفعل أساسيات التصميم ، لقد تعلمنا كيفية توفير أداء أكثر أو أقل عالية. حان الوقت لمواصلة العمل مع الواجهات ، وهو ما سنفعله في المقالة التالية. بتعبير أدق ، مجموعة من المقالات ، تضع في اعتبارها القاعدة "مادة واحدة - شيء واحد".