Menu

Verilog $display ו-$monitor: הדפסה מתוך testbench

איך $display, $write ו-$monitor עובדים: מצייני הפורמט שתשתמשו בהם, ההבדל ביניהם, ומתי כל אחד הוא הכלי הנכון.

בדף הזה יש עורכים שאפשר להריץ. לערוך, להריץ ולראות את הפלט מיד.

משפחת 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 מרפד לרוחב ברירת מחדל לפי גודל האופרנד. ל-reg של 8 ביטים זה 3 תווים (מקום ל-255). הרווחים המובילים יכולים להיראות מכוערים בפלט טבלאי, אז השתמשו ב-%0d כדי לבטל אותם.
  • ל-%h, %b, %o יש ריפוד דומה כברירת מחדל. רוב קוד ה-testbench משתמש בגרסאות %0 כשהיישור לא מועיל.
  • ירידת השורה בסוף אוטומטית. אל תשימו \n בסוף מחרוזת פורמט של $display, אחרת תקבלו שורה ריקה.

מצייני פורמט

הסט ש-Verilog תומכת בו:

מצייןמשמעות
%bבינארי
%dעשרוני (עם סימן אם האות מוצהר עם סימן)
%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, ה-monitor מופעל פעם אחת עם שני הערכים החדשים, לא פעמיים.

מתי להשתמש בכל אחד

  • $display: רוב הפלט של testbench. קראו לו במפורש אחרי גירוי, אחרי מעברי מצב חשובים, או בתוך בלוק דגימה always @(posedge clk).
  • $write: כשרוצים לבנות שורה אחת מלולאה או מכמה חלקים קטנים.
  • $monitor: כשרוצים לעקוב ברציפות אחרי קבוצה קטנה של אותות ולראות פלט רק כשהם משתנים. שימושי לדיבוג ראשוני; קשה יותר לשימוש בסקריפטים של רגרסיה, כי הפלט לא דטרמיניסטי מבחינת מספר השורות הכולל.

ברוב תהליכי העבודה $display מכסה הכול. פנו ל-$monitor רק כשפלט רציף שמונע משינויים הוא באמת מה שאתם צריכים.

עבודה עם זמן

$time מחזיר את זמן הסימולציה הנוכחי כמספר שלם של 64 ביטים. שלבו אותו עם %0t:

$display("at %0t: signal flipped", $time);

הפלט נראה כמו at 25: signal flipped (היחידה תלויה ב-timescale שלכם).

אם צריך דיוק של פחות מ-tick (נדיר), השתמשו ב-$realtime במקום: הוא מחזיר real.

%t מעצב אוטומטית זמן עם רוחב ברירת מחדל שהסימולטור בוחר. %0t מסיר את הריפוד.

דגימה בקצה השעון

ניב נקי למעקב אחרי תכנונים סדרתיים: בלוק always @(posedge clk) נפרד שמדפיס פעם אחת בכל מחזור:

תבנית הדגימה הזו מבטיחה שורת לוג אחת לכל שעון, מושלם לבדיקות רגרסיה שמשוות תבניות בפלט.

כתיבת לוג לקובץ

פותחים קובץ עם $fopen, וכותבים לוג עם $fdisplay (שעובד כמו $display אבל כותב ל-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 וכן הלאה. מעבר לזה, הפונקציות זהות לאחיות שלהן שמדפיסות לקונסולה.

מה הלאה

$display וחבריו נותנים לוגים טקסטואליים. לדיבוג ויזואלי, כלומר צפייה באותות כמתחים לאורך זמן, צריך waveform של VCD. המסמך הבא, Dumpfile ו-VCD, עוסק ב-$dumpfile וב-$dumpvars, שתי הקריאות שהופכות את הסימולציה ל-waveform גרפי שאפשר לגלול בו.

שאלות נפוצות

מה ההבדל בין $display ל-$monitor ב-Verilog?

$display מדפיס פעם אחת, מיד כשהוא מבוצע, כמו printf ב-C. $monitor רושם רשימת מעקב; בכל פעם שאות כלשהו ברשימה משתנה, ההודעה המעוצבת מודפסת אוטומטית. רק $monitor אחד יכול להיות פעיל בכל רגע; קריאה נוספת לו מחליפה את רשימת המעקב הקודמת.

באילו מצייני פורמט $display של Verilog תומך?

הנפוצים: %b (בינארי), %d (עשרוני), %h (הקסדצימלי), %o (אוקטלי), %c (תו יחיד מהבייט התחתון), %s (מחרוזת), %t (זמן סימולציה), %m (שם המופע ההיררכי). השתמשו בצורה %0d כדי לוותר על ריפוד באפסים מובילים: %d מרפד לרוחב ברירת מחדל, %0d לא מרפד בכלל.

מה זה $write ב-Verilog?

$write דומה ל-$display, אבל לא מוסיף ירידת שורה. שימושי כשרוצים לבנות שורת פלט מכמה קריאות. $display בסוף השורה (בלי ארגומנטים או עם ירידת שורה בסוף) סוגר את השורה.

איך מדפיסים את זמן הסימולציה ב-Verilog?

משתמשים ב-$time (או ב-$realtime לרזולוציה של פחות מ-tick) עם מציין הפורמט %t: $display("at time %t: ...", $time);. השתמשו ב-%0t כדי לבטל את ריפוד ברירת המחדל. לספירה פשוטה של יחידות זמן כמספר שלם, גם %0d עם $time עובד: $display("t=%0d", $time);.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל