عائلة C printf في Verilog
ثلاث مهام نظام تتيح لك الطباعة إلى stdout للمحاكي:
$display- تطبع مرة، تُلحق سطرًا جديدًا.$write- تطبع مرة، بلا سطر جديد.$monitor- تطبع تلقائيًا في كل مرة تتغير فيها إشارة مُراقبة.
كل الثلاث تأخذ سلسلة تنسيق وقائمة حجج، مثل printf تمامًا. محددات التنسيق مشابهة لكنها خاصة بـ Verilog.
$display: الافتراضي
$display هو حصان العمل:
سترى شيئًا مثل:
Hello, world.
byte_val = ab
byte_val = 10101011
byte_val = 171
byte_val = 171 (no padding)
multi: nibble=1010 count=42
ملاحظات:
%dيحشو إلى عرض افتراضي مبني على حجم المعامل. لـreg8 بت، هذا 3 أحرف (مكان لـ255). المسافات البادئة قد تبدو قبيحة في الخرج الجدولي - استخدم%0dلقمعها.%hو%bو%oلها حشو مشابه افتراضيًا. معظم شيفرة testbench تستخدم متغيرات%0عندما لا تكون المحاذاة مفيدة.- السطر الجديد في النهاية تلقائي. لا تضع
\nفي نهاية سلسلة تنسيق$display- ستحصل على سطر فارغ.
محددات التنسيق
المجموعة التي يدعمها Verilog:
| المحدد | المعنى |
|---|---|
%b | ثنائي |
%d | عشري (signed إن كانت الإشارة signed) |
%h أو %x | ست عشري |
%o | ثُماني |
%c | حرف ASCII واحد (البتات 8 السفلى) |
%s | سلسلة |
%t | زمن المحاكاة |
%m | الاسم الهرمي للنطاق الحالي |
%% | % حرفي |
%0X | بلا حشو بادئ، لأي من %b، %d، إلخ. |
%b و%d و%h و%o هي الأربعة التي ستستخدمها 95% من الوقت. %t هو الأكثر شيوعًا بعد ذلك - أي وقت تريد سطر سجل مختوم بالزمن.
$write: بلا سطر جديد
$write مطابقة لـ $display باستثناء أنها لا تُلحق سطرًا جديدًا:
الخرج:
abc
done
مفيد لبناء سطر واحد من جسم حلقة:
$write("[");
for (integer i = 0; i < 8; i = i + 1) $write("%h ", arr[i]);
$display("]");
$monitor: طباعة تلقائية عند التغيير
$monitor تسجّل قائمة مراقبة. يُعيد المحاكي التقييم ويطبع كلما تغيّرت أي إشارة مذكورة في سلسلة التنسيق:
سترى ثلاثة أسطر، واحد لكل تغيير في المدخلات. لا حاجة لاستدعاء $display يدويًا بعد كل تغيير تحفيز - $monitor يفعل ذلك.
قيدان:
- يمكن أن يكون
$monitorواحد نشطًا. استدعاؤها مرة أخرى يستبدل قائمة المراقبة السابقة. استخدم$monitoroffو$monitoronلتعطيل وإعادة تفعيل مؤقت. - التغييرات داخل نفس الخطوة الزمنية تنهار إلى طباعة واحدة. إن تغيّر
aوbكلاهما عند الزمن 5، يُطلق المراقب مرة بكلا القيمتين الجديدتين، لا مرتين.
متى تستخدم كل واحدة
$display: معظم خرج testbench. استدعِها صراحةً بعد التحفيز، بعد انتقالات الحالة المهمة، أو داخل كتلةalways @(posedge clk)للأخذ بالعينات.$write: عندما تريد بناء سطر واحد من حلقة أو عدة قطع صغيرة.$monitor: عندما تريد تتبّع مجموعة صغيرة من الإشارات باستمرار ورؤية الخرج فقط عندما تتغير. مفيد للتنقيح الأولي؛ أصعب للاستخدام في سكربتات regression لأن الخرج غير حتمي بعدد الأسطر الإجمالي.
لمعظم سير العمل، $display تغطي كل شيء. ألجأ إلى $monitor فقط عندما يكون الخرج المستمر مدفوعًا بالتغيير هو ما تريد فعلًا.
العمل مع الزمن
$time تُرجع زمن المحاكاة الحالي كعدد صحيح 64 بت. اقرنها مع %0t:
$display("at %0t: signal flipped", $time);
الخرج يبدو مثل at 25: signal flipped (الوحدة تعتمد على timescale لديك).
إن احتجت دقة sub-tick (نادر)، استخدم $realtime بدلًا من ذلك - يُرجع real.
%t يُنسّق الزمن تلقائيًا بعرض افتراضي يختاره المحاكي. %0t يجرّد الحشو.
أخذ العينات على حافة Clock
اصطلاح نظيف لمراقبة التصاميم التسلسلية: كتلة always @(posedge clk) منفصلة تطبع مرة لكل دورة:
نمط أخذ العينات هذا يضمن سطر سجل واحد لكل clock - مثالي لاختبارات regression التي تطابق نمطًا على الخرج.
التسجيل إلى ملف
افتح ملفًا بـ $fopen، سجّل بـ $fdisplay (الذي يعمل مثل $display لكنه يكتب إلى file handle):
integer fd;
initial begin
fd = $fopen("results.txt", "w");
$fdisplay(fd, "test=%s status=%s", test_name, status);
$fclose(fd);
end
$fopen يُرجع handle 32 بت؛ مرّره كأول حجة لـ $fdisplay و$fwrite و$fstrobe وهكذا. الدوال متطابقة فيما عدا ذلك مع أشقائها الطابعين للـ console.
ماذا بعد
$display وأخواتها يعطيانك سجلات نصية. للتنقيح البصري - مراقبة الإشارات كجهد عبر الزمن - تريد VCD waveform. المستند التالي، Dumpfile وVCD، يغطي $dumpfile و$dumpvars، الاستدعاءان اللذان يحوّلان محاكاتك إلى waveform رسومي يمكنك التمرير خلاله.
الأسئلة الشائعة
ما الفرق بين $display و$monitor في Verilog؟
$display تطبع مرة، فورًا، عند تنفيذها - مثل printf في C. $monitor تسجّل قائمة مراقبة؛ كلما تغيّرت أي إشارة في القائمة، تُطبع الرسالة المُنسّقة تلقائيًا. يمكن أن يكون $monitor واحد نشطًا في كل مرة؛ استدعاؤها مرة أخرى يستبدل قائمة المراقبة السابقة.
ما محددات التنسيق التي يدعمها Verilog $display؟
الشائعة: %b (ثنائي)، %d (عشري)، %h (ست عشري)، %o (ثُماني)، %c (حرف واحد من البايت السفلى)، %s (سلسلة)، %t (زمن المحاكاة)، %m (الاسم الهرمي للنسخة). استخدم شكل %0d لإسقاط حشو الأصفار البادئة - %d يحشو إلى عرض افتراضي، %0d ينتج بلا حشو.
ما هي $write في Verilog؟
$write مثل $display لكنها لا تُلحق سطرًا جديدًا. مفيدة عندما تريد بناء سطر خرج من عدة استدعاءات. $display نهاية السطر (بلا حجج أو بسطر جديد لاحق) ينهي السطر.
كيف أطبع زمن المحاكاة في Verilog؟
استخدم $time (أو $realtime لدقة sub-tick) مع محدد تنسيق %t: $display("at time %t: ...", $time);. استخدم %0t لقمع الحشو الافتراضي. لعدّاد عدد صحيح عادي من وحدات الزمن، %0d مع $time يعمل أيضًا: $display("t=%0d", $time);.