בנימין אברמוב ר"ד

Transcription

בנימין אברמוב ר"ד
‫הרצאה ‪21.10.12 -1‬‬
‫‪VHDL‬‬
‫ד"ר בנימין אברמוב‬
‫תוכן ההרצאות נמצא באתר‪/http://www.abramovbenjamin.net :‬‬
‫המצגת העיקרית ממנה נלמד הקורס‪.BVHDL :‬‬
‫אתר להורדה‪/http://www.altera.com :‬‬
‫להוריד את סביבת העבודה‪.Quartus II Subscription Edition Software Version 12.0 Service Pack 2 for Windows :‬‬
‫להוריד גם את‪ modelsim :‬עבור הסימולציות‪.‬‬
‫מייל של הקורס‪biu.vhdl@gmail.com :‬‬
‫במהלך הרצאה זו נלמדו השקפים הראשונים העוסקים ב‪ -‬מדע כדאי לכתוב ב‪ VHDL -‬וכיצד השפה התפתחה‪.‬‬
‫לא מצאתי לנכון לסכם משהו מדברים אלו – עמכם הסליחה‪.‬‬
‫‪|1‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪31.10.12 – 2‬‬
‫משפחות רכיבים‪:‬‬
‫המשפחה הבסיסית היא ‪ (Programmable Logic Device) PLD‬המכילה את‪.PAL , PLA , GAL PLD :‬‬
‫את כל אלו ראינו במעגלים ספרתיים הבנויים על סכום מכפלות או מכפלת סכומים‪.‬‬
‫הצעד הבא במשפחה הם הרכיבים הקרויים ‪ .CPLD‬הרעיון הוא הגדלה של השערים (עשרות אלפי שערים במקום מאות)‪.‬‬
‫בנוסף מוכנסים ‪ FF‬לכל מאקרו‪-‬תא המכיל מספר שערי ‪ AND‬ו‪ .OR-‬רכיבים אלו מאפשרים תכנות רב פעמי של עשרות אלפי‬
‫תיכנותים‪ .‬השלב האחרון במשפחה הם רכיבי ה‪ .FPGA-‬ה‪"-‬שחקנים" המובילים בייצור רכיבי ה‪ FPGA-‬הם‪,Xilinx (60%) :‬‬
‫)‪ Altera (35%‬ו‪.)5%( Others -‬‬
‫מבנה רכיב ‪:FPGA‬‬
‫הרכיב בנוי מבלוקים המחוברים לעולם החיצוני באמצעות ‪.)In/out Bit( IOB/IOE‬‬
‫יש לנו משאבים המאפשרים דגימת אות פנימה באמצעות ‪( FF‬שניים זמינים תמיד)‪.‬‬
‫כל הסיליקון חצוי באמצעות קווים הנקראים ‪.(Global Interconnect) GI‬‬
‫הם בעלי יכולת דחיפה גבוהה ומטרתם להזין צרכנים רבים‪.‬‬
‫ה‪ GI-‬מחלק את הרכיב לחלקים גדולים הנקראים )‪ LA (Logic Array‬ובתוכם יש ‪ )Block( LAB‬ולהם קווים ‪LI‬‬
‫ו‪ (Logic Element) LE-‬כל אלו מחולקים גם הם למקטעים שבשפתם יש אפשרות תכנות‪ .‬יחידה בסיסית ‪ LE‬מורכבת מ‪ FG -‬ו‪.FF-‬‬
‫רוב המערכות שמכילות רכיבי ‪ FPGA‬מכילות גם זכרון‪.‬‬
‫לשם כך הדרגה הבאה היא )‪ – SoC (System on Chip‬אלו רכיבי ‪ FPGA‬עם זכרון‪.‬‬
‫ברכיבים אלו יש לנו שורות של זכרונות המחולקים למקטעים (בד"כ ‪ .)4kb‬מערכים אלו הם גולמיים (‪ - SRAM‬יודעים רק לשמור)‬
‫המוקפים בלוגיקה‪ .‬ע"י הדו‪-‬שיח בניהם ניתן להפוך את הזכרון לכל סוג אחר ‪ ROM , RAM , FIFO , LIFO‬וכו'‪.‬‬
‫השלב האחרון הוא )‪ – SoPC (System on Programmable Chip‬אלו מכילות גם מעבד בתוכן המתפקד כבקרה על הכל‪.‬‬
‫הבקרה היא גם דינאמית‪ .‬יש שתי גישות לתיכון המעבד‪:‬‬
‫* גישה אחת היא ‪ – Hardcore‬בתוך אזור מסוים של הרכיב יש מעבד אחד (או יותר) והם לא גמישים‪.‬‬
‫* גישה שנייה היא ‪ – Softcore‬ניתן לתכנן את המעבד לפי מספר קונפיגורציות ומקבלים מהחברה את המעבד הניתן לשתילה בתוך‬
‫הרכיב‪ .‬ניתן לשתול עד ‪ 16‬מעבדים באופן כזה שהם יתפקדו בתקופה מירבית ביניהם‪.‬‬
‫דבר אחרון שנעשה בשנים האחרונות (לאחר שבלענו את המערכת השלמה בתוך השבב) קשור לפעולות ‪.DSP‬‬
‫לכן מפתחים תשתיות של מכפלות (פעולה דומיננטית ביותר לביצוע קונבולוציות ושאר פעולות ‪ DSP‬שכיחות) מלוטשות שכל‬
‫תפקידם הוא להכפיל בלבד (היתרון הוא יכולת גבוהה יותר ומהירות בעת ביצוע הפעולות)‪.‬‬
‫(מכפל בודד היום מסוגל לבצע הכפלה של ‪ 78‬ביטים במחזור שעון אחד בתדר של ‪ .)!!!800Mb/s‬למערכים אלו יש ריבוי שעונים‬
‫המנוהלים במערכות ‪ PLL‬ו‪ .DCM (Digital Clock Manager)-‬באמצעות מבנים אלו יש לנו שליטה על הפאזה של השעון‬
‫ומבטיחים נקודות דגימה יציבות של אותות‪.‬‬
‫‪|1‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪31.10.12 – 2‬‬
‫פותחים בשקף ‪.12‬‬
‫מספר‬
‫שקף‪:‬‬
‫‪23‬‬
‫‪24‬‬
‫‪25‬‬
‫‪27‬‬
‫‪28‬‬
‫‪29‬‬
‫‪30‬‬
‫‪31‬‬
‫‪32‬‬
‫‪36-37‬‬
‫‪38-39‬‬
‫‪40‬‬
‫‪46‬‬
‫‪|2‬‬
‫הערות שונות‪:‬‬
‫השוואה בין שפות תיכנות לשפות ‪ .HDL‬בשפות תיכנות הפקודות מתבצעות על כתובות ובצורה סדרתית‪.‬‬
‫הביטוי בשפת ‪ HDL‬מתאר פעולת חיבור ‪ Adder‬ופעולת כפל‪ .‬יש לנו לופ חומרתי הזוי ולכן הדבר לא מתאפשר‪.‬‬
‫יש לנו שני מבנים התלויים זה בזה הפועלים במקביל וזה מה שפוסל את הדבר‪( .‬הבעיה ב‪)A-‬‬
‫הדוגמא בשפת ‪ C‬נכונה אך אינה חכמה במיוחד (בלשון המעטה)‪ .‬המקרה ב‪ HDL-‬לא נכון כי שמים ל‪ D-‬שני דברים‬
‫יחדיו (על אותו החוט) ולכן הדבר לא אפשרי‪.‬‬
‫שוני בסדר הפעולות בשפת תיכנות יגרור שוני בתוצאות בניגוד ל‪.HDL-‬‬
‫השפה לא רגילה לגדלים‪ Der der DER :‬זהים‪.‬‬
‫דוגמא‬
‫צורות כתיבה‬
‫הערות כותבים עם‪-- :‬‬
‫מילים שמורות בשפה‪.‬‬
‫צורה לכתיבה הערות שלא יתייחסו אליהם בתהליך הסינתזה אך כן בתהליך הקומפילציה‪.‬‬
‫הגדרת פרמטרים‪.‬‬
‫דוגמא‪.‬‬
‫המצבים הקיימים )‪* .(Modes‬קיים מצב נוסף המשמש לכתיבה עם מערכות לא ספרתיות שלא מופיע במצגת‪.‬‬
‫המצב חוצץ מאפשר לכתוב נתונים החוצה וגם לקרוא נתון שכתבנו החוצה למשך החישובים שלנו בתוך הבלוק‪.‬‬
‫הרעיון הוא לאפשר לקבל ערך שהוצאנו במידה ויש בו צורך בשער כלשהו בתוך הבלוק‪ .‬אחרת נקבל שגיאת קומפילציה‪.‬‬
‫המצב ‪ inout‬מאפשר לקבל ערך מבחוץ לבפנים בניגוד ל‪ Buffer-‬שבו נשתמש כאשר הוא מוציא ערך אבל אנו רוצים‬
‫את הערך שלו מתוך הבלוק‪ .‬הפורט ‪ inout‬דורש בקרת נתונים‪*** .‬להוסיף סרטוט של ‪***inout‬‬
‫סוגי פרמטרים‪ .(Types) .‬בוליאן מאפשר פעולות מסוג אמת‪/‬שקר וביט מאפשר פעולות מסוג ‪.0/1‬‬
‫זה לא אותו דבר‪ .‬נציין כי הסוג של תוצאה זהה לסוג של מרכיביו‪ .‬הסוג ‪ integer‬מאפשר תוצאה שהיא ערך שלם‪.‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪7.11.12 – 3‬‬
‫סוגי פעולות וכלליהן‪:‬‬
‫בהרצאה קודמת למדנו על המבנה הכללי של הכתיבה ועל המצבים )‪.(Modes‬‬
‫ראינו כי חשוב לציין את סוג המשתנה )‪ (Type‬היות והוא מתורגם לחוטים ממשיים‪.‬‬
‫נתמצת את הסוגים המרכזיים והפעולות הכלליות באופן הבא‪:‬‬
‫‪Shift‬‬
‫‪V‬‬
‫‪V‬‬
‫‪Relation‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪logical‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪Arithmetic‬‬
‫‪V‬‬
‫‪V‬‬
‫‪V‬‬
‫‪Type \ Operation‬‬
‫‪Boolian‬‬
‫‪bit‬‬
‫‪bit_vector‬‬
‫‪integer‬‬
‫‪std_logic‬‬
‫‪std_logic_vector‬‬
‫הסוגים ‪ boolian‬ו‪ bit-‬מיוצגים ע"י קו חשמלי אחד‪ .‬הערכים שניתן להשים בהם הם‪ 'true','false' :‬ו‪ '0','1'-‬בהתאמה‪.‬‬
‫הסוג ‪ integer‬מתורגם אוטומטית ל‪ bus-‬של קווים – ‪ 32‬קווים‪.‬‬
‫הסוג ‪ std_logic‬הוא קם קו אחד (נדבר בהמשך) ו‪.std_logic_vector-‬‬
‫הפעולות שנדון עליהן הן‪ :‬פעולות אריתמטיות‪ ,‬פעולות לוגיות‪ ,‬פעולות השוואה ופעולות הזזה‪.‬‬
‫הפעולות האריתמטיות‪ :‬חיבור ‪ ,‬חיסור ‪ ,‬כפל ‪ ,‬חילוק ‪ ,‬חזקה ‪ ,‬ערך מוחלט ‪ ,‬מוד ו‪-‬שארית‪.‬‬
‫הסימנים בהתאמה‪.rem , mod , abs , ** , / , * , - , + :‬‬
‫פעולות חיבור‪ ,‬חיסור וכפל ניתנות לביצוע בין שני סוגים עם אותה כמות הביטים‪.‬‬
‫פעולת חלוקה בעייתית עקב עלות גבוהה של משאבים ומהווה צוואר בקבוק של המערכת‪ .‬לרוב היא תבוצע רק ב‪.int-‬‬
‫פעולת חזקה לא נתמכת בצורה מלאה בפעולות סינתזה אלא רק‪( 2**m :‬שקול להזזה) ו‪( m**2 -‬כפל)‪ .‬כל השאר בעייתיים‪.‬‬
‫פעולת ערך מוחלט נתמכת באופן מלא‪.‬‬
‫פעולות ‪ mod‬ו‪ rem-‬מתקבלות כתוצאה מחילוק‪ .‬כאשר נכתוב‪ a mod b :‬אם ‪ a‬שלילי נקבל תוצאה שלילית ואם ‪ b‬שלילי נקבל‬
‫‪ rem‬שלילי‪ .‬לצרכי יישום המערכת נשתמש באופרנד קבוע‪ ,‬חזקה של ‪ ,2‬כהמחלק שלנו‪.x mod n :‬‬
‫הפעולות הלוגיות הבאות‪ not , or , and , nor , nand , xor , xnor :‬ניתנות לביצוע באופן כללי‪.‬‬
‫בכתיבה מבצורה הבאה‪ x  s1 or s2 or s3 or s4 :‬הפעולות מבוצעות משמאל לימין באופן סדרתי‪.‬‬
‫כדי לשנות את הצורה נשתמש בסוגריים כגון‪. x   s1 or s2 or  s3 or s4 :‬‬
‫פעולות עם שלילה לא יבוצעו על שלוש כניסות אלא רק על ‪ ,2‬אחרת התכנית לא תעבור קומפילציה‪.‬‬
‫פעולות השוואה הן‪ .<= , >= , < , > , /= , = :‬התרגום בהתאמה‪ :‬שוויון‪ ,‬אי‪-‬שוויון ‪ ,‬קטן ‪ ,‬גדול ‪ ,‬קטן שווה ‪ ,‬גדול שווה‪.‬‬
‫ברגע שמבצעים פעולת השוואה מקבלים חזרה ערך ‪ boolian‬לכן בביטוי‪ d  s1 op s2 :‬ידוע כי ‪ d‬הוא בוליאני ו‪s2 , s1-‬‬
‫הם שני אופרנדים מאותו הסוג (כלשהו רק לא ‪ int‬כפי שמסומן בטבלה)‪.‬‬
‫פעולות הזזה הקיימות‪( sll :‬הזזה שמאלה ובביט הכי קטן יהיה אפס)‪( sla ,‬הזזה שמאלה כאשר הביט ‪ MSB‬הוא סימן)‪.‬‬
‫‪( srl‬הזזה ימינה) וכנ"ל‪ .sra :‬סיבובים‪( rol :‬סיבוב שמאלה) ‪( ror‬סיבוב ימינה)‪.‬‬
‫ניתן לבצע פעולה‪ s  a sll b :‬כאשר ‪ b‬הוא ‪ int‬המייצג כמה פעמים יש להזיז‪.‬‬
‫‪|1‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪7.11.12 – 3‬‬
‫להלן תכנית‪:‬‬
‫הקבועים ‪ m‬ו‪ n-‬הם מספרים שלמים ותמיד הולכים מה‪ MSB-‬כלפי ה‪.LSB-‬‬
‫מותר‪ ,‬אך לא כדאי ‪ ,‬שימוש בערכים שליליים‪ .‬מומלץ ש‪ n-‬יהיה אפס‪.‬‬
‫;)‪a: in bit_vector (m down to n‬‬
‫הכתיבה‪ a: bit_vector 1 to 8 ; :‬מעידה על כך שה‪ MSB-‬תמיד יהיה המספר הראשון (‪. )1‬‬
‫נכתוב גם‪ b: bit_vector  9 dwon to 2 ; :‬ו‪. c: bit_vector  7 dwon to 0 ; -‬‬
‫כעת הפעולה‪ c  a; :‬משמעה‪. c  7  =a 1 :‬‬
‫הפעולה‪ c  a and c; :‬משמעה‪. b 8  a  2  and c  6  ; , b  9   a 1 and c  7  ; :‬‬
‫ניתן לבצע פעולות ברמות ביטים בודדים ע"י שימוש באינדקס‪ .‬ניתן גם להשתמש בפעולות על חתיכה מהווקטור באמצעות‬
‫אינדקסים‪ .‬למשל‪. a  2 to 4  b 8 down to 6  xor c  2 down to 0  :‬‬
‫חשוב לשמור על הסינטקס בתוך האופרנדים‪ ,‬אם הראשון כתוב ב‪ down to-‬אז גם השני‪.‬‬
‫השמת קבועים‪:‬‬
‫שמים קבועים בשלב האתחול והם נכנסים לרגיסטרים באמצעות קווי הבקרה‪.‬‬
‫ערכים מסוג ‪ bit‬יכתבו‪ .'1' , '0' :‬ערכים מסוג בוליאני יהיו אמת‪/‬שקר‪ .‬ערכים מסוג ‪ int‬יהיו דצימלים כגון ‪.10‬‬
‫אם נרצה בסיס שונה יש לכתוב‪ base#const# :‬כגון‪ - 16#ABCD# :‬מספר הקסדצימלי ‪ ABCD‬על בסיס ‪.16‬‬
‫לא נשתמש בבסיסים "מרתקים" כגון ‪ 5 ,9‬וכו'‪...‬‬
‫ערכים קבועים מסוג ‪ bit_vector‬נכתבים כמחרוזות )‪ (string‬מה שחשוב הוא שמספר הביטים יהיו כמספר האובייקט המוגדר‬
‫כגון‪ . "0100111100" :‬מותר לציין שמדובר בווקטור בינארי ע"י הכתיבה‪. b"0100111100" :‬‬
‫בסיסים המותרים לשימוש הם אוקטלי והקסדצימלי‪ .‬למשל אוקטלי יכתב‪ . x  O"1234567"; :‬הקסדצימלי‪. x  X"1AFC"; :‬‬
‫מה שחשוב הוא שהערך שמתקבל כקבוע חייב להיות כפולה של ‪ 3‬או ‪ 4‬לפי הבסיסים‪.‬‬
‫כתיבה נוחה שקולה היא‪ . "01001000"  "0100_1000" :‬הקומפיילר לא מתרגש מזה וזה נוח יותר לקריאה‪.‬‬
‫השמות לתוך מחזורות‪:‬‬
‫נניח שיש לנו ;‪ . a,b,c,d: bit‬וגם‪ e: bit_vector  3 down ot 0 ; :‬נרצה לבצע השמה של ‪ a,b,c,d‬לתוך ‪.e‬‬
‫נוכל לכתוב‪ . e  3  a; e  2  b; e 1  c; e  0   d; :‬נוכל גם‪( e   a,b,c,d  ; :‬זאת השמה לפי מיקום)‪.‬‬
‫הסדר בצורות אלו משנה לנו ומשמעותי‪ .‬ניתן להכניס גם קבועים‪. e   a,"0",c,"1" ; :‬‬
‫ניתן לכתוב‪ . e  17  a,22  b,16 down to 9  "1",2:1:23:8  c , others  d  ; :‬כך שולטים בצורה גדולה יותר‪.‬‬
‫פעולת שרשור מחזורות נעשית באופן הבא‪:‬‬
‫; ‪e: bit_vector  7 down ot 0‬‬
‫;"‪e  "1" & b & 8 & O"6" & a & d & "0‬‬
‫חשוב להקפיד להשים את אותה כמות הביטים שממנה מורכב ‪ – e‬משתנה ההשמה‪.‬‬
‫‪|2‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪14.11.12 – 4‬‬
‫הסוגים‪ Std_Logic :‬ו‪:Std_logic_vec-‬‬
‫זכרונות סטטיים ניתנים לקריאה בכל עת בעוד שזיכרונות דינמיים דורשים ריענון מדי פעם אחרת הערכים שנקרא לא יהיו מדויקים‬
‫ולעיתים לא נכונים‪.‬‬
‫כדי לממש ביט ‪ inout‬נעזר בחוצץ ‪ 3‬מצבים )‪ (3 state buffer‬שהוא למעשה ‪ Transmission gate‬שראינו במעגלים ספרתיים‪.‬‬
‫ערך המוצא יכול לקבל ‪ 1 , 0‬או ‪.High-Z‬‬
‫‪ 9‬ערכים המזוהים במצב ‪:std_logic‬‬
‫‪ -U‬ערכים שלא אותחלו‪.‬‬
‫‪ –X‬התנגשות בין ‪ 0‬ו‪ 1-‬לוגים משני בלוקים אשר יצאתם מתחברת וברור כי הם מוצאים ערכים הפוכים‪.‬‬
‫‪ – 0,1‬ערכים תקינים‪.‬‬
‫‪ –W‬מצב התנגשות חלשה‪.‬‬
‫‪ –L,H‬רמה לוגית נמוכה‪/‬גבוהה לא תקינה‪.‬‬
‫'‪ – '-‬ערך ‪( .don’t care‬ערכים שאינן משפיעים מבחינתנו)‪ .‬כלי סינתזה לא אוהבים אותו בד"כ כי עלינו מוטלת החובה להחליט מה‬
‫לעשות עם כל ביט ולא לצפות מהמערכת לבצע זאת בשבילנו‪.‬‬
‫כדי להבין את משמעות ה‪ don’t care-‬נניח ‪ bus‬משותף למספר צרכנים‪ .‬כאשר יש צרכן שלא נבחר נוכל להשים את ערך זה‬
‫בכניסתו כאשר נתכנת אותו למצב ‪ .disable‬היתרון בכך הוא שערך תקין הנמצא בכניסה לבלוק במדובר – קשה מאוד להבחנה בחוץ‬
‫אם הוא נכנס או לא בעוד שאם נכנס ערך ‪ don’t care‬נוכל לזהותו במידה והוא נכנס‪.‬‬
‫נצטמצם לערכים '‪ 'X' , '0' , '1' , 'Z‬המותרים לסינתזה‪.‬‬
‫דוגמא של מצב נדיר הדורש שימוש ב‪:'X'-‬‬
‫‪If(S/=R) than‬‬
‫‪q  R,‬‬
‫‪elseif (S='0') than‬‬
‫;'‪q  'X‬‬
‫;‪endif‬‬
‫לגבי אי השוויון בכניסות אין כל בעיה כי זה בהחלט יתכן‪.‬‬
‫במצב של ‪ elseif‬אנו מכסים את המצב הלא‪-‬רצוי בכדי למנוע התנגשות‪ .‬למעשה יש לנו פה מימוש של ‪ SR-FF‬כאשר הצירוף '‪'00‬‬
‫הוא הצירוף האסור‪ .‬לכן אנו מגדירים אותו להיות '‪ 'X‬המתאר מצב‪-‬לא‪-‬מוגדר‪ .‬נציין כי אין צורך בתנאי '‪ S='0' && R='0‬מאחר‬
‫ומדובר במקרה ‪ elseif‬המדבר על מצב בו הביטים לא מקיימים את התכונה המתוארת ב‪ if(…)-‬ולכן ברור כי הם שווים‪.‬‬
‫בערך '‪ 'Z‬משתמשים במצבים נדירים בלבד כי אין להכניסו לתוך מערכת אלא הוא רק ביציאה‪.‬‬
‫‪ENB‬‬
‫‪i3‬‬
‫‪ENB‬‬
‫‪Dout‬‬
‫‪i2‬‬
‫‪Decoder‬‬
‫‪ENB‬‬
‫‪i1‬‬
‫‪ENB‬‬
‫‪|1‬‬
‫‪2‬‬
‫ערכי יציאה מותרים הם‪:‬‬
‫‪.1000 , 0100 , 0010 , 0001‬‬
‫צירופים אחרים יגררו מצב של‬
‫התנגשות‪ .‬בכל צירוף‪ ,‬שאר‬
‫היציאות שאינן ‪ 1‬יקבלו ערך של‬
‫‪.High-Z‬‬
‫‪i0‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪14.11.12 – 4‬‬
‫ספריות הרחבה לשימוש ב‪:std_logic-‬‬
‫;‪Library IEEE‬‬
‫;‪Use IEEE.std_logic_1164.all‬‬
‫עם ספריות אלו נוכל להשתמש בכל הפעולות על אובייקטים אלו מלבד פעולות אריתמטיות‪.‬‬
‫הספרייה שאחראית על זה היא‪.use IEEE.std_logic_arith.all :‬‬
‫כאשר מבצעים פעולות ‪ sign‬או ‪ unsign‬יש משמעות ולכן נוסיף את הספריות הבאות‪use IEEE.std_logic_unsigned.all :‬‬
‫או ‪ .use IEEE.stdlogic_signed.all‬אם נשתמש למשל בשורה‪ if(c>x"04") than :‬כאשר "‪ c=X"80‬חייבים להשתמש בסימן‬
‫כי הערך הנ"ל שלילי‪ .‬חשוב להתייחס לאותם הקווים החשמליים לכל אורך הדרך במערכות מרובות דרגות‪ .‬לכן נעבוד עם פורמט‬
‫אחד לכל תתי המערכות‪.‬‬
‫בסה"כ נכתוב את כל הספריות הבאות‪:‬‬
‫;‪Library IEEE‬‬
‫;‪use IEEE.std_logic_1164.all‬‬
‫;‪use IEEE.std_logic_arith.all‬‬
‫;‪use IEEE.std_logic_unsigned.all‬‬
‫בדיקת תכנון ‪:Test-Bench (TB) -‬‬
‫בדומה למעבדות – שבהן הכנסנו אותות חיצוניים – נבצע זאת גם כאן‪.‬‬
‫נכתוב בלוק ‪ UUT , DUT‬או ‪ MUT‬בהתאם לגודל אשר יימצא בתוך ה‪.TB-‬‬
‫עלינו לכתוב את ה‪ entity-‬של ה‪ TB-‬ולהצהיר על ה‪ DUT-‬כ‪.component -‬‬
‫כעת עלינו להצהיר סיגנלים הנכנסים לתוך ה‪ component-‬הנ"ל )‪ (TG – Test generator‬ויוצאים למוניטור כלשהו‪.‬‬
‫את כל הסיגנלים נאתחל בעת ההצהרה על מנת לא לקבל את '‪ 'U‬בהרצה‪.‬‬
‫איתחול סיגנל בעת ההצהרה נראה באופן הבא‪.signal s: type:=init_value; :‬‬
‫אחרי ‪ Begin‬מחברים את הסיגנלים אל ה‪ DUT-‬ב‪.Port map-‬‬
‫מחוללי האותות יכולים להיות כל דבר‪ .‬כדי לנדנד שעון בתכנון נכתוב‪.clk  not clk after 5ns; :‬‬
‫המילה ‪ after‬שמורה בזיכרון‪ .‬ניתן להגדיר זמנים מקנ"מ של שניות ועד ל‪.fs-‬‬
‫נציין כי השמה זו היא השמה מתמשכת )‪ (Continuous assignment‬אשר אינה ניתנת לסינתזה אך זה לא מעניין אותנו‪.‬‬
‫כדי ליצור נדנוד כלשהו של כל אות באפן חד פעמי נכתוב‪.s1  '0', '1' after 10ns , '0' sfter 20ns , …. :‬‬
‫נוכל להמשיך כך כמה שנרצה‪.‬‬
‫‪|2‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪21.11.12 – 5‬‬
‫בלוק ה‪:Process-‬‬
‫שפת ‪ VHDL‬כוללת מנגנון מובנה סגור הנקרא ‪ process‬ולו ניתן לתת תוויות ותיאור התהליך‪.‬‬
‫אופן הכתיבה הוא‪:‬‬
‫‪E1: process ( ) is‬‬
‫‪begin‬‬
‫;‪end process E1‬‬
‫כאשר ‪ E1‬הוא השם (אנו בוחרים) ובתוך הסוגריים נכנסת רשימת רגישות )‪ (sensitivity list‬המאפשרת גישה למשאבים שלו‬
‫בלבד‪ .‬פעולה זו פועלת במקביל ליתר התהליכים בקוד‪ .‬הרשמה כוללת סיגנלים שהשינוי שלהם משפיע על הפעולות שבתוך הבלוק‪.‬‬
‫לכן יש לכלול רק את הסיגנלים שמשפיעים על הפעולות‪ ,‬סיגנלים אחרים לא יכנסו‪.‬‬
‫הבלוק הנ"ל הוא יוצא דופן בשפה המתבצע בצורה סדרתית עפ"י הרצף הכרונולוגי של הפעולות הרשומות בו‪.‬‬
‫יחד עם זאת כל הבלוק עצמו פועל במקביל ליתר התהליכים‪ .‬זמן הביצוע של ‪ process‬הוא אפס מכיוון שמדברים על מודל אידילי‬
‫ללא זמן השהייה‪.‬‬
‫ניתן למיין ‪ process‬לשני סוגים‪:‬‬
‫ חומרה צירופית (א‪-‬סינכרונית) ללא התערבות של שעון‪.‬‬‫ חומרת סדרתית (סינכרונית) ובה מעורב שעון‪.‬‬‫הסוגים משליכים לכללי הכתיבה של התהליך‪ .‬באסינכרונים רשימת הרגישות כוללת את כל הסיגנלים שקוראים ערך שלו בין‬
‫להשמה בין להשאלה או תנאי – את כולם יש לכלול ברשימת הרגישות‪ .‬בתהליך סינכרוני כל הסיגנלים שנכנסים מייצגים ‪– FF‬‬
‫כולם בעלי זיכרון‪.‬‬
‫בדוגמא המופשטת להלן ניתן לראות כי מי שנכנס לרשימת הרגישות‬
‫הוא כל מי שלא תלוי בשעון כולל השעון‪:‬‬
‫שעון נכנס ושני הקווים ‪ Set‬ו‪.Reset (clr)-‬‬
‫‪Q‬‬
‫‪SET‬‬
‫‪in1‬‬
‫‪D‬‬
‫‪in2‬‬
‫‪clk‬‬
‫‪Q‬‬
‫‪CLR‬‬
‫היות ובשירשור של ‪ FF‬מקובלת ליצור קו קבוע שמאתחל את כולם ‪ -‬תמיד יש לכלול את ‪ .reset‬אין צורך גם ב‪ set-‬כי ה‪reset-‬‬
‫של דרגה אחת נכנס ל‪ set-‬של הדרגה הבאה‪.‬‬
‫;‪s  a and b‬‬
‫במקרה של שתי השמות לאותו הערך כגון‪:‬‬
‫;‪s  a or b‬‬
‫במקרה של ‪ decoder‬עם ביטים בכניסה שנסמן ‪ din‬ואת הביטים במוצא נסמן ‪ , dout‬נכתוב את ‪ din‬בתוך רשימת הרגישות‪.‬‬
‫בתוך הבלוק נכתוב‪ dout   others  '0' ; :‬ובשורה הבאה‪ . dout  conv_integer  din    '1'; :‬זו היא השמה כפולה‬
‫‪ ,‬למרות שהכתיבה חסרת משמעות‪ ,‬רק הפעולה האחרונה תבוצע‪.‬‬
‫אבל בתחילה קיבלנו אפס ורק לאחר מכן שמנו מספר‪ .‬הריאליזציה היא שבתחילה הכנסנו ל‪ dout -‬את‪ 00000000 :‬ולאחר מכן‬
‫כאשר מתקבל בכניסה ערך‪ ,‬למשל ‪ ,3‬נקבל שינוי ל‪.00001000 -‬‬
‫‪|1‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪21.11.12 – 5‬‬
‫דוגמא למימוש ‪ Xor‬בשני שלבים‪:‬‬
‫‪E1: process  a, b, c  is‬‬
‫‪begin‬‬
‫;‪s1  a xor b‬‬
‫;‪s 2  s1 xor c‬‬
‫;‪end process E1‬‬
‫עפ"י האמור לעיל‪ ,‬כל משתנה שמשנה ערך במוצא צריך להיכלל ברשימת הרגישות‪ ,‬לכן גם ‪.s1‬‬
‫במקרה שנוסיף אותו ניפול בבעיות סימולציות (בעיה של "ביצה ותרנגולת" בלתי פתירה)‪.‬‬
‫לכן במקרים מעין אלו יש לחלק לשני ‪ Process‬ואין מעבר‪.‬‬
‫בעיה הקשורה לרשימת הרגישות‪:‬‬
‫‪E1: process  a  is‬‬
‫‪begin‬‬
‫;‪s  a xor b‬‬
‫;‪end process E1‬‬
‫לכאורה אין ‪ b‬ברשימת הרגישות‪ .‬המעבד מבין זאת בכך שיש משמעות לכך שהוא לא הוכנס‪ .‬לכן הוא רוצה לקמפל את התהליך‬
‫באופן כזה ששינויי ‪ b‬לא ישפיעו‪ .‬לכן הוא יכניס את ‪ a‬לתוך ה‪ Xor-‬בצורה ישירה אבל ‪ b‬יחסם‪ .‬כדי לבצע זאת המעבד יחבר את‬
‫הכניסה הזאת ל‪ Latch-‬כאשר ה‪ enb-‬שלו יקבע ע"י ‪ a‬באופן הבא‪:‬‬
‫‪a‬‬
‫‪S‬‬
‫‪Q‬‬
‫‪Q‬‬
‫‪SET‬‬
‫‪D‬‬
‫‪b‬‬
‫‪CLR‬‬
‫‪Q‬‬
‫‪Q‬‬
‫‪SET‬‬
‫‪D‬‬
‫‪CLR‬‬
‫יש לנו פעמיים ‪( Xor 16‬כי המשתנים הם בעלי ‪ 16‬ביטים) וגם שני ‪ Lacth‬בעלי ‪ 4‬שערים לפחות כל אחד מהם‪.‬‬
‫הכפלנו את החומרה פי ‪ 8‬מהרצוי וקיבלנו התנהגות לא נכונה‪.‬‬
‫המסקנה היא להכניס לרשימה את כל הסיגנלים הרצויים!‬
‫‪|2‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
21.11.12 – 5 ‫הרצאה‬
E1: process  clk , arst  is
begin
if   then
elseif
:‫ בתוך בלוק באופן כללי‬if ‫אופן הכתיבה של‬
:‫ אסינכרוני‬enb ‫ עם‬FF ‫דוגמא למימוש של‬
  then
else
end if;
end process E1;
E1: process  clk , arst  is
begin
if  arst  '0 ' then
:‫ אסינכרוני‬enb ‫ עם‬FF ‫דוגמא למימוש של‬
q  '0 ';
elseif  clk' event and clk  1'1 then
q  d;
end if;
end process E1;
.‫ במקום השורה הארוכה‬elseif rising_edge  clk  then ‫דרך אחרת היא לכתוב‬
.‫ יגיב לאחד מהתנאים וזהו‬FF-‫ה‬
:T-FF ‫נכתוב‬
E1: process  clk , arst  is
begin
if  arst  '0 '  then
q  '0 ';
elseif rising_edge  clk  then
if  t  '1'  then
q  not q;
end if;
end if;
end process E1;
.‫הקוד כשר‬
‫ סיכום ועריכה מאת שי ידרמן‬-
VHDL
|3
21.11.12 – 5 ‫הרצאה‬
:JK-FF-‫דוגמא ל‬
E1: process  clk , arst  is
begin
if  arst  '0 '  then
q  '0 ';
elseif rising_edge  clk  then
if  J /  k  then
q  J;
elseif  J  '1'  then
q  not q;
end if;
end if;
end process E1;
:)‫ לא צריך להיכלל ברשימת רגישות כי הוא תלוי בשעון‬reset-‫ סינכרוני (כעת ה‬reset ‫ עם‬FF-‫דוגמא ל‬
.)‫ השעון וכל המשתנים שאינם תלויים בו ובלוק משתמש בהם בתנאים‬:‫(נזכור כי הגדרנו את המשתנים שנכנסים לרשימה‬
E1: process  clk  is
begin
if rising_edge  clk  then
d
SET
Q
clk
if  srst  '0 '  then
CLR
q  '0 ';
else q  d;
end if;
end if;
end process E1;
‫ סיכום ועריכה מאת שי ידרמן‬-
D
reset
Q
‫ תלוי בשעון כי‬reset-‫ה‬
‫המוצא ישתנה או שלא‬
‫בהתאם אליו אבל רק‬
‫ לכן‬.‫בעליית השעון‬
.‫אומרים שיש תלות‬
VHDL
|4
28.11.12 – 6 ‫הרצאה‬
:Process ‫המשך‬
:Mux ‫המבנה הבא מייצג‬
E1: process  x, y  is
begin
if  a  b  then
s  x;
else s  y;
end if;
end process E1;
Multiplexer
x
S1
y
S2
D
C
ENB
a=b
. a  b :‫ שהוא‬select ‫ עם‬mux ‫יש לנו כאן‬
:‫ נקבל את הסכמה הבאה‬.Latch ‫בפועל לא יכנס השוויון הנ"ל באופן ישיר אלא ע"י‬
Multiplexer
x
S1
D
SET
CLR
D
S2
Q
C
Q
ENB
y
D
SET
CLR
a
D
SET
CLR
b
D
SET
CLR
Q
Q
Q
Q
Q
Q
.)select ‫ אמורה להיות‬MUX-‫ של ה‬ENB ‫(באיור הנ"ל כניסת‬
‫ סיכום ועריכה מאת שי ידרמן‬-
VHDL
|1
‫הרצאה ‪28.11.12 – 6‬‬
‫דוגמא נוספת – ‪ process‬סינכרוני‪:‬‬
‫‪E1: process  clk , rst , ld , adat  is‬‬
‫‪begin‬‬
‫‪if  rst  '0 '  then‬‬
‫; ‪s   others  '0 ' ‬‬
‫‪elseif rising_edge  clk  then‬‬
‫;‪s  din‬‬
‫‪elseif  ld  '1' then‬‬
‫; ‪s  adat‬‬
‫;‪end if‬‬
‫;‪end process E1‬‬
‫המעבד יסמלץ את הדוגמא הנ"ל אך ישנה בעיה אחרת‪ .‬יש לנו כאן שימוש בלוגיקה סינכרונית ב‪ elseif-‬הראשון ושימוש‬
‫בלוגיקה א‪-‬סינכרונית בשני‪ .‬ל‪ Q-‬ניתן לגשת בשני דרכים‪ ,‬או בצורות א‪-‬סינכרוניות (‪ set‬ו‪ )reset-‬או באמצעות השעון (סינכרוני)‪.‬‬
‫אי אפשר יחד ולכן הפקודה פסולה‪ .‬העדיפות היא לגישה האסינכרונית‪ .‬כל מה שלא מיושם בדרך זו יוכל להתיישם בצורה סינכרונית‪.‬‬
‫לכן המודל עובר סימולציה אך לא סינתזה‪.‬‬
‫דוגמא נוספת‪:‬‬
‫‪E1: process  clk , rst , data  is‬‬
‫‪begin‬‬
‫‪if  rst  '0 ' then‬‬
‫;‪s  data‬‬
‫‪elseif rising_edge  clk  then‬‬
‫;‪s  din‬‬
‫;‪end if‬‬
‫;‪end process E1‬‬
‫הבעיה כאן שפוסלת את הפקודה היא שהבקשה הזויה‪ .‬מנסים לבצע טעינה אסינכרונית לתוך ‪.Q‬‬
‫למה רוצים לבצע זאת וכמה זה הולך לעלות לנו? התשובות לא כ"כ חיוביות‪..‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪D‬‬
‫‪3‬‬
‫)‪Data(4‬‬
‫‪reset‬‬
‫‪|2‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
28.11.12 – 6 ‫הרצאה‬
:‫ עם בקרת ספירה מעלה ומטה‬,‫ עם אפשור ספירה‬,‫ אסינכרוני‬reset ‫ עם‬,11 ‫דוגמא לכתיבת מונה עד‬
E1: process  clk , rst  is
begin
if  rst  '0 '  then
count   others  '0 '  then
elseif rising_edge  clk  then
din
Add/
sub
Up/
down
Multiplexer
S1
D
S2
1
0
enb
C
ENB
count
load
rst
if  load  '1'  then
count  din;
elseif rising_edge  enb  '1'  then
if  up _ ndwn  '1'  then
count  count  1;
else
count  count  1;
end if;
end process E1;
E1: process  clk , rst  is
begin
if  rst  '0 '  then
:)‫דוגמא חולנית במיוחד (לשון המרצה‬
q1  '0 ';
elseif rising_edge  clk  then
q1  d1;
q 2  d 2;
end if;
end process E1;
.reset-‫ לא מושפע מ‬q2 ‫ מוגדר לחלוטין אך המוצא‬q1 ‫ המוצא‬.‫ עבור שתי היציאות‬,FF 2 ‫רוצים לכתוב כאן‬
.)‫(נציין כי הסיבות ליצור דבר כזה צריכות להיות מאוד מדויקות היות ולא מקובל לדרוש דבר כזה‬
‫ ויש‬1 ‫ הוא‬reset ‫ כן מקבל משמעות נוספת והיא כאשר‬reset .‫ שומר על הערך שלו‬reset ‫ שבו‬q2-‫ ל‬FF ‫יש לנו כאן ניסיון לכתוב‬
:‫ בנפרד‬process ‫ כדי להתגבר על זה יש לכתוב‬.)‫עליית שעון הכניסה כן עוברת למוצא (מופיע באיור‬
E1: process  clk  is
begin
if rising_edge  clk  then
q 2  d 2;
end if;
end process E1;
‫ סיכום ועריכה מאת שי ידרמן‬-
d2
0
1
q2
rst
VHDL
|3
‫הרצאה ‪28.11.12 – 6‬‬
‫דוגמא אחרונה למימוש שני ‪:FF‬‬
‫‪E1: process  clk  is‬‬
‫‪begin‬‬
‫‪if rising_edge  clk  then‬‬
‫‪if  srst  '1'  then‬‬
‫;' ‪q1  '0‬‬
‫;‪else q1  d1‬‬
‫;‪q 2  q1‬‬
‫;‪end if‬‬
‫;‪end if‬‬
‫;‪end process E1‬‬
‫התכוונו לממש את המעגל הבא‪:‬‬
‫‪q2‬‬
‫‪q1‬‬
‫‪Q‬‬
‫‪Q‬‬
‫‪SET‬‬
‫‪Q‬‬
‫‪D‬‬
‫‪Q‬‬
‫‪CLR‬‬
‫‪SET‬‬
‫‪din‬‬
‫‪srst‬‬
‫‪D‬‬
‫‪CLR‬‬
‫‪clk‬‬
‫הבעיה היא ש‪ q2-‬נכלל במסגרת הרגישה ל‪ .reset-‬לא כתוב מה לעשות איתו כאשר ‪ reset‬הוא ‪.1‬‬
‫נקבל‪:‬‬
‫‪d2‬‬
‫‪Q‬‬
‫‪Q‬‬
‫‪SET‬‬
‫‪CLR‬‬
‫‪D‬‬
‫‪0‬‬
‫‪1‬‬
‫‪srst‬‬
‫‪Q‬‬
‫‪Q‬‬
‫‪SET‬‬
‫‪din‬‬
‫‪srst‬‬
‫‪D‬‬
‫‪CLR‬‬
‫‪clk‬‬
‫שוב יש לנו לוגיקה זיבלית‪ .‬הפתרון הוא להעביר את הפקודה ;‪ q2  q1‬או לפני הלולאה הפנימית או אחריה‪ .‬אז הכל יהיה בסדר‪.‬‬
‫סיכום‪:‬‬
‫בלוגיקה יש לנו שני עולמות – אסינכרונית (עדיפות ראשונה) וסינכרונית‪ .‬יש להתייחס רק לאירוע אחד (עלייה או ירידה) בלבד‪.‬‬
‫אין להתייחס (ולתכנת) למספר שעונים שונים הנכנסים לשעון של אותו ה‪.FF-‬‬
‫‪|4‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪5.12.12 – 7‬‬
‫כלים נוספים בכתיבה התנהגותית‪:‬‬
‫נלמד איך להתנות ביצוע של פעולה מסוימת המבוצעת באמצעות תהליך )‪.(process‬‬
‫בשונה מלולאת ‪ if‬אנו פותחים באופן הבא בו נבדק סיגנל אחד בלבד ביחס לערכים הקבועים של אותו הסיגנל‪:‬‬
‫‪case sig is‬‬
‫;‪when "001"  .........‬‬
‫;‪when "010"  .........‬‬
‫;‪when "001" c1|c2|c3|c4|c5  .........‬‬
‫;‪when 1 to 11  .........‬‬
‫;‪when 11 downto 1  .........‬‬
‫;‪when others  .........‬‬
‫;‪end case‬‬
‫בקטע קוד זה מופיעות כל צורות הכתיבה התקניות‪ .‬חשוב לפרט על כל הערכים שהסיגנל יכול לקבל‪.‬‬
‫לאחר החץ כותבים את כל המצבים שאנו רוצים שסיגנל יקבל ערכים לפיהם כגון‪.  s1  a  b; :‬‬
‫דוגמא‪:‬‬
‫;‪ s2  .........‬‬
‫;‪ s2  .........‬‬
‫;‪ s2  .........‬‬
‫;‪ s2  .........‬‬
‫‪case s1 is‬‬
‫"‪when "00‬‬
‫"‪when "01‬‬
‫"‪when "10‬‬
‫"‪when "11‬‬
‫;‪end case‬‬
‫הקומפיילר לא יעביר את זה כי הסיגנל הוא מסוג ‪ std_logic‬המכיל ‪ 9‬ערכים לכל ביט ולכן יש ‪ 11‬צירופים‪.‬‬
‫;‪when others  s2  .........‬‬
‫יש לנו ‪ 77‬צירופים שלא מכוסים ולכן נוסיף את השורה‪:‬‬
‫הבעיה היא מה לכתוב בתנאי של מקרה זה‪ .‬היות והדבר לעולם לא קורה במערכת אמיתית (כל המקרה ממומש באמצעות ‪)mux‬‬
‫נוכל לכתוב‪  s 2  y; :‬למשל‪ .‬נניח כי זה הוא גם הערך שמתקבל כאשר‪when "11"  s 2  y; :‬‬
‫אז נעדיף לחבר ולכתוב‪:‬‬
‫‪case s1 is‬‬
‫;‪when "00"  s2  .........‬‬
‫;‪when "01"  s2  .........‬‬
‫;‪when "10"  s2  .........‬‬
‫;‪when others  s 2  y‬‬
‫;‪end case‬‬
‫זה הוא פתרון אך קטע קוד זה אינו ברור בעליל לכל נפש ולכן מקובל להשתמש במילה שמורה ‪ NULL‬באופן הבא‪:‬‬
‫;‪when others  NULL‬‬
‫השימוש ב‪ NULL-‬מותנה בכך שיש לנו זכרונות מכיוון שאי‪-‬עשייה היא פעולה הדורשת זיכרון‪.‬‬
‫‪|1‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪5.12.12 – 7‬‬
‫לולאות‪:‬‬
‫קיים כלי חזק מאוד המאפיין לנו כתיבת קוד התנהגותי המשמש תיאור של מערכות הפועלות בצורה איטרטיבית‪.‬‬
‫לצורך כך קיימות לולאות – יש לנו ‪ 3‬סוגים של לולאות שונות‪.‬‬
‫נדבר היום על לולאת ‪:for‬‬
‫‪for i in n to m loop‬‬
‫)‪( m downto n‬‬
‫;‪end loop‬‬
‫נציין כי הגדרת משתנה האינדקס היא לוקלית‪ ,‬אין צורך להגדיר אותו בחוץ והוא מת מיד בתום הלולאה‪.‬‬
‫חייב להתקיים‪. m  n :‬‬
‫ניתן גם להשתמש בפקודות‪ next :‬ו‪ exit-‬המשמשות כ‪ count-time-‬ו‪ break-‬בהתאמה‪.‬‬
‫בפקודה ‪ next‬קופצים לסוף הלולאה אם התנאי מתקיים‪ .‬בפקודה ‪ exit‬נקפוץ גם על השורה ‪ end loop‬ונצא לגמרי מהלולאה‪.‬‬
‫מקובל להשתמש בתוויות ללולאות (במערכות גדולות) ואז נוסיף‪ L1: for in n to m loop :‬וגם בשורה האחרונה‪.‬‬
‫דוגמא‪:‬‬
‫‪L1: for . . . . loop‬‬
‫‪L2: for . . .‬‬
‫‪L3: for . . .‬‬
‫;‪End loop L3‬‬
‫;‪End loop L2‬‬
‫;‪End loop L1‬‬
‫באיזה שלב שנכתוב את הפעולות ‪ next‬ו‪ exit-‬אנו נצא מהלולאה המכוננת המסוימת שבה הם נמצאים‪.‬‬
‫הערות‪:‬‬
‫‪.1‬נזכור כי בקלות ניתן לשרוף משאבים ע"י שימוש בריצות ארוכות מדי‪.‬‬
‫‪ . 2‬חשוב להבין את טיב החומרה הכתובה בלולאות אחרת הקומפיילר לא יעבד אותה מכיוון שהכל ממומש לחומרה‪.‬‬
‫דוגמא לכתיבת ‪:priority encoder‬‬
‫‪E1: process  din  is‬‬
‫‪begin‬‬
‫; ‪dout  others  '0 ' ‬‬
‫‪for i in din'renge loop‬‬
‫; ‪dout  i   din  i ‬‬
‫; ‪exit when  din  i   '1' ‬‬
‫;‪end loop‬‬
‫;‪end process E1‬‬
‫‪|2‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
5.12.12 – 7 ‫הרצאה‬
:‫נציין צורות כתיבת נוספות‬
.‫ כפי שהוגדר‬s ‫ – מחזיר את הטווח של הסיגנל‬s'renge
.s ‫ – מחזיר את הטווח בצורה הפוכה של הסיגנל‬s'reverserenge
.s ‫ – מחזיר את האורך של‬s'length
.‫ – מחזיר את הערך הנמוך ביותר בטווח‬s'low
.‫ – מחזיר את הערך הגבוה ביותר בטווח‬s'high
.‫ – מחזיר את הערך השמאלי ביותר בטווח‬s'left
.‫ – כנ"ל עם הערך הימני ביותר בטווח‬s'right
signal s : stdlogic_vector 15 downto 0  ;
:shift left register ‫דוגמא למימוש‬
E1: process  clk , rst  is
begin
if  rst  '0 '  then
s   others  '0 '  ;
elseif rising_edge  clk  then
if  enb  '1' then
for i in s'reverserenge loop
if  i  s 'low  then
s  i   sin;
else s  i   s  i  1 ;
end if;
end loop;
end if;
end if;
end process E1;
:‫ניתן לכתוב בצורה יעילה וקריאה יותר את הלולאה האחרונה באמצעות השורה הבאה‬
s  s   s'high-1 downto s'low  & sin ;
‫ סיכום ועריכה מאת שי ידרמן‬-
VHDL
|3
12.12.12 – 8 ‫הרצאה‬
:‫הערה בנוגע להקצאת זיכרון המתבצעת ע"י המחשב בזמן סימולציה של תוכנית‬
int ‫ בתים (המון!) מומלץ לעבוד כמה שיותר עם סוגים זולים כגון‬8 ‫היות והקצאת הזיכרון לביט בודד בסימולציה של תוכנית היא‬
‫ הערכים‬9 ‫ וידוע כי הביטים לא אמורים כלל לקבל ערכים מסוים מתוך‬std_logic-‫ ניתן במצבים שמשתמשים ב‬.boolian ‫או‬
. s  to_01ZX  s1 ; :‫ באופן הבא‬to_01ZX , to_01Z , to_01 :‫שהכרנו לכתוב המרה שמקלה על הזיכרון‬
.to ‫ אבל יכול לקבל רק את הערכים הנקובים בפונקציה‬S ‫ והוא מושם לתוך‬std_logic ‫ הוא מסוג‬S1 ‫הסיגנל‬
.‫פעולה זו מאפשרת לזיכרון להקצות פחות מקום העת ההרצה וחוסכת זמן במהלך הסימולציה‬
:Generic Constant – ‫קבועים כלליים‬
:‫לאחר השורה הראשונה ניתן להגדיר קבועים באופן הבא‬
entity e_name is
generic ( cont1: type:= init_value ; const2: type := init_value; . . . )
port (
);
end entity e_name;
:‫כל קבוע מקבל סוג ומספר התחלה כגון‬
entity gcnt is
generic (side : integer : = 100 )
port (
clk : in std_logic ;
rst : in std_logic ;
din : in std_logic_vector ((size-1) downto 0 ) ;
ld : in std_logic ;
en : in std_logic ;
dout : in std_logic ((size-1) downto 0 )
);
end entity gcnt;
architecture arc_ gcnt of gcnt is
signal out: std_logic_vector (dout'range);
begin
process (clk , rst) is
begin
if (rst = '0') then
out  (others  '0');
elseif rising_edge (clk) then
if (ld = '1') then
out  din;
elseif (en ='1') then
out  af+1;
end if;
end if;
end process;
dout  count;
end architecture;
‫ סיכום ועריכה מאת שי ידרמן‬-
VHDL
|1
12.12.12 – 8 ‫הרצאה‬
Port map -‫ אם הוא נכנס בתוך ה‬.‫ הולך להיות בכל התכנית יש לאתחל אותו בהגדרתו‬Generic-‫אם ה‬
.‫אפשר להשאיר ריק‬
:Generate ‫לולאת‬
.‫ עבור פעולות גדולות יותר‬component ‫המטרה היא לכתוב באופן כללי יותר‬
.component ‫ פעמים‬n ‫ לא נכתוב‬.‫ ביטים‬2 ‫ של‬Adder ‫ ביטים באמצעות‬n ‫ של‬adder ‫נניח שרוצים לממש‬
Carry_out-‫ ו‬Carry_in ‫ כל הבלוקים המשורשרים אליו הם בעלי‬,carry_in ‫ בלוק ראשון הוא ללא‬,‫ מקרים‬3 ‫נציין כי יש לנו‬
:‫ נכתוב‬.n+1-‫ בערך הביט ה‬Carry_out :‫והבלוק האחרון מחליף‬
g1: for i in a'reverse_range generate
g2: if (i=a'low) ganarate
u1: fa
port map ( a  a(i) ,
b  b(i)
ci  '0',
s  s(i),
co  c(i)
);
end_ganarate g2;
g3: if (i=a'high) generate
u1 : fa
port map
( a  a(i) ,
b  b(i) ,
ci  c(i-1) ,
s  s(i) ,
co  s(i+1)
);
end_ganarate g3;
g4: if (i/= a'low and i/= a'high) generate
u1 : fa
port map
( a  a(i) ,
b  b(i) ,
ci  c(i-1) ,
s  s(i) ,
co  c(i)
);
end_ganarate g4;
end_ganarate g1;
‫ סיכום ועריכה מאת שי ידרמן‬-
VHDL
|2
‫הרצאה ‪12.12.12 – 8‬‬
‫ניתן לפשט את התמונה ולחסוך את ההתמודדות עם מקרי הקצה‪ .‬עלינו להגדיל את שרשרת ה‪ ,Carry -‬לקבוע אותה כ‪ 11-‬ביט במקום‬
‫‪ 11‬ואז נוכל לדלג על הרבה שלבים ע"י שנכתוב פשוט (מחוץ למסגרת ‪:)Generate g1‬‬
‫;'‪c(0)  '0‬‬
‫;)‪s(16)  c(16‬‬
‫כעת עלינו לכתוב רק את ה‪ port map-‬הראשון‪.‬‬
‫ניתן התייחסות ל‪ generic-‬בתוך חומרה באופן הבא‪:‬‬
‫נניח ויש לנו חומרה כלשהי ‪ ,s‬ואנו רוצים להתייחס למשתנה כללי אז יש להשים ‪ .Register‬מבצעים זאת כך‪:‬‬
‫"‪generic ( kind_of_output: string:= "registered"); -- "unregistered‬‬
‫) "‪g1: if (kind_of_output ="unregistered‬‬
‫;‪dout  s‬‬
‫;‪end generate g1‬‬
‫‪g2: if (kind_of_output ="registered" ) generate‬‬
‫‪process (din) is‬‬
‫‪begin‬‬
‫‪if rising_edge (clk) then‬‬
‫;‪dout  s‬‬
‫;‪end if‬‬
‫;‪end process‬‬
‫;‪end generate g2‬‬
‫‪:Wait Statement‬‬
‫השימוש ב‪ wait-‬בא במקום רשימת הרגישות ומתבצע בתוך התהליכים בלבד‪ .‬הם לא יבואו יחד‪ .‬יש לנו ‪ 4‬צורות לשימוש בהם‪:‬‬
‫‪ - wait; .1‬עצירה של תהליך לנצח‪ .‬נשתמש בו לביצוע חד פעמי של תהליך ללא אפשרות חזרה‪.‬‬
‫‪ - wait for time units; .2‬עצירה למשך זמן מסוים‪ ,‬כאשר ב‪ time-‬נכתוב את הזמן שלנו וב‪ units-‬את יחידות הזמן‪.‬‬
‫‪ wait on s1,s2,….,sn; .3‬מחכים עד לשינוי לכל כיוון של לפחות אחד מהסיגנלים המופיעים ברשימה‪.‬‬
‫‪ wait until (cond.); .4‬מחכים עד למילוי התנאי הכתוב בסוגריים‪.‬‬
‫כאשר משתמשים ב‪ wait-‬כל הסיגנלים שלפניו מתעדכנים גם אם העצירה היא ל‪"-‬אפס" זמן‪.‬‬
‫נציין כי ב‪ VHDL-‬ניתן להגדיר משתנה מסוג ‪ time‬שכל תפקידו הוא לקבוע משך זמן‪.signal t : time; :‬‬
‫הפונקציה ‪ Now‬מחזירה את ערך הזמן הנוכחי‪ .‬ניתן להשתמש באופן הבא‪( .t1  now; :‬כאשר ‪ t1‬מוגדר סוג ‪.)time‬‬
‫ניתן להגדיר אותה בתור תנאי‪. if (now_t1) > 100 ns then :‬‬
‫ניתן לשלב בין הצורות‪ .wait on rst until rising_edge(clk) for 1 us; :‬מחכים לשילוב של שינוי ב‪ reset-‬יחד עם עליית שעון‬
‫או עד ‪ ,1us‬מה שבא קודם‪.‬‬
‫‪|3‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
‫הרצאה ‪19.11.11 – 9‬‬
‫מבני מערכות‪:‬‬
‫באיור הבא יש לנו מבנה כללי של מערכת ספרתית‪.‬‬
‫השכבה המקווקות היא שכבת החומרה )‪ (Hardware‬הנשלטת ע"י מערכת תוכנה )‪.(Software‬‬
‫תפקיד החומרה הוא עיבוד נתונים דרך ה‪ .Operational Unit-‬אלו הם רכיבים "דלי מוח" הנשלטים ע"י ה‪.Control Unit-‬‬
‫הבקר שולח מילות בקרה המאפשרות שליטה מלאה על ה‪ OU-‬דרך ה‪ Control-‬והחומרה מעדכנת את הבקרה באמצעות קווי המצב‬
‫(‪ .)Status‬כלפי חוץ – כשעולים לשכבת התוכנה )‪ – (Software‬יש לנו את הבקרה החיצונית ‪ external control‬ואת דיווח מצב‬
‫‪.external status‬‬
‫‪din‬‬
‫‪Data‬‬
‫‪Path‬‬
‫)‪(OU‬‬
‫‪control‬‬
‫‪ext.cntrl.‬‬
‫‪FSM‬‬
‫)‪(CU‬‬
‫‪status‬‬
‫‪microC/‬‬
‫‪user etc.‬‬
‫‪ext.statu‬‬
‫‪s.‬‬
‫‪dout‬‬
‫החומרה ניתנת לסיווג למכונות מילי )‪ (mealy‬ומקרים פרטיים של ‪.moore‬‬
‫להלן תרשים זרימה של מכונת המצבים‪:‬‬
‫(הקו המקווקו קיים רק ב‪.)Mealy-‬‬
‫‪next state‬‬
‫‪in‬‬
‫‪out‬‬
‫‪next‬‬
‫‪state‬‬
‫‪logic‬‬
‫‪current‬‬
‫‪state‬‬
‫‪state‬‬
‫‪Reg.x‬‬
‫‪output‬‬
‫‪logic‬‬
‫ב‪ moore-‬מבקשים בקשה‪ ,‬המערכת מתכנסת ומוציאה מוצא במצב הבא‪ .‬ב‪ mealy-‬המוצא נכנס גם לכניסה‪.‬‬
‫ב‪ mealy-‬המוצא הוא פונקציה של הכניסה והמצב הנוכחי‪ ,‬לכן בשינוי הכניסה‪ ,‬המוצא משתנה מיד ועימו גם המצב הנוכחי ואז פעם‬
‫נוספת משתנה המוצא עקב היותו תלוי בשניהם‪ .‬לכן יש לנו סכנה בקבלת שרשרת של תגובות במוצא‪.‬‬
‫ב‪ VHDL-‬כותבים את ההתנהגות של המכונה (ולא טבלאות כפי שראינו במל"ס)‪ .‬להלן תיאור מכונת מצבים פשוטה‪:‬‬
‫_‪write‬‬
‫‪mem‬‬
‫‪y2‬‬
‫‪y2‬‬
‫‪x1‬‬
‫‪y1‬‬
‫‪idle‬‬
‫‪x1 x2‬‬
‫‪y1‬‬
‫‪x1‬‬
‫‪y1 y2‬‬
‫‪x1 x2‬‬
‫_‪read‬‬
‫‪mem‬‬
‫‪y2‬‬
‫‪x2‬‬
‫אנו נכתוב מעל ה‪ entity-‬את הסוג של הגדרת המצבים שלנו באמצעות ‪ type‬באופן הבא‪type fsm_st is ( ) :‬‬
‫כאשר בסוגריים נכתוב את המצבים‪ .)idle , read mem , write mem) :‬מגדירים גם את האותות‪.signal ns , cs : fsm_st ; :‬‬
‫מקובל לרשום את הערך הנמוך ביותר בתחילת הסוגריים ולאחריו את הערכים בסדר גדל‪ .‬המבנה הקלאסי של מכונת המצבים מתואר‬
‫בסכמה לעיל‪ .‬ה‪ state Reg-‬הוא לוגיקה ישירה‪ .‬ה‪ NS-‬הם לוגיקה צירופית המקבלת הוראות מה לעשות ובאיזה מצב אנחנו‪ .‬כנ"ל‬
‫לגבי ה‪ .Output-‬נזכור כי עוסקים בלוגיקה צירופית ולכן יש לכסות את כל המצבים אחרת נקבל ‪-latch‬ים‪.‬‬
‫חובה להגדיר את המצב ההתחלתי שבו המכונה מתעוררת‪ .‬בעמוד הבא מופיע תיאור המלא‪.‬‬
‫‪|1‬‬
‫‪VHDL‬‬
‫‪ -‬סיכום ועריכה מאת שי ידרמן‬
19.11.11 – 9 ‫הרצאה‬
type fsm_st is (idle , read mem, write mem);
signal ns , cs : fsm_st;
begin
state_reg : process (clk , rst) is
begin
if (rst <= '0') then
cs <= idle;
elseif rising_edge (clk) then
cs<=ns;
endif;
end process state_reg;
common_logic: process (cs , x) is
-- ‫הלוגיקה עבור המצב הבא והמוצא זהה ולכן כותבים תהליך פעם אחת‬
begin
ns<=cs; -- ‫שורה זו תורמת לקיצור הכתיבה בכך שהמצב הבא יקבל תמיד את הערך המצב הנוכחי בהתאם לקייסים‬
y[2]<= '0' ;
y[1]<='0';
case cs is
when idle => if ( x[1]='1') then
ns <=read_mem;
y[2] <='1';
elseif ns<=idle;
y[1]<='1';
endif;
when read_mem => if (x[2]='1') then
ns <=write_mem;
y<='11';
elseif (x[1] = '0') then
ns<=idle;
y[1]<='1';
else ns<=read_mem;
y[2]<='1';
endif;
when write_mem => ns<=idle;
y[2]<='1';
end case;
end process;
‫ סיכום ועריכה מאת שי ידרמן‬-
VHDL
|2