האנטומיה של ליטרל עם גודל
לליטרל ב-Verilog יש עד שלושה חלקים:
8'b1010_1100
│ │ │
│ │ └─ digits in the chosen base
│ └─── base specifier: b (binary), h (hex), d (decimal), o (octal)
└────── width in bits (decimal)
קוראים לפי סדר הכתיבה: "ערך של 8 ביטים, כתוב בבינארי, עם הספרות 10101100". זה 172 בעשרוני, 0xAC בהקסדצימלי: אותם ביטים, לא משנה איך כותבים אותם. הרוחב אומר לקומפיילר בדיוק כמה ביטים להקצות; הבסיס אומר לו איך לפרש את הספרות.
קווים תחתונים הם מפרידים ויזואליים. 32'b1010_1100_0011_0101 זהה ל-32'b1010110000110101. השתמשו בהם.
ארבעת הבסיסים
הקסדצימלי (h) הוא הסטנדרט לכל מה שרחב מ-4 ביטים. בינארי (b) הוא הסטנדרט כשרוצים לקרוא תבניות ביטים ישירות. עשרוני (d) מיועד לספירות שיש להן משמעות אנושית. אוקטלי (o) קיים, אבל כמעט אף פעם לא תראו אותו.
ספרות הקסדצימליות לא רגישות לאותיות גדולות וקטנות: 8'hAB ו-8'hab זהים.
מה קורה כשהערך לא מתאים לרוחב?
אם הספרות לא ממלאות את הרוחב שהוצהר, Verilog מרחיבה באפסים בצד הביטים העליונים:
8'b101 // equivalent to 8'b00000101 (= 5)
8'hF // equivalent to 8'h0F (= 15)
אם הספרות חורגות מהרוחב שהוצהר, Verilog קוטמת את הביטים העליונים עם אזהרה:
4'hFF // truncates to 4'hF, simulator warns
4'b10000 // truncates to 4'b0000
האזהרה היא חברה שלכם. אל תשתיקו אותה.
עם גודל מול בלי גודל
ליטרל בלי רוחב:
'd10 // unsized, takes default size (≥32 bits)
10 // also unsized - no base means decimal
ליטרלים בלי גודל מקבלים ברוב הכלים ברירת מחדל של 32 ביטים. זה המקור למשפחה שלמה של באגים:
reg [7:0] count;
if (count == -1) ... // -1 is unsized 32-bit; comparison gets weird
הפתרון הוא לכתוב 8'hFF במקום -1, או 8'd255, או {8{1'b1}}. תמיד תנו גודל לליטרלים כשמשתמשים בהם בביטויים שתלויים ברוחב.
המקום היחיד שבו ליטרלים בלי גודל בסדר הוא מוני integer בלולאות for של testbench, שבהם ה-integer רחב מספיק כך ששום דבר מפתיע לא קורה.
ליטרלים עם סימן
כברירת מחדל, ליטרלים עם גודל הם בלי סימן:
8'd255 // unsigned 255
8'b1111_1111 // unsigned 255 - same bit pattern, just written differently
אם רוצים שהליטרל יפורש עם סימן, מוסיפים s אחרי הגרש:
8'sd10 // signed 10
8'sb1111_1111 // signed -1 (two's complement)
הדגל s חשוב עבור:
- האופרטורים
<<<ו->>>(הזזות אריתמטיות): הם מרחיבים סימן של אופרנדים עם סימן. - אופרטורי השוואה בביטויים מעורבים עם סימן.
- ההמרות
$signed/$unsigned.
ברוב האריתמטיקה הרגילה על אותות אפיק, תשאירו את ה-s בחוץ.
ליטרלים מספריים עם X ו-Z
ספרה בליטרל יכולה להיות x (לא ידוע) או z (עכבה גבוהה):
8'bx הוא קיצור של "כל 8 הביטים לא ידועים": הערך מתפשט כדי למלא את הרוחב שהוצהר. ספרות x נפוצות במקרי default של מכונות מצבים ובאתחול. אנחנו מכסים את הסמנטיקה ב-ערכי X ו-Z.
איפה ליטרלים עם גודל מופיעים בפועל
ברגע שמתחילים לכתוב מודולים אמיתיים, ליטרלים עם גודל מופיעים בכל מקום:
// Bus widths
input wire [31:0] addr;
wire [31:0] zero = 32'h0;
wire [31:0] all_ones = 32'hFFFF_FFFF;
// State encodings
localparam IDLE = 3'd0;
localparam BUSY = 3'd1;
localparam DONE = 3'd2;
// Masks
wire is_msb_set = data & 32'h8000_0000;
// Comparisons
if (counter == 8'd255) ...
// Reset values
always @(posedge clk) begin
if (reset) data_out <= 8'd0;
else data_out <= data_in;
end
התבנית עקבית: כותבים את הרוחב, כותבים את הבסיס, כותבים את הספרות. לכל ליטרל שתשתמשו בו יש אותה צורה.
נסיעת מבחן
עכשיו יש לכם כל מה שצריך כדי לכתוב כל קבוע שמודול Verilog עשוי לרצות. החלק האחרון בסיפור של טיפוסי הנתונים הוא מה שקורה כשאות הוא לא 0 או 1 נקי: הערכים x ו-z.
שאלות נפוצות
מה המשמעות של 8'b1010 ב-Verilog?
זה ליטרל בינארי עם גודל: ערך של 8 ביטים שהייצוג הבינארי שלו הוא 00001010. המספר שלפני הגרש הוא הרוחב בביטים; האות שאחרי הגרש היא הבסיס (b בינארי, h הקסדצימלי, d עשרוני, o אוקטלי); הספרות שאחריה הן הערך. אם הספרות לא ממלאות את הרוחב, הליטרל מרופד באפסים בצד הביטים העליונים.
מה ההבדל בין מספרים עם גודל לבלי גודל ב-Verilog?
ליטרל עם גודל כמו 8'd10 הוא ברוחב של 8 ביטים בדיוק. ליטרל בלי גודל כמו 'd10 או פשוט 10 מקבל כברירת מחדל 32 ביטים, שזה בדרך כלל יותר מדי. ערבוב ליטרלים בלי גודל בביטויים שתלויים ברוחב גורם לבאגים עדינים: העדיפו ליטרלים עם גודל בכל מקום, חוץ מקוד בדיקה חד פעמי.
איך כותבים מספר הקסדצימלי ב-Verilog?
משתמשים במציין הבסיס 'h: 8'hFF הוא ערך של 8 ביטים ששווה 255. ספרות הקסדצימליות לא רגישות לאותיות גדולות וקטנות; 8'hff ו-8'hFF זהים. אפשר לקבץ ספרות עם קווים תחתונים לקריאות: 32'hDEAD_BEEF. המפענח מתעלם מהקווים התחתונים.
איך קווים תחתונים עובדים במספרים ב-Verilog?
קווים תחתונים הם מפרידים ויזואליים שהמפענח מתעלם מהם. 32'b1010_1100_0011_0101 הוא בדיוק אותו ערך כמו 32'b1010110000110101, אבל הרבה יותר קל לקריאה. התו הראשון אחרי קידומת הבסיס לא יכול להיות קו תחתון, אבל בכל מקום אחר במחרוזת הספרות אפשר לשים אותם.
איך כותבים מספר עם סימן ב-Verilog?
מוסיפים s אחרי הגרש: 8'sd10 הוא 10 עשרוני עם סימן ב-8 ביטים, ו-8'sb1111_1111 הוא -1 עם סימן. כברירת מחדל, ליטרלים עם גודל הם בלי סימן; המציין s הופך את זה. רוב האריתמטיקה משתמשת באופרנדים בלי סימן: פנו לערכים עם סימן רק כשבאמת צריך שערכים שליליים יעברו דרך <, >>> ואופרטורים דומים.