Menu

פרמטרים ב-Verilog: parameter ו-localparam למודולים גמישים

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

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

קבועים עם טוויסט

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

כך בונים IP רב פעמי. מודול FIFO עם הפרמטרים WIDTH ו-DEPTH יכול לשרת כל צוות בחברה. מונה עם פרמטר WIDTH הוא אותו קוד מקור, בין אם הוא סופר עד 16 ובין אם עד 4 מיליארד.

הצהרת פרמטר בסיסית

שלושה פריטי תחביר חדשים:

  1. בלוק פרמטרים: #( parameter WIDTH = 8 ) בין שם המודול לרשימת הפורטים. ערך ברירת המחדל 8 הוא מה שהמודול משתמש בו כשאף אחד לא דורס.
  2. מקום השימוש: output reg [WIDTH-1:0] count. הפרמטר הוא פשוט קבוע, ואנחנו מציבים אותו בטווח הביטים. אותו קוד מקור של מודול מייצר פלט של 8 או 16 ביטים, לפי WIDTH.
  3. תחביר הדריסה: counter #(.WIDTH(16)) dut16(...) בזמן יצירת המופע. בלוק ה-#(...) בא לפני שם המופע, אחרי שם המודול. פרמטרים שלא מזכירים שומרים על ברירות המחדל שלהם.

localparam: קבועים פנימיים

יש קבועים שאתם לא רוצים שמי שמשתמש במודול ידרוס. קידודי מצבים הם המקרה הקלאסי:

localparam הופך את IDLE, RUNNING, DONE לזמינים בתוך המודול, אבל לא ניתנים לדריסה ביצירת מופע. זו הבחירה הנכונה: לשנות מבחוץ איזה ערך מצב פירושו IDLE היה מפחיד.

השתמשו ב-parameter לדברים שמי שמשתמש במודול צריך להגדיר (רוחבים, עומקים, אפשרויות התנהגות), וב-localparam לכל השאר. תבנית נפוצה היא לגזור localparams מתוך parameters:

parameter WIDTH = 32;
localparam WIDTH_M1 = WIDTH - 1;   // computed once; not overrideable

רוחבים עם פרמטרים בפועל

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

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

כמה פרמטרים, דריסה לפי שם

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

module fifo #(
    parameter WIDTH = 8,
    parameter DEPTH = 16,
    parameter AFULL = DEPTH - 2
)(
    input  wire             clk,
    input  wire             reset,
    // ... ports ...
);
    // ...
endmodule

// At the call site:
fifo #(.WIDTH(32), .DEPTH(1024)) cmd_queue (.clk(clk), .reset(reset), ...);

לא חייבים לדרוס כל פרמטר; מי שלא מוזכר שומר על ברירת המחדל שלו. ברירת המחדל של AFULL בדוגמה מחושבת מתוך DEPTH, כלומר אם דורסים את DEPTH, גם AFULL מתעדכן אוטומטית. זה בדיוק סוג התלות ש-localparam היה מטפל בה גם, אם לא הייתם רוצים לאפשר לדרוס את AFULL בנפרד.

טעויות נפוצות

שכחת ה-# בדריסה. counter (.WIDTH(16)) dut(...) נראה כמו דריסה, אבל Verilog קוראת את (.WIDTH(16)) כחיבור פורט. צריך counter #(.WIDTH(16)) dut(...).

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

בלבול בין parameter ל-localparam ברשימות פורטים. רק parameter נכנס לבלוק ה-#(...) שבראש המודול. localparam חי בתוך הגוף. הקומפיילר יגיד לכם אם תחליפו ביניהם.

מה הלאה

עכשיו אתם יכולים ליצור מודולים שהגודל שלהם נקבע בזמן הקומפילציה. שני המסמכים הבאים עוסקים בכללים לכתיבת קבועים מילוליים (8'h1F, 4'b1010, 32'd100) ובערכים x ו-z שמופיעים כשאותות לא מוזנים או מתנגשים. אחרי זה נעבור לאופרטורים: כל מה שאפשר לעשות עם הווקטורים והפרמטרים שראיתם.

שאלות נפוצות

מה זה parameter ב-Verilog?

parameter הוא קבוע של זמן קומפילציה שמוצהר בתוך מודול. אפשר להשתמש בו בכל מקום שבו מותר קבוע: רוחבי אפיקים, עומקי זיכרון, קידודי מצבים, ערכי ברירת מחדל. והכי חשוב, כל מופע של המודול יכול לדרוס את הפרמטר, כך שאותו קובץ מקור יכול לייצר, למשל, מונה של 8 ביטים במקום אחד ומונה של 32 ביטים במקום אחר.

מה ההבדל בין parameter ל-localparam ב-Verilog?

ערכי parameter אפשר לדרוס מחוץ למודול כשיוצרים ממנו מופע. ערכי localparam אי אפשר: הם קבועים פנימיים בלבד. השתמשו ב-localparam לקידודי מצבים ולקבועים נגזרים שכותב המודול לא רוצה שמי שמשתמש בו ישנה.

איך דורסים parameter ב-Verilog?

כשיוצרים את המופע, מוסיפים בלוק דריסת פרמטרים לפני שם המופע: counter #(.WIDTH(16)) my_inst (.clk(clk), .count(count));. התחביר .WIDTH(16) קובע את הפרמטר הספציפי הזה; פרמטרים שלא מופיעים ברשימה שומרים על ברירות המחדל שלהם. כמה דריסות מופרדות בפסיקים בתוך ה-#(...).

מה זה מודול עם פרמטרים?

מודול שחושף הצהרת parameter אחת או יותר שמי שמשתמש בו יכול לדרוס. ל-FIFO עם פרמטרים יכולים להיות הפרמטרים WIDTH ו-DEPTH, כך שאותו קוד מקור מייצר FIFO של 32 ביטים בעומק 16 במקום אחד, ו-FIFO של 8 ביטים בעומק 1024 במקום אחר. כך נכתבות ספריות של בלוקי IP רב פעמיים.

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

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

להתחיל