المقالات السابقة في السلسلة
في الواقع ، ظهر هذا المقال كملف DOC مرة أخرى في يونيو. ثم تمت كتابة مجموعة من خمسة مقالات في وقت واحد. لكن تحميل ملف DOC إلى Habr هو مهمة أخرى. لذلك ، حدث أن الوقت لم يظهر إلا الآن (وهناك اثنان آخران في حالة ترقب). عند التحميل ، لاحظت أنه إذا لم تدخل في روح المقالات السابقة ، فهذا يبدو مملاً نوعًا ما. لذلك ، إذا كانت هناك رغبة من هذا القبيل ، فقم بتحديث المقالة الأخيرة على الأقل في ذاكرتك ، أو أفضل من هاتين المادتين ( "جعل رأس محلل ناقل USB ..." و "محاكاة سلوك مشروع Quartus ..." ).
المقدمة
لذا ، النموذج النهائي ، أين يمكنني الحصول عليه؟ هناك مشروع يحل بالضبط نفس مشكلة المحلل الذي نعمل على تطويره ، ولكن لديه ميزتان. الميزة الأولى هي Xilinx FPGAs. ثانيًا ، إنها غير موثقة تمامًا. يعمل بطريقة ما. يمكنك حتى شراء لوح تجارب جاهز وملئه برمز ثنائي جاهز ... والحصول على بعض الوظائف. يمكن لأي شخص يحتاج إلى جهاز بأي ثمن اتباع هذا المسار ببساطة. لكن لا أحد يعرف كيف يطورها. هذا المشروع هنا . في دليل \ ulpi_wrapper \ testbenchهناك مجموعة من الملفات لاختبار النظام الفرعي للغلاف حول ULPI. يوصون بالنمذجة في بيئة Icarus Verilog ، لكنني بحثت في كل مكان ولم أجد أي أوصاف معقولة على السطح لكيفية القيام بذلك في لغة SystemC. لذلك ، قررت مواصلة العمل في بيئة ModelSim. لو علمت كيف ستنتهي ... لكنني لم أعرف. لذلك ، بدأت البحث. في سياق العرض التقديمي ، سيتم عرض حالات النجاح والفشل. لنبدأ بالفشل حتى يرى الجميع كيف لا يفعلون ذلك.
محاولة فاشلة للقيام بكل شيء "وجهاً لوجه"
في البداية قررت أن آخذ مثالًا جاهزًا وأديره من خلال النمذجة. من خلال الحركة المعتادة ليدي (وقمنا بتعبئة يدنا في المقالة الأخيرة ) ، قمت بإنشاء مجموعة اختبار تحتوي على ملفات على Verilog و SystemC. اتضح شيء من هذا القبيل: لقد قمت
بتشغيل ModelSim ولا أرى أي شيء في مجموعة العمل قد يكون مرتبطًا بـ SystemC. أرى رمز Verilogo ، لكن رمز Sishny لا.
إذا نظرت إلى السجلات ، يمكنك أن ترى أنهم لم يحاولوا جمعها. ما هو الأمر؟
معلومات مفيدة حول تكوين ملف * .do
يُعرف ملف * .do بتشغيل ModelSim. لكن بصفتي محبًا لفعل كل شيء باستخدام الماوس ، لم أنظر بداخله أبدًا. دعونا نبحث عنه ونفتحه! لا يوجد سوى ملف واحد من هذا القبيل في دليل المشروع. ربما هذا ما نحتاجه.
نفتحه. في البداية - تجميع جميع أنواع عناصر الخدمة والملفات المضمنة في المشروع.
شاهد النص
transcript on
if ![file isdirectory verilog_libs] {
file mkdir verilog_libs
}
if ![file isdirectory vhdl_libs] {
file mkdir vhdl_libs
}
vlib verilog_libs/altera_ver
vmap altera_ver ./verilog_libs/altera_ver
vlog -vlog01compat -work altera_ver {c:/intelfpga_lite/17.1/quartus/eda/sim_lib/altera_primitives.v}
vlib verilog_libs/lpm_ver
vmap lpm_ver ./verilog_libs/lpm_ver
vlog -vlog01compat -work lpm_ver {c:/intelfpga_lite/17.1/quartus/eda/sim_lib/220model.v}
vlib verilog_libs/sgate_ver
vmap sgate_ver ./verilog_libs/sgate_ver
vlog -vlog01compat -work sgate_ver {c:/intelfpga_lite/17.1/quartus/eda/sim_lib/sgate.v}
لكن في النهاية - من الواضح أن تجميع الأشياء التي نحتاجها ، أحكم على ذلك من خلال اسم ملف ulpi_wrapper.v :
vlog -vlog01compat -work work +incdir+C:/Work/UsbHead1/SystemCPlay {C:/Work/UsbHead1/SystemCPlay/ulpi_wrapper.v}
vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cycloneive_ver -L rtl_work -L work -L UsbHead1 -voptargs="+acc" lalala
add wave *
view structure
view signals
run 10 us
هل حقا. يوجد تجميع لوحدة Verilog ، ولا يوجد تلميح لتجميع الوحدات على SystemC. المؤسف الوحيد هو أن ملف DO هذا يتم إنشاؤه تلقائيًا في كل مرة تبدأ فيها المحاكاة ، لذلك لا يمكنك فقط أخذها وتحريرها. يتم إنشاؤه بواسطة نص TCL معقد للغاية. لا توجد رغبة في الحكم عليه. ولكن بعد المقالة عن الحي المبهج ، ربما يكون من الواضح أن مثل هذا التافه ليس سببًا للاستسلام. بالتأكيد ، كل شيء موجود بالفعل. المؤسف الوحيد هو أن الوثائق تقول "يمكنك عمل النص بهذه الطريقة ، أو يمكنك القيام بذلك" ، ولا توجد تلميحات لأمثلة. حسنًا ، دعنا نستنتج كل شيء بشكل تجريبي. قم بإنشاء ملف C: \ Work \ UsbHead1 \ SystemCPlay \ myrun.do وحاول نقل التحكم إليه. أولاً ، نحاول القيام بذلك على النحو التالي:
يستمر إنشاء ملف DO الرئيسي ، لكن نهايته تصبح كما يلي:
vlog -sv -work UsbHead1 +incdir+C:/Work/UsbHead1/UsbHead1/synthesis/submodules {C:/Work/UsbHead1/UsbHead1/synthesis/submodules/UsbHead1_master_0_b2p_adapter.sv}
vlog -sv -work UsbHead1 +incdir+C:/Work/UsbHead1/UsbHead1/synthesis/submodules {C:/Work/UsbHead1/UsbHead1/synthesis/submodules/UsbHead1_master_0_timing_adt.sv}
vlog -vlog01compat -work work +incdir+C:/Work/UsbHead1/SystemCPlay {C:/Work/UsbHead1/SystemCPlay/ulpi_wrapper.v}
vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cycloneive_ver -L rtl_work -L work -L UsbHead1 -voptargs="+acc" lalala
do C:/Work/UsbHead1/SystemCPlay/myrun.do
نرى أن ملف Verilog لا يزال مجمّعًا ، ثم لا تزال عملية النمذجة قد بدأت (على الرغم من أنني رأيت ذلك أثناء التشغيل التجريبي ، ولكن يمكنني الآن أن أقول على وجه اليقين أن الأمر vsim يبدأ هذه العملية) ، وبعد ذلك يتم نقل التحكم إلى النصي. يجب أن يتحكم هذا البرنامج النصي في عملية العرض. لكننا ما زلنا لا نستطيع إدارة التجمع. إذا كانت الملفات المجمعة غير كافية ، فسوف يسقط النظام عن طريق الخطأ قبل أن يُسمح لنا بفعل أي شيء. حسنًا ، رائع ، دعنا نجرب الإعداد الأخير.
وهنا تبدأ المتعة. من المهم جدًا أن أضعها في إطار.
أقوم بتحديد برنامج نصي ، لكن لم يتم تحديده. أذهب إلى الإعدادات (لدي الخيار المحدد السابق). أنا أختار ، لم أختار. وهكذا - حتى اللون الأزرق في الوجه. حتى لاحظت ذلك ، حتى وجدت كيف أفوز - قتلت المساء! اتضح أنه إذا حددت ملفًا فقط ، فسيظل الزر "تطبيق" باللون الرمادي. ولن يتم تذكر التغييرات. من الضروري جعل زر "تطبيق" يتحول إلى اللون الأسود من خلال تحرير معلمات الحوار الأخرى! في الصورة أعلاه ، إنه أسود تمامًا. إذا ظل باللون الرمادي ، فلن يتم حفظ التغييرات ولن يتم إعادة تكوين كل شيء لاستخدام البرنامج النصي.
لا يزال النص قيد التكوين ، لكن نهايته أصبحت أكثر ملاءمة لنا.
vlog -sv -work UsbHead1 +incdir+C:/Work/UsbHead1/UsbHead1/synthesis/submodules {C:/Work/UsbHead1/UsbHead1/synthesis/submodules/UsbHead1_master_0_timing_adt.sv}
do "C:/Work/UsbHead1/SystemCPlay/myrun.do"
أخيرًا ، عملية بناء المصادر للمشروع تحت رحمتنا تمامًا! رائع! في ذلك الوقت ، لم أتمكن إلا من العثور على تحقق SystemC مع مستند ModelSim المكتوب لـ Xilinx. لكن ModelSim موجود في Africa ModelSim أيضًا. باستخدام الأمثلة من هذا المستند وعينات ملف DO الذي تم إنشاؤه في التجارب السابقة ، قمت بعمل نص البرنامج النصي التالي (لا تنزعج من كثرة المفاتيح ، أدناه سنطرح كل شيء تقريبًا ، ثم سنقوم أيضًا باستبدال المسارات المطلقة بمسارات نسبية ، في هذه المرحلة قمت بسحب كل شيء من الأمثلة وعينات تم إنشاؤها تلقائيًا).
vlog -vlog01compat -work work +incdir+C:/Work/UsbHead1/SystemCPlay {C:/Work/UsbHead1/SystemCPlay/ulpi_wrapper.v}
vlib sc_work
sccom –g –I C:/intelFPGA_lite/17.1/quartus/cusp/systemc/include –work sc_work C:/Work/UsbHead1/SystemCPlay/ulpi_driver.cpp
لفة الطبل ... وتعلن لنا ModelSim:
إذا حذفنا كل الكلمات البذيئة ، فلن يكون لدي ما أقوله ... ولكن تم تجاوز هذا المسار! وأين يمكنني الحصول على نموذج ULPI آخر؟ بالطبع ، لقد عقدت اتفاقًا مع أصدقاء أجانب يشاركون بشكل احترافي في مشاريع جادة لـ FPGAs. بالنسبة لي على وجه الخصوص ، فقد فتحوا الوصول عن بُعد إلى جهاز باستخدام ModelSim مرخص لعطلة نهاية الأسبوع. تبين أيضًا أن الفطيرة الثانية كانت متكتلة: الإصدار 64 بت ، حتى في الشكل المرخص ، لا يعمل مع SystemC. لكن في النهاية ، تمكنت من التلاعب بالإصدار 32 بت من ModelSim المرخص. لذلك نواصل القصة ...
بضع كلمات حول التوثيق
وبالتالي. الآن بعد أن تمكنت من الوصول إلى البرنامج المرخص ، حان الوقت للتحدث عن مكان العثور على المعلومات ومكان الحصول على الإلهام. على شبكة الإنترنت ، المعلومات حول اللغة سطحية نوعًا ما. ولكن في تسليم النظام ، هناك الأدلة المفيدة التالية:
C: \ modeltech_10.2c \ docs \ pdfdocs - الوثائق ، بما في ذلك الملفات بتنسيق PDF. أعجبتني الملفات Modelsim_se_ref.pdf (الدليل المرجعي للأوامر ModelSim SE) ، و modelsim_se_user.pdf ( دليل مستخدم ModelSim SE) ، و Modelsim_se_tut.pdf (ModelSim SE Tutorial). لا يوجد الكثير حول اللغة نفسها ، ولكن حول كيفية توصيل الملفات وكيفية حل مشاكل اللهجات - تمامًا.
التالي ، الدليل المفيد C: \ modeltech_10.2c \ أمثلة... هناك أمثلة على ملفات * .do الجاهزة وملفات cpp و h الجاهزة. المثال الأكثر فائدة بالنسبة لنا هو C: \ modeltech_10.2c \ أمثلة \ systemc \ vlog_sc . يوضح لك كيفية الوصول إلى رمز SystemC من كود Verilog. في النهاية ، سوف نسير بهذه الطريقة بالضبط.
و C: \ modeltech_10.2c \ يتضمن \ دليل systemc يحتوي على شفرة المصدر لمكتبة النوع لغة. ليس مرجعا سيئا. كما يقولون ، هناك سمكة للسمك والسرطان.
كل شيء من الكتالوجات. الآن هو عنوان كتاب رائع ، يمكنك من خلاله معرفة الكثير عن اللغة وطرق البرمجة فيه. SystemC - من الألف إلى الياء ، الإصدار الثاني. بقلم ديفيد سي بلاك ، جاك دونوفان ، بيل بونتون ، آنا كيست.
لهجات النظام
وبالتالي. بعد أن تمكنت من الوصول إلى نظام العمل ، قمت بتجميع المشروع بفرح ، وفقًا للنص الذي تم إنشاؤه مسبقًا. اجتمع بدون أخطاء! النموذج الأول من جيثب وافق على العمل معنا! الرغبة في تشغيل المعيار ، أضفت ملف ulpi_wrapper_tb.cpp من نفس الدليل إلى المشروع وحصلت على الكثير من الأخطاء. لنفترض أن هناك خطأ في السطر:
m_vpi_handle = vpi_handle_by_name ((const char *) name، NULL)؛
يصعب إصلاحه ، ولكن لا يزال من الممكن. لكن الخط
// Update systemC TB
if(sc_pending_activity())
sc_start((int)(time_value-m_last_time),SC_NS);
استحضر الأفكار السيئة. لا توجد وظيفة sc_pending_activity () في المكتبات. هناك وظيفة sc_pending_activity_at_current_time () ، لكنني لم أكلف نفسي عناء التعامل معها. بدلاً من ألف كلمة للتفسير ، سأقدم تفريغًا:
وكان هناك 44 ملفًا بهذا النص (* .exe ، * .dll ، إلخ).
يمكنك محاولة إعادة كتابة كل شيء ... لكن هل هو ضروري؟ اسمحوا لي أن أذكركم أنني بدأت بالفعل كل هذا ، لأنني أردت استخدام كل ما كان جاهزًا. يمكنني تطوير كل شيء في بيئة حرة على نظام SystemVerilog خالص ، إذا أهدرت الكثير من الوقت حقًا ... ذهبت إلى هنا حتى لا أضيع الوقت ، ولكن لأوفر! لكن في الواقع ... الشيء الرئيسي هو عدم نسيان ما نقوم به. نريد استخدام نموذج ناقل ULPI. جمعت نفسها. نشأت المشاكل عند محاولة بناء نظام اختبار كامل من المثال ... لماذا هذا؟ حسنًا ، النظام الكامل لا يعمل ، ولا بأس. سنتقن نموذجًا واحدًا ، دون النظر إلى تشغيل النظام ، عن طريق التجربة والخطأ.
القضاء على سوء التفاهم القائم على اللهجة
وبالتالي. سنفعل نظام مختلط. ستتم كتابة الوحدة مع النموذج بلغة SystemC ، وسأرسل إجراءات الاختبار إليها والوحدة التي يتم تطويرها بلغة Verilog. هذا يعني أنك تحتاج إلى إظهار وحدة ulpi_driver في مجموعة العمل .
عند فحص ملفات * .do من تسليم ModelSim ، قمت بتبسيط البرنامج النصي إلى حد كبير ، وفي النهاية ، قمت بهذا:
vlog +../../SystemCPlay {../../MyCores/ULPIhead.sv}
sccom -g ../../SystemCPlay/ulpi_driver.cpp
sccom -link
لا توجد أخطاء ، لكن الوحدة لم تظهر في المجموعة أيضًا. فحص ملفات الأمثلة (تذكر أن أفضل مثال يقوم بتنفيذ مثل هذا المزج بين اللغات موجود في الدليل C: \ modeltech_10.2c \ أمثلة \ systemc \ vlog_sc ) ، أدركت أنه يجب إضافة السطر التالي إلى نهاية ملف ulpi_driver.cpp :
SC_MODULE_EXPORT(ulpi_driver);
تشير وثائق ModelSim إلى أن هذه ميزات لهجة. وفويلا! ها هي الوحدة الخاصة بنا:
صحيح ، قائمة إنشاء الموجة (ناقشنا هذه القائمة في المقالة الأخيرة ) غير متوفرة لها. وليس لديه منافذ. تاريخيًا ، تعاملت أولاً مع الموانئ ، لكن بشكل منهجي - سأؤجل القصة عنها لاحقًا. خلاف ذلك ، يجب عليك تحرير الرمز مرتين. لتجنب هذا ، دعنا أولاً نقوم ببعض التحضير.
صنع مولد ساعة
اتضح أن النموذج يحتوي على بعض الاختلافات عن ULPI الحقيقي. الاختلاف الأول هو أن الساعة 66 ميجاهرتز يجب أن تولدها الرقاقة. ماذا نرى في النموذج؟
sc_in<bool> clk_i;
اضطراب! لنبدأ إعادة العمل! يتم تنفيذ جميع الأعمال ، ما لم يذكر خلاف ذلك ، في ملف ulpi_driver.h.
قم بتغيير نوع المنفذ. كانت:
sc_in<bool> clk_i;
أصبح (قمت أيضًا بتغيير اسم المنفذ):
sc_inout<bool> clk;
تعلمت من الكتاب أنه يتم إدخال مولد حقيقي عن طريق إضافة متغير:
sc_clock oscillator;
قمنا بتعيين المعلمات في المنشئ. نتيجة لذلك ، يأخذ المُنشئ الشكل:
//-------------------------------------------------------------
// Constructor
//-------------------------------------------------------------
SC_HAS_PROCESS(ulpi_driver);
ulpi_driver(sc_module_name name): sc_module(name),
m_tx_fifo(1024),
m_rx_fifo(1024),
oscillator ("clk66",sc_time(15,SC_NS))
{
السطر الأخير لهذا فقط. إذا كنت ترغب في ذلك ، يمكنك حتى بدء المحاكاة ، انقر نقرًا مزدوجًا فوق وحدة usb_driver ، ثم اسحب clk66 إلى الكوخ المؤقت وقم بتشغيل عملية المحاكاة قليلاً. نرى بالفعل كيف يعمل المولد:
دعونا لا ننسى تغيير اسم إشارة الساعة في المكان الذي يبدأ فيه الخيط الرئيسي. كانت:
SC_CTHREAD(drive, clk_i.pos());
أصبح:
SC_CTHREAD(drive, clk.pos());
تم استبدال الروابط الداخلية. لكن ما أجمل إحضار الإشارة إلى الخارج ، لم أجدها. ربما أنا فقط أفتقر إلى المؤهلات. ولكن بطريقة أو بأخرى ، باءت كل محاولات سحب المنفذ بالفشل. كان هناك دائما شيء ما في الطريق. حتى أنني وجدت مناقشة في أحد المنتديات حيث كان المؤلف بحاجة إلى فعل الشيء نفسه. قرر الفريق أنه لا يمكن إعادة توجيهه إلا إلى منافذ الإدخال. لكننا نحتاج إلى الخروج! لذلك ، نحن نفعل هذا.
أضف دالة دفق أسفل المُنشئ:
void clkThread(void)
{
while (true)
{
wait(oscillator.posedge_event());
clk.write (true);
wait(oscillator.negedge_event());
clk.write (false);
}
}
وأضف رابطًا لها في مُنشئ الفصل:
SC_THREAD(clkThread);
دعني أعرض منطقة المُنشئ الحالية لإعطاء نظرة شاملة للنتيجة الحالية:
SC_HAS_PROCESS(ulpi_driver);
ulpi_driver(sc_module_name name): sc_module(name),
m_tx_fifo(1024),
m_rx_fifo(1024),
oscillator ("clk66",sc_time(15,SC_NS))
{
SC_CTHREAD(drive,clk.pos());
SC_THREAD(clkThread);
m_reg[ULPI_REG_VIDL] = 0x24;
m_reg[ULPI_REG_VIDH] = 0x04;
m_reg[ULPI_REG_PIDL] = 0x04;
m_reg[ULPI_REG_PIDH] = 0x00;
m_reg[ULPI_REG_FUNC] = 0x41;
m_reg[ULPI_REG_OTG] = 0x06;
m_reg[ULPI_REG_SCRATCH] = 0x00;
}
void clkThread(void)
{
while (true)
{
wait(oscillator.posedge_event());
clk.write (true);
wait(oscillator.negedge_event());
clk.write (false);
}
}
الكل. اكتمل التعديل الأول.
صنع ناقل بيانات ثنائي الاتجاه
يحتوي ULPI على ناقل بيانات ثنائي الاتجاه. وفي النموذج نرى الوصف التالي له:
sc_out <sc_uint<8> > ulpi_data_o;
sc_in <sc_uint<8> > ulpi_data_i;
اضطراب! سنقوم أولاً بعمل فراغ بناءً على ناقل الإخراج ، ثم نحول كل شيء إليه. من أين نبدأ؟ من حقيقة أن الناقل يجب أن يكون قادرًا على الانتقال إلى الحالة الثالثة ، وأن النوع sc_uint <8> يعمل فقط مع البيانات الثنائية. سيساعدنا النوع sc_lv <8> . لذلك نقوم بتغيير بيان الإطارات إلى:
sc_inout <sc_lv<8> > ulpi_data_o;
انتقل الآن إلى ملف ulpi_driver.cpp وابحث عن جميع المكالمات إلى الحافلة ulpi_data_o هناك . بشكل حدسي ، أدركت أنه لا يوجد سوى مكان واحد لإصلاحه:
نفس النص.
void ulpi_driver::drive_input(void)
{
// Turnaround
ulpi_dir_o.write(false);
ulpi_nxt_o.write(false);
ulpi_data_o.write(0x00);
wait(oscillator.posedge_event());
}
قم بتغيير الخط المحدد إلى
ulpi_data_o.write("ZZZZZZZZ");
الكل. يمكنك الآن بدلاً من سطرين:
sc_inout <sc_lv<8> > ulpi_data_o;
sc_in <sc_uint<8> > ulpi_data_i;
اكتب واحد:
sc_inout <sc_lv<8> > ulpi_data;
واستبدل جميع الإشارات إلى المتغيرات القديمة في كل من h-nick وفي cpp-shnik بالإشارة إلى المتغير ulpi_data .
أضف الأسماء المستعارة للمنافذ
وبالتالي. بعد بحث طويل ، توصلت إلى استنتاج (ربما يكون خاطئًا) أنه في بيئة ModelSim ، من السهل أخذ ورؤية المنافذ لوحدة منفصلة في SystemC باستخدام واجهة المستخدم الرسومية ، لا حظ. ومع ذلك ، إذا تم إدخال هذه الوحدة في نظام الاختبار ، فسوف تظهر. لكن أثناء البحث في النظرية ، وجدت كيفية تعيين أسماء مستعارة بشكل جميل لأسماء المنافذ. يبدو مُنشئ الفئة النهائية الآن كما يلي:
SC_HAS_PROCESS(ulpi_driver);
ulpi_driver(sc_module_name name): sc_module(name),
m_tx_fifo(1024),
m_rx_fifo(1024),
oscillator ("clk66",sc_time(15,SC_NS)),
rst_i ("rst"),
ulpi_data ("data"),
ulpi_dir_o ("dir"),
ulpi_nxt_o ("nxt"),
ulpi_stp_i ("stp")
{
SC_CTHREAD(drive,clk.pos());
SC_THREAD(clkThread);
m_reg[ULPI_REG_VIDL] = 0x24;
m_reg[ULPI_REG_VIDH] = 0x04;
m_reg[ULPI_REG_PIDL] = 0x04;
m_reg[ULPI_REG_PIDH] = 0x00;
m_reg[ULPI_REG_FUNC] = 0x41;
m_reg[ULPI_REG_OTG] = 0x06;
m_reg[ULPI_REG_SCRATCH] = 0x00;
}
عمل نظام اختبار
حسنا اذن. لم أتمكن من القيام بكل شيء تلقائيًا بحيث تقفز وحدتان تم تصحيحهما (رأس المحلل ونموذج ناقل ULPI) إلى ملف الاختبار بأنفسهما. ولكن دعونا نجري اختبارًا للرأس على الأقل ، ثم نضيف ULPI إليه. باستخدام التقنية من المقالة الأخيرة ، قمت بعمل نظام اختبار لملف ULPIhead.sv . لدي ملف يسمى sim1.v وسميت على الفور sim1.sv .
ثم أضفت وحدة ulpi_driver بالمقابض . يبدو النص الناتج myrun.do كما يلي:
vlog +../../SystemCPlay {../../MyCores/ULPIhead.sv}
sccom -g ../../SystemCPlay/ulpi_driver.cpp
sccom -link
vlog +../../SystemCPlay {../../SystemCPlay/sim1.sv}
vsim -voptargs="+acc" sim1
يتم تعذيب السطر الأخير. بدونها ، لا يحتوي كود Verilog على منافذ. من خلال تغيير معلمات التحسين ، يمكننا القضاء على هذه المشكلة. لقد رأيته في ملف * .do الذي تم إنشاؤه لمحاكاة نظامنا في البداية ، عندما كان كل شيء لا يزال يتم على الجهاز. صحيح ، هناك طابور طويل. لقد وجدت للتو المفتاح الذي يحل المشكلة ونسخها. وهكذا - لا أحب الطوابير الطويلة ، لقد ألقيت بكل شيء غير ضروري.
الآن نضيف كتلة ULPI إلى نظام الاختبار ونجري اختبارًا وهميًا. فقط للتأكد من أن جميع إشارات الساعة تدق وأن الحافلات مضبوطة على القيم الصحيحة.
حصلت على هذا الاختبار.
شاهد النص.
`timescale 1ns / 1ns
module sim1 ;
reg ulpi_dir ;
wire source_valid ;
wire ulpi_stp ;
reg ulpi_clk ;
reg ulpi_nxt ;
reg reset_n ;
reg read ;
reg [31:0] writedata ;
wire ulpi_rst ;
reg clk ;
wire [7:0] source_data ;
reg write ;
wire [7:0] ulpi_data ;
reg source_ready ;
reg [1:0] address ;
wire [31:0] readdata ;
always
begin
clk = 1;
#5;
clk = 0;
#5;
end
ULPIhead DUT
(
.ulpi_dir (ulpi_dir ) ,
.source_valid (source_valid ) ,
.ulpi_stp (ulpi_stp ) ,
.ulpi_clk (ulpi_clk ) ,
.ulpi_nxt (ulpi_nxt ) ,
.reset_n (reset_n ) ,
.read (read ) ,
.writedata (writedata ) ,
.ulpi_rst (ulpi_rst ) ,
.clk (clk ) ,
.source_data (source_data ) ,
.write (write ) ,
.ulpi_data (ulpi_data ) ,
.source_ready (source_ready ) ,
.address (address ) ,
.readdata (readdata ) );
ulpi_driver ULPI
(
.clk (ulpi_clk),
.rst (ulpi_rst),
.data (ulpi_data),
.dir (ulpi_dir),
.nxt (ulpi_nxt),
.stp (ulpi_stp)
);
initial
begin
reset_n = 1'b0;
source_ready = 1;
writedata = 0;
address = 0;
read = 0;
write = 0;
#20
reset_n = 1'b1;
end
endmodule
خاتمة
على أقل تقدير ، لقد أتقننا النمذجة في لغة SystemC باستخدام نظام ModelSim. ومع ذلك ، اتضح أن هذا يتطلب الوصول إلى إصدار 32 بت المرخص. لا يوفر الإصدار المجاني والإصدار 64 بت المرخص مثل هذه الفرصة. كما أفهمها ، يمكن عمل كل شيء مجانًا تمامًا في نظام Icarus Verilog ، لكنني لم أعرف بالضبط كيفية تحقيق ذلك. اتضح أنه من الأسهل بالنسبة لي الوصول إلى ModelSim المطلوبة. في المقالة التالية ، سوف نستخدم هذه المعرفة لنمذجة رأسنا.
أثناء العمل ، تم إجراء تعديلات معقدة للغاية على النماذج. يمكن تنزيل الملفات الناتجة هنا .