المقالات السابقة في السلسلة
كيف يعمل برنامج الكمبيوتر العادي؟ هناك بيئة خارجية معينة (الشاشة ولوحة المفاتيح مع "الماوس" هما الممثلان الأكثر نموذجية لهذه البيئة بالذات). البرنامج يتفاعل معهم. عند تصحيح الأخطاء ، يمكنك إحداث تأثيرات حقيقية من البيئة الخارجية ، أو يمكنك محاكاتها. غالبًا ما يكتب المختبرين لدينا جميع أنواع النصوص التي تحاكي التأثيرات الخارجية. بعد ذلك ، يتم تشغيل أدوات تحليل السجلات ، والتي تتحقق من صحة الإجابات يوم الأربعاء.
ماذا لو كان كل شيء عربات التي تجرها الدواب في برنامج الكمبيوتر هذا؟ يمكنك تعيين نقاط التوقف وفحص لقطة من النظام في اللحظة التي تصل فيها. شريحة النظام هي قيم المتغيرات. ربما حالات كائنات المزامنة المختلفة وكائنات المزامنة الأخرى. بشكل عام ، لقطة للمعلمات الداخلية للنظام الذي تم تصحيحه.
عند تصحيح أخطاء FPGAs ، يمكنك القيام بنفس الشيء. صحيح ، إذا كانت البيئة حقيقية ، فإن التوقف عن جزء من النظام ودراسته يمثل مشكلة ، وإن كان ذلك ممكنًا. كجزء من قصة Redd ، أواصل الترويج لفكرة أن كل شيء يجب أن يكون بسيطًا وسريعًا. نحن لا نصمم أنظمة معقدة. نحن نقوم ببعض الوحدات النمطية ، مثل تلك التي تم إجراؤها في المقالة الأخيرة . إنه معقد ، لكنه غير معقد للغاية. بشكل عام ، سنقوم بعمل نمذجة سلوكية.
وهنا يأتي السؤال عن البيئة الخارجية. كيف تحاكيه؟ تأتي النماذج لمساعدتنا. Verilog (بالإضافة إلى VHDL وغيرها من الأشياء المماثلة) من الممكن تمامًا وصف سلوك أي شيء. نحن نصنع نظامًا يعمل مع الدائرة المصغرة ULPI ... لذلك ، لاختبار تشغيلها ، يجب أن يكون هناك شيء على الطرف الآخر يتصرف تمامًا مثل ULPI. هذا هو ، نموذج ULPI. لكن هذا لا يكفى. تستجيب الكتلة الخاصة بنا لأوامر الحافلة ALAVON_MM. هذه الحافلة هي التي تجعل الكتلة تعيش. لذلك ، نحتاج أيضًا إلى إضافة طراز الناقل AVALON_MM ، ويجب أن يكون هذا النموذج نشطًا. هي التي ستقدم اختبار التأثيرات.
في النهاية علينا أن نصنع مثل هذا النظام. وبعد ذلك سنكون قادرين على تسجيل المخططات الزمنية للإشارات في جميع حافلاتها وحتى داخل أي من وحداتها. في حالة حدوث خطأ ، يمكننا تعيين نقاط التوقف وفحص لقطات النظام للعثور على العدو. على الرغم من أنني ، شخصيًا ، لا أقوم عادةً بتعيين نقاط التوقف هذه ، إلا أن تحليل الرسوم البيانية الزمنية يكون كافياً في أغلب الأحيان. الحقيقة هي أنه لا يمكن عرض الإشارات فقط على إشارات الواجهة ، ولكن أي إشارات داخلية. من خلال سحب عشرات أو اثنتين من الإشارات الداخلية على الرسم البياني ، يمكنك عادةً تخمين ما يتم تنفيذه بشكل خاطئ في المنطق.
الغرض من مقال اليوم ليس الحديث عن ماهية النمذجة بشكل عام (هذه قصة طويلة) ، ولكن لإظهار كيفية القيام بهذا النمذجة بسرعة أكبر. وسننظر في هذا ليس في مهمة قتالية ، ولكن في مثال بسيط. لنقم بعمل نظام اختبار بسيط للغاية حتى نفهم بالفعل في المقالة التالية من أين تنمو أرجل نسخة أكثر تعقيدًا منه ، لأنه عند القراءة يكون من الأنسب عدم الجلوس والتساؤل: "لماذا يفعل هذا؟" ، ولكن لمعرفة كل المبادئ الأساسية ، والتي تتبع منها التعقيدات بالفعل ... بالمناسبة ، اتضح مؤخرًا أن أحد معارفي ، على الرغم من أنه يمتلك مهارة النمذجة ، لم يكن يعلم أن بيئة Quartus بها آليات مدمجة تتيح لك القيام بذلك بسهولة وبشكل طبيعي. لقد بذل الكثير من الجهد عليه أكثر مما هو مطلوب. لذلك ربما يتعلم شخص ما الآن شيئًا جديدًا لأنفسهم حول الاحتمالات الكامنة في Quartus. وبالتالي،هيا بنا نبدأ.
Verilog
ينقسم الناس إلى فئتين. أولئك الذين يحبون إنشاء كل شيء من الصفر بأيديهم وأولئك الذين يحبون القيام بذلك باستخدام الماوس. من الأصح إنشاء كل شيء بيديك. يمكنك التحكم في كل إجراء والقيام بكل شيء تعرفه تمامًا. لكن الذاكرة لا يمكن الاعتماد عليها. إذا كانت تفعل الشيء نفسه طوال الوقت ، فإنها تضع التفاصيل في الاعتبار ، وإذا كان عليها التبديل بين اللغات طوال الوقت ، فبعد شهر أو شهرين عليها أن تتذكر ما يجب القيام به هناك. لذلك فإن العمل من خلال خيار "العبث بالماوس" له الحق في الوجود على الأقل بسبب هذا. مرة أخرى ، إذا كانت الوحدة التي يتم تصحيحها تحتوي على عشرات أو نحو ذلك من إشارات الواجهة ، فأنا دائمًا أشعر بالملل من القيام بالأعمال الروتينية المتمثلة في إعادة إعلانها وإعادة توجيهها. لذلك ، سننظر الآن في كيفية صنع نموذج باستخدام "الفأرة". وبعد ذلك - سيقرر الجميع بنفسه ما إذا كان هذا كافياً بالنسبة له ، أم يجب عليه التحول إلى العمل اليدوي.
لذلك ، نريد محاكاة الوحدة. ما هو "محاكاة" هو خارج نطاق دورتنا ، يمكنك كتابة دورة كبيرة منفصلة حول هذا الموضوع. بمعنى ، في إطار هذا القسم ، نفترض أنك على دراية بمنهجية تطوير النموذج. ولكن بعد ذلك كل شيء يحتاج إلى تضمينه في المشروع ... أم لا؟ من الغريب أنك لا تحتاج حتى إلى إنشاء مشروعك الخاص لتصميم وحدة نمطية. يمكننا أن نلحق نفسه كطفيلي لأي مشروع ، دون تضمين أي شيء جديد فيه ، ولكن فقط من خلال إنشاء مجموعة اختبار لن تشارك في التجميع الرئيسي بأي شكل من الأشكال.
من أجل الاهتمام ، دعنا نعلق على مشروع ULPI الخاص بنا مثل هذه الوحدة المضحكة في SystemVerilog ، التي كتبتها خصيصًا للتوضيح وليس لها علاقة بالمحلل المطور. منذ فترة وجيزة ، كان لدي الكثير من العبث في حساب المجاميع الاختبارية ، لذلك جاء في رأسي.
module sum(
input clk,
input [7:0] data,
input we,
input sof,
output [15:0] sum
);
logic [15:0] temp;
always @ (posedge clk)
begin
if (we)
begin
if (sof)
temp <= data;
else
temp <= temp + data;
end
end
// -
//assign sum = (~temp)+1;
// :
assign sum = temp;
endmodule
يمكن ملاحظة أن البيانات تأتي إليها عبر حافلة ، والتي تذكرنا عن بعد بـ AVALON_MM ، ويتم إخراجها ببساطة في رمز متوازي.
دعنا نضع الملف الناتج في الدليل مع مشروعنا ، لكننا لن ندرجه في المشروع في Quartus. بدلاً من ذلك ، سننشئ مجموعة اختبار خصيصًا لها. للقيام بذلك ، حدد عنصر القائمة "التعيينات" -> الإعدادات:
وفي الشجرة التي تظهر ، ابحث عن العنصر إعدادات أدوات EDA -> محاكاة:
بالمناسبة ، حول نوع المحاكاة التي تم تمييزها بواسطة الإطار الأخضر. ربما يتذكر شخص ما أنه في المقالات الأولى قلت أنه عند إنشاء مشروع ، بدافع العادة ، اخترت ModelSim Altera؟ لقد كانت البندقية ذاتها على المسرح التي كان عليها إطلاق النار عاجلاً أم آجلاً. ومع ذلك ، إذا لم تحدد نوع النمذجة عند إنشاء المشروع ، فيمكنك تحديده أو تغييره هنا.
نواصل إنشاء مجموعة اختبار. قم بتبديل زر الاختيار إلى منصة اختبار الترجمة (بالمناسبة ، كيف يترجم هذا المصطلح بشكل جميل إلى اللغة الروسية؟ لا يمكنني إحضار نفسي لكتابة "مقعد الاختبار" ، حيث لا أرى أي مقعد) واضغط على زر " مقاعد الاختبار" :
في مربع الحوار الذي يفتح ، اضغط على " جديد" :
إذا كنت تريد حالة الاختبار يدويًا ، يمكنك ملء الحقول في مسار واحد. ولكن نظرًا لأننا نقوم بكل شيء باستخدام الماوس ، فإننا نملأ الآن جزءًا فقط من الحقول ، وسنملأ الباقي لاحقًا. في حقل اسم مقعد الاختبارلقد كتبت كلمة Parazit (ماذا يمكنك أن تسميه أيضًا اختبارًا يتطفل على المشروع فقط؟). تم ملء كلمة Parazit تحتها تلقائيًا. لن نغيره الآن ، لكن في المستقبل لا يزال يتعين علينا القيام به. أيضًا ، باستخدام الزر "..." ، قمت بتحديد ملف sum.sv مع كود الأعلاف المراد تصحيحه ، ثم باستخدام الزر " إضافة " ، قمت بدفعه إلى قائمة ملفات الاختبار. في الوقت الحالي ، هذا كل شيء. إغلاق مربع الحوار ...
بعد ذلك ، سنستمر في تشكيل الاختبار في بيئة ModelSim. للقيام بذلك ، حدد عنصر القائمة Tools—> Run Simulation Tools—> RTL Simulation:
تفتح نافذة ModelSim. ربما سيتم العثور على أخطاء في كود Verilog ، فأنت بحاجة إلى إغلاق ModelSim وتصحيح الأخطاء وإعادة الفتح. لكن عاجلاً أم آجلاً ، ستصبح قائمة الأخطاء تنظيمية بحتة. يبدو هذا بالنسبة لي:
لم يتم العثور على وحدة من المستوى الأعلى. هذا امر طبيعي. لم نقم بإنشائه ببساطة. لذلك نذهب للعمل في قائمة المكتبات ونفتحها . ها هو أفعانا.
قم بالمرور فوقه ، واضغط على زر الماوس الأيمن وحدد عنصر القائمة Create Wave. كل هذا ممل جدًا في النص ، إذا كنت أصور مقطع فيديو ، فستستغرق العملية برمتها عشرات الثواني ، لذلك لا تنزعج ، ولكن راقب يديك أكثر. لذلك ، إنشاء موجة ...
تم نقل إشارات واجهة الوحدة تلقائيًا إلى المخطط:
من الضروري تعيين قيمة لأحدهم. لا يهم أيهما ، من المهم تعيينه. كانت بيئة النمذجة القديمة جدًا في Quartus جيدة في توليد إشارات الساعة. للأسف ، تم سحبه من التسليم منذ وقت طويل ، حيث بدأوا في إرفاق ModelSim ، وهنا كل شيء ليس جميلًا جدًا بشيء من هذا القبيل. لم أرى الهدف من إنشاء مولد هنا ، لذا لن أعرضه حتى. حسنًا ، دعنا نضع الخط المستقيم على صفر. نهدف إلى الإشارة ، اضغط على الزر الأيمن ، وحدد عنصر القائمة تحرير -> محرر الموجة -> إنشاء / تعديل WaveForm.
في مربع الحوار الذي يظهر ، حدد ثابت . وفي نفس الوقت سنغير الوقت ، على سبيل المثال ، بمقدار 100 ميكروثانية:
بعد ذلك ، نشير إلى القيمة 0:
لقد أنشأنا الحد الأدنى من مجموعة البيانات المطلوبة ، وسيكون الباقي أسهل مع الأقلام. نقوم بتصدير الملف. للقيام بذلك ، حدد عنصر القائمة File—> Export—> Waveform:
حدد نوع الملف Verilog Testbench (بالمناسبة ، من المؤسف أنه ليس SystemVerilog ، ولكن في المستقبل سيكون من الممكن تصحيحه باستخدام الأقلام). قمنا أيضًا بتعيين اسم الملف. أنا أطلق عليها اسم parazit_tb ، بعد "لماذا لا؟"
هذا كل شيء ، يمكن إغلاق ModelSim ، بينما لا يحتاج المنزل المؤقت إلى الحفظ.
ماذا تفعل مع النموذج التالي
هذا ملف ملتوي ، لكنه لا يزال ملف Verilog جاهزًا ، تم إنشاء النظام لنا:
`timescale 1ns / 1ns
module parazit_tb ;
reg sof ;
reg we ;
wire [15:0] sum ;
reg [7:0] data ;
reg clk ;
sum
DUT (
.sof (sof ) ,
.we (we ) ,
.sum (sum ) ,
.data (data ) ,
.clk (clk ) );
// "Constant Pattern"
// Start Time = 0 ns, End Time = 100 us, Period = 0 ns
initial
begin
end
initial
#0 $stop;
endmodule
الأتمتة أنقذتنا من كتابة اللبنات الأساسية. علاوة على ذلك ، إذا كان هناك المزيد من إشارات الواجهة ، فإن الأتمتة ستسجل وتوصل جميع الدوائر بطاعة. شخصيًا ، عندما أقوم بإنشاء مجموعات اختبار يدويًا ، فإن عملية وصف الإشارات وإعادة توجيهها أمر محبط. الآن ، في هذا الملف ، سننشئ الآن نموذج بيئة سيؤثر على وحدة المجموع المصحح .
كما ترى ، لا يوجد أي معنى في تحديد الثوابت التي يصنعها المذبذب. ولكن مع ذلك ، تم إنشاء جميع الدوائر ، وتم توصيل الوحدة المراد اختبارها ، حتى تم إنشاء القسم الأولي . دعونا نحسن الكود. الأول هو إزالة نقطة التوقف عن طريق حذف الأسطر:
initial
#0 $stop;
بعد ذلك ، سنضيف نموذج مولد ساعة (كيف أفتقد المولد الرائع الذي صنعه Quartus القديم! هناك يمكنك ضبط التردد بالميغاهرتز ولا تفكر في إعادة حسابه في فترة زمنية ، وأكثر من ذلك - نصف فترة).
always
begin
clk = 0;
#5;
clk = 1;
#5;
end
الآن نحن بحاجة إلى إرسال بعض البيانات بايت. أسهل طريقة للقيام بذلك هي في القسم الأولي ، ولكن إذا كتبت كل مرحلة وصول للحافلة هناك ، فسيصبح الرمز الموجود في هذا القسم محيرًا. لذلك ، سأقوم بالمهمة التالية (هي التي تعمل كنموذج للإطارات):
task SendByte (input reg[7:0] D);
begin
data = D;
we = 1;
@(posedge clk);
#1
we = 0;
end
endtask
حسنًا ، سأكتب الغرض من الثوابت ودعوة الدورات للعمل مع الناقل في الكتلة الأولية . دعني أذكرك أن نوع السجل # 123 يعني "انتظر 123 وحدة زمنية". لدينا في نانوثانية. أذكرك أيضًا أنه نظرًا لأن التخصيصات متسلسلة ، فإننا نستخدم عملية "المساواة" ، وليس "السهم". لذلك ، لدينا كود الاختبار الرئيسي التالي:
مشاهدة هنا
initial
begin
sof = 0;
we = 0;
data = 0;
#13;
//
sof = 1;
SendByte (1);
//
sof = 0;
SendByte (5);
SendByte (1);
//
#20;
SendByte (1);
end
في المجموع ، يبدو رمز الوحدة الكامل لدينا كما يلي:
عرض كود الوحدة كاملة.
`timescale 1ns / 1ns
module parazit_tb ;
reg sof ;
reg we ;
wire [15:0] sum ;
reg [7:0] data ;
reg clk ;
sum
DUT (
.sof (sof ) ,
.we (we ) ,
.sum (sum ) ,
.data (data ) ,
.clk (clk ) );
always
begin
clk = 0;
#5;
clk = 1;
#5;
end
task SendByte (input reg[7:0] D);
begin
data = D;
we = 1;
@(posedge clk);
#1
we = 0;
end
endtask
// "Constant Pattern"
// Start Time = 0 ns, End Time = 100 us, Period = 0 ns
initial
begin
sof = 0;
we = 0;
data = 0;
#13;
//
sof = 1;
SendByte (1);
//
sof = 0;
SendByte (5);
SendByte (1);
//
#20;
SendByte (1);
end
endmodule
استكمال تحضير حالة الاختبار
حان الوقت لإضافة هذا النص إلى مجموعة الاختبار. للقيام بذلك ، انتقل إلى مربع الحوار المعروف لنا بالفعل ، لكننا
الآن لا ننشئ مجموعتنا ، ولكننا نحددها من القائمة. في المستقبل ، ستكبر القائمة مع إضافة المجموعات ... بعد التحديد ، اضغط على زر تحرير. لقد أجريت ثلاثة تعديلات على الإعدادات:
- تمت إضافة ملف parazit_tb.v إلى القائمة.
- نظرًا لأن وحدة المستوى الأعلى في ملف parazit_tb.v لها اسم parazit_tb (يمكنك التأكد من خلال النظر إلى المصدر من القسم السابق) ، فقد قمت بإدخال هذا الاسم في وحدة المستوى الأعلى في سطر الاختبار .
- قلت لتشغيل المحاكاة لمدة 10 ميكروثانية ثم توقف. إذا كان هناك أي شيء ، فسأفعل ذلك بالضغط على أزرار التحكم اليدوي.
مجموع
نغلق كل شيء. قم بتشغيل ModelSim مرة أخرى. نرى أن كل شيء يعمل بشكل صحيح. تأتي البيانات وتحسب بالمقدار. إذا لم تكن هناك بيانات على مدار الساعة ( نحن صفر) ، فلن يزيد المقدار.
كيفية استخدام بيئة النمذجة نفسها موضوع لعدة مقالات. وبدلا من ذلك في شكل فيديو. لكن بشكل عام ، تعرفنا على طريقة الإعداد والتشغيل السريع للاختبارات بلغة Verilog من بيئة Quartus.
الآن بعد أن عرفنا كيفية تشغيل المحاكاة بسرعة ، يمكننا رسم نموذج بيئة لرأس محلل USB واختباره. في الوقت نفسه ، لم نحفظ تعويذة ModelSim واحدة ، لأن Quartus يسمح لك بتهيئة كل شيء باستخدام "الفأرة". يولد جميع البرامج النصية اللازمة بنفسه ويدعو بيئة ModelSim بنفسه. أنشأنا أيضًا قاعدة النموذج في الوضع التلقائي ، على الرغم من أنه كان علينا بعد ذلك تعديله يدويًا.
آه وآه. أحد عناصر البيئة الخارجية هو وحدة ULPI. لتطوير نموذجها بنفسك ، يجب عليك أولاً أن تفهم بعناية منطق تشغيل تلك الدائرة المصغرة. وفي المقال السابق قلت إن الأمر صعب للغاية. حسنًا ، وثانيًا ، تحتاج إلى قضاء الكثير من الوقت في تطوير كود النموذج. والقضاء على الأخطاء فيه .. من الواضح أنه من الأسهل العثور على شيء جاهز. لكن النموذج الجاهز تم العثور عليه فقط في لغة SystemC. لذلك ، في المقالة التالية سوف نتعلم تصميم نظام باستخدام هذه اللغة.