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

להתחיל