Menu

Timescale ו-delay ב-Verilog: שליטה בזמן הסימולציה

איך ההנחיה `timescale קובעת את היחידה של #delay, מה הכללים לשילוב יחידות שונות בין קבצים, ואיך השהיות מתנהגות לצד לוגיקה מתוזמנת בשעון.

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

מה המשמעות של "זמן" ב-Verilog

ל-Verilog אין מושג מובנה של שניות. הסימולטור מקדם "יחידות זמן", כלומר טיקים שלמים שרירותיים, והקוד שלכם משתמש ב-#N כדי להמתין N מהם. ההנחיה `timescale היא זו שממפה את הטיקים האלה לזמן אמיתי.

`timescale 1ns / 1ps

module test;
    initial begin
        $display("t = %0t", $time);   // 0
        #5;
        $display("t = %0t", $time);   // 5 ns
        #1.5;
        $display("t = %0t", $time);   // 6500 ps (or 6.5 ns)
        $finish;
    end
endmodule

שני פרמטרים:

  • יחידה (המספר הראשון): מה המשמעות של #1. 1ns אומר שטיק אחד הוא ננו-שנייה אחת.
  • דיוק (המספר השני): באיזו רזולוציה הסימולציה עוקבת אחרי הזמן בתוך היחידה. 1ps אומר שהשהיות שבורות מעוגלות לפיקו-שניות.

הדיוק לא יכול להיות גס יותר מהיחידה (1ps / 1ns אינו חוקי). בחירות נפוצות:

  • 1ns / 1ps: הסטנדרט בפועל. הכול בננו-שניות, עם דיוק מתחת לננו-שנייה לכל השהיית שער.
  • 1ps / 1ps: כשממדלים מעגלים מהירים במיוחד, או כשכל ההשהיות קצרות מננו-שנייה.
  • 1us / 1ns: לסימולציות איטיות בקנה מידה של מערכות משובצות (זמני בית ב-UART, פרוטוקולים איטיים).

איפה לשים את זה

`timescale היא הנחיית קומפיילר, לא מבנה ברמת המודול. היא נכתבת ממש בראש הקובץ, לפני כל module:

`timescale 1ns / 1ps

module foo(...);
    // ...
endmodule

התחום שלה הוא "מהנקודה הזו והלאה בסדר הקומפילציה, עד ה-`timescale הבא או סוף הקומפילציה". יש לזה השלכה עדינה: קובץ בלי `timescale מפורש יורש את מה שהצהיר הקובץ שקומפל לפניו, וזה תלוי בסדר שבו הקומפיילר קורא את הקבצים. הימנעו מההפתעה: שימו `timescale בראש כל קובץ.

העורך בדפדפן שבדפי התיעוד האלה קובע עבורכם timescale ברירת מחדל (בדרך כלל 1ns / 1ps), ולכן הדוגמאות בדפים הקודמים עבדו בלי להצהיר עליו. בפרויקט אמיתי כדאי להיות מפורשים.

#delay בפועל

אחרי `timescale 1ns / 1ps:

#5            // wait 5 ns
#100          // wait 100 ns
#1.5          // wait 1.5 ns (precision allows it)
#0.001        // wait 1 ps (just barely above precision)
#0            // zero-delay; useful for ordering events at the same time

בתוך בלוק initial או always, #N עוצר את הזרימה הפרוצדורלית למשך N יחידות זמן. הסימולטור משהה את הבלוק הזה (בלוקים מקבילים אחרים ממשיכים לרוץ) וממשיך אחרי ההשהיה.

אפשר להקדים השמה בהשהיה:

#10 a = 1;        // wait 10 ns, then assign
data <= #2 new_value;   // schedule the non-blocking assignment 2 ns from now

הצורה הראשונה היא כלי בסיסי ב-testbench. השנייה (השמה non-blocking עם השהיה) משמשת בסימולציה ברמת השערים כדי למדל השהיית התפשטות.

יצירת שעון

התבנית הקלאסית:

`timescale 1ns / 1ps

module test;
    reg clk = 0;
    always #5 clk = ~clk;
    // ...
endmodule

עם timescale של 1ns / 1ps, #5 הוא 5 ns. השעון מתהפך כל 5 ns, מה שנותן מחזור של 10 ns, כלומר שעון של 100 MHz. כדי לשנות את התדר, משנים את ההשהיה:

חצי מחזורמחזורתדר
#12 ns500 MHz
#2.55 ns200 MHz
#510 ns100 MHz
#1020 ns50 MHz
#2550 ns20 MHz
#50100 ns10 MHz

אם רוצים חצי מחזור שבור (#2.5), הדיוק צריך לתמוך בזה. דיוק של 1ps מטפל בכל ערך עד 0.001 ns, כך שכל תדר סביר יעבוד.

שילוב timescale שונים בין קבצים

בתכנון אמיתי יש הרבה קבצים, והם יכולים להצהיר על timescale שונים. הסימולטור משתמש ב-timescale של כל קובץ כדי לפרש את ההשהיות באותו קובץ. אם module_a.v מצהיר `timescale 1ns / 1ps ומשתמש ב-#5, מדובר ב-5 ns. אם module_b.v מצהיר `timescale 1us / 1ns ומשתמש ב-#5, מדובר ב-5 us.

רוב הזמן זה בלתי נראה, כי הסימולטור מציג ציר זמן גלובלי אחד בכל מקרה. אבל המשמעות היא שאותו #N בשני קבצים יכול לייצג דברים שונים לגמרי. הפתרון: בחרו timescale אחד (הסטנדרט בתעשייה הוא 1ns / 1ps) ושימו אותו בראש כל קובץ. אל תערבבו.

השהיות לא ניתנות לסינתזה

נקודה קריטית: #delay קיים רק לסימולציה. כלי הסינתזה קורא:

// In synthesizable RTL - WRONG
always @(posedge clk) begin
    out <= #2 in;
end

…ואז או מתעלם מה-#2 (רוב הכלים) או דוחה את המבנה (linter-ים מחמירים יותר). התזמון של חומרה אמיתית נקבע על ידי השעון ועל ידי השהיית ההתפשטות של השערים, ושניהם לא מופיעים בקוד המקור.

הכלל: השתמשו ב-# רק ב-testbench. ב-RTL שמיועד לסינתזה אין השהיות #. אם אתם מוצאים את עצמכם רוצים השהיה בקוד שמיועד לסינתזה, מה שאתם באמת צריכים הוא מונה שסופר לאחור עם השעון. כך חומרה אמיתית "ממתינה".

$time מול $realtime

שתי דרכים לקרוא את זמן הסימולציה הנוכחי:

  • $time מחזיר מספר שלם של 64 ביט ביחידות של היחידה של ה-timescale הנוכחי.
  • $realtime מחזיר real ביחידות של היחידה של ה-timescale הנוכחי, אבל בדיוק מלא.

לרישום לוגים ב-testbench, $time כמעט תמיד מספיק. השתמשו ב-$realtime רק כשצריך דיוק של פחות מטיק בפקודות הדפסה.

טיפים מעשיים

  • תמיד הצהירו על `timescale בראש כל קובץ. 1ns / 1ps הוא ברירת המחדל הבטוחה.
  • השתמשו ב-#delay רק ב-testbench. התייחסו להיעדרו מקוד שמיועד לסינתזה ככלל קבוע.
  • התאימו את מחזורי השעון לתדר היעד. אם אתם מדמים תכנון של 50 MHz, השתמשו במחזור שעון של 20 ns. מחזורים לא תואמים יכולים להסתיר באגים שרגישים לתזמון.
  • לגירויים שנספרים במחזורים, השתמשו ב-@(posedge clk) במקום #. זה עמיד לשינויים במחזור השעון.

מה הלאה

עכשיו ראיתם את כל הדפים במדריכי ה-Verilog האלה. מיסודות השפה (wire מול reg, מודולים, אופרטורים), דרך בלוקים פרוצדורליים ובקרת זרימה, אל תכנון סינכרוני ומכונות מצבים, ולבסוף כלי ה-testbench שמוכיחים שהכול עובד. הגיע הזמן לבנות משהו: העורך האונליין שליד דפי התיעוד האלה הוא אותו סימולטור שהשתמשנו בו לאורך כל הדרך, מוכן לכל מודול שתשרטטו.

שאלות נפוצות

מה המשמעות של `timescale 1ns / 1ps ב-Verilog?

ההנחיה אומרת לסימולטור: 'יחידת זמן אחת בקובץ הזה היא ננו-שנייה אחת, והזמנים נמדדים בדיוק של פיקו-שנייה.' אחרי ההנחיה, #5 ממתין 5 ns, #1.5 ממתין 1.5 ns (מעוגל לפיקו-שניות), ו-$time מדווח בננו-שניות. המספר הראשון הוא היחידה, והשני הוא הדיוק.

האם צריך `timescale בכל קובץ Verilog?

לפי הנוהג הטוב: כן. התחום של ההנחיה נגמר ב-\timescaleהבא או בסוף הקומפילציה, כך שקבצים בלי הנחיה משלהם יורשים את מה שהצהיר הקובץ שקומפל לפניהם. זה הופך את התזמון ללא דטרמיניסטי בין build ל-build. שימו`timescale 1ns / 1ps` בראש כל קובץ מקור (זו המוסכמה הנפוצה ביותר) ולא תופתעו לעולם.

מה המשמעות של #5 ב-Verilog?

#5 מקדם את זמן הסימולציה ב-5 יחידות זמן. היחידה מגיעה מהנחיית \timescaleהפעילה. עם`timescale 1ns / 1ps, #5הוא 5 ננו-שניות. עם`timescale 1us / 1ns, #5הוא 5 מיקרו-שניות. המספר יכול להיות שבר:#1.5` עובד אם הדיוק שלכם עדין יותר מהיחידה.

האם #delay ניתן לסינתזה ב-Verilog?

לא. #delay משפיע רק על הסימולציה: כלי הסינתזה מתעלם ממנו או דוחה אותו. התזמון של חומרה אמיתית נובע מאות השעון ומהשהיית ההתפשטות של השערים, לא מפקודות #. השתמשו ב-# בחופשיות ב-testbench, ולעולם אל תכתבו אותו ב-RTL שמיועד לסינתזה.

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

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

להתחיל