Menu

אופרטורים ב-Verilog: אריתמטיקה, השוואה, לוגיקה ותנאי

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

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

מה "אופרטור" אומר ב-Verilog

אופרטורים מקבלים ביטויים שנושאים אותות ומפיקים ביטויים חדשים שנושאים אותות. a + b הוא חומרה: הסינתיסייזר הופך אותו למחבר. a == b הוא חומרה: הוא בונה משווה. שום דבר מזה אינו "קוד שרץ"; הכול הוא "מעגלים שהאופרטור מתאר".

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

אריתמטיקה: + - * / %

שלושה דברים שכדאי לדעת:

  1. חילוק הוא חילוק שלמים. 7/2 הוא 3, לא 3.5. ל-Verilog אין טיפוס float (טוב, יש real, אבל הוא לסימולציה בלבד).
  2. חילוק ושארית יקרים בחומרה. /4 זה בסדר (הסינתיסייזר הופך אותו להזזה ימינה), אבל /n עם n שמשתנה בזמן ריצה בונה מחלק רב מחזורי שכמעט אף פעם לא תרצו.
  3. גלישה מתגלגלת. חיבור של שני ערכים בלי סימן של N ביטים שחורג מ-N ביטים נקטם ל-N ביטים. אם רוצים ללכוד את הנשא, מצהירים על התוצאה ברוחב של ביט אחד יותר:
wire [7:0] a, b;
wire [8:0] sum = a + b;   // 9-bit sum captures carry out

השוואה: == != < > <= >=

כל ששת אופרטורי ההשוואה מחזירים תוצאה של ביט יחיד: 1 אם אמת, 0 אם שקר, x אם באחד האופרנדים יש ביט x או z. כדי לטפל במקרה של x/z, פנו ל-=== ול-!== (אופרטורי ה-case equality) שמוסברים ב-ערכי X ו-Z.

<= כאן הוא אופרטור ההשוואה (קטן או שווה). אותם תווים משמשים גם להשמה לא חוסמת בבלוק פרוצדורלי (q <= d). ההקשר מבחין ביניהם: בתוך ביטוי זו השוואה; אחרי היעד של השמה, זו ההשמה. החפיפה מבלבלת, אבל חד משמעית עבור המפענח.

לוגיקה: && || !

אופרטורים לוגיים מתייחסים לאופרנדים שלהם כערכים בוליאניים (כל דבר שונה מאפס הוא אמת, אפס הוא שקר) ומפיקים תוצאה של ביט יחיד:

ההבחנה הקריטית שצריך להפנים: && לוגי אינו & ביט אחר ביט.

4'b1100 && 4'b0011   // 1 (both are non-zero, logical AND is true)
4'b1100 &  4'b0011   // 4'b0000 (no bit positions are 1 in both)

אותו דבר לגבי || מול |. השתמשו באופרטורים לוגיים בתנאי if ובפרדיקטים של ?:; השתמשו ב-bitwise כשרוצים שכל מיקום ביט יעבור AND/OR באופן עצמאי.

&& ו-|| מבצעים short-circuit במובן של C: צד ימין לא מחושב אם התוצאה כבר נקבעה על ידי צד שמאל. זה חשוב ב-testbenches שבודקים מצביעים או קריאות לפונקציות; זה לעיתים רחוקות משנה ב-RTL בר סינתזה, שבו הכול קורה במקביל בכל מקרה.

האופרטור המותנה: ?:

האופרטור התלת מקומי הוא החבר הכי טוב שלכם לבניית muxes וביטויים מותנים:

התבנית cond ? a : b היא בחומרה multiplexer של 2 ל-1 עם בורר של ביט אחד. שרשור שלהם בסדר לבחירות של 3 ו-4 כיוונים, אבל מעבר לזה משפט case (מוסבר ב-משפט case) קריא הרבה יותר.

האופרטור ?: הוא גם הדרך הסטנדרטית לתת לאוגר ערך ברירת מחדל שדורסים רק לפעמים:

next_value = update ? new_data : next_value;

כללי רוחב: המלכודת של המתחילים

כללי הרוחב של Verilog לאופרטורים אריתמטיים ידועים כמפתיעים. הגרסה הקצרה:

  • הרוחב של התוצאה הוא המקסימום של רוחבי הכניסות.
  • אם התוצאה מושמת למשהו רחב יותר, היא מורחבת באפסים (או מורחבת סימן אם היא עם סימן).
  • הרוחב של חישובי ביניים הוא גם רוחב התוצאה, כלומר הגלישה קורית כבר בחישוב הביניים.

הכפל הראשון גולש כי רוחבי שני האופרנדים הם 8 ביטים, ולכן רוחב התוצאה הוא 8 ביטים, ו-40000 לא נכנס. השני עובד כי הרחבנו את a במפורש לפני הכפל.

טכניקות התיקון:

  • השתמשו באופרטור השרשור {8'b0, a} כדי להרחיב באפסים.
  • השתמשו ב-$unsigned(a) או ב-$signed(a) כדי להשפיע על הפרשנות.
  • כשיש ספק, המירו ביטויי ביניים לרוחבים גדולים יותר.

קדימות אופרטורים

לא תשננו את הטבלה, אבל תסמכו על כמה כללים:

  • *, /, % נקשרים חזק יותר מ-+, -.
  • השוואה נקשרת חזק יותר מאופרטורים לוגיים (&&, ||).
  • לאופרטור המותנה ?: יש קדימות נמוכה מאוד: בביטויים גדולים יותר בדרך כלל צריך סוגריים סביב הענפים שלו.
  • כשיש ספק, שימו סוגריים. הסימולטור לא גובה לפי תו.
out = (mode == 2'd0) ? a + b : a - b;   // clearer with parens

מה הלאה

כיסיתם את כל האופרטורים שנראים כמו בני הדודים שלהם בתוכנה. המסמך הבא, Bitwise ו-Reduction, עוסק באופרטורים שאין להם מקבילה ישירה בתוכנה: AND/OR/XOR לכל ביט, וצורות ה-reduction שמכווצות וקטור שלם לביט יחיד.

שאלות נפוצות

באילו אופרטורים Verilog תומכת?

ל-Verilog ארבע משפחות רחבות של אופרטורים: אריתמטיים (+, -, *, /, %), השוואה (==, !=, <, >, <=, >=), לוגיים (&&, ||, !), ו-bitwise/reduction (&, |, ^, ~, ~&, ~|, ~^). ובנוסף אופרטורי הזזה (<<, >>, <<<, >>>), שרשור {}, שכפול {N{...}}, והאופרטור המותנה ?:.

מה ההבדל בין && ל-& ב-Verilog?

&& הוא AND לוגי: הוא מתייחס לכל אופרנד כערך בוליאני (אפס או לא אפס) ומחזיר תוצאה של ביט אחד. & הוא AND ביט אחר ביט: הוא מצמיד ביטים לפי מיקום. 4'b1100 && 4'b0011 הוא 1 (שניהם שונים מאפס); 4'b1100 & 4'b0011 הוא 4'b0000. השתמשו ב-&& בתנאים, וב-& לפעולות ברמת הביט.

איך חילוק עובד ב-Verilog?

חילוק שלמים: החלק השברי נזרק. 7 / 2 הוא 3, לא 3.5. האופרטור % נותן את השארית: 7 % 2 הוא 1. חילוק באפס מפיק x (לא ידוע) בסימולציה. שני האופרטורים ניתנים לסינתזה מבחינה טכנית, אבל מייצרים חומרה גדולה ואיטית מאוד ב-FPGAs וב-ASICs: הימנעו מהם במסלולים ברי סינתזה, אלא אם המחלק הוא חזקה של 2.

מה זה האופרטור המותנה ב-Verilog?

?: הוא האופרטור התלת מקומי או המותנה, שהועתק מ-C. cond ? a : b מחושב ל-a אם cond אמת (שונה מאפס) ול-b אחרת. זה המבנה הנפוץ ביותר ללוגיקה בסגנון multiplexer: out = sel ? in1 : in0 בונה mux של 2 ל-1. שרשראות של ?: בונות muxes רחבים יותר, אם כי case בדרך כלל ברור יותר מעבר לשתי כניסות.

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

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

להתחיל