1 - سطح گیت
جلسه اول (ماژول ها) جلسه دوم (گیت ها) جلسه سوم (نوع سیگنال) جلسه چهارم (پایان فصل)2 - مقداردهی مداوم
جلسه پنجم (اُپراتور ها) جلسه ششم (آرایه ها) جلسه هفتم (شرط ها) جلسه هشتم (فراخوانی ماژول) جلسه نهم (تست بنچ) جلسه دهم (نگاشت حافظه)3 - سطح رفتاری (ترکیبی)
جلسه یازدهم (بلاک Always) جلسه دوازدهم (ابزار ها) جلسه سیزدهم (نوع پردازش) جلسه چهاردهم (نکات تکمیلی) جلسه پانزدهم (پایان فصل)4 - سطح رفتاری (ترتیبی)
جلسه شانزدهم (لبه ها) جلسه هفدهم (تست بنچ 2) جلسه هجدهم (شمارنده ها) جلسه نوزدهم (ضرب و شیفت) جلسه بیستم (استیت ماشین) جلسه بیست و یکم (کشف رشته) جلسه بیست و دوم (فرکانس) جلسه بیست و سوم (نان بلاک) جلسه بیست و چهارم (پایان)5 - جلسات تمرینی
جلسه تمرین اول (تاخیر ها) جلسه تمرین دوم (الحاق-منطق) جلسه تمرین سوم (شیفت ها) جلسه تمرین چهارم (استیت)6 - مثال های پروژه محور
پروژه طراحی پردازنده RTL پروژه پردازنده Maano پروژه پردازنده MIPS7 - ارتباط و گفتگو
ارتباط با نویسنده گروه تلگرام تبلیغات و آگهیآموزش وریلاگ آموزش Verilog
این جلسه قراره با نوع جدیدی از اُپراتور ها (شرطی - منطقی) آشنا بشیم . خب منطق خودش چیه که اُپراتورش چی باشه ؟ در طبیعت یک چیزی یا هست یا نیست ، در دنیای دیجیتال بجای هست و نیست از صفر و یک استفاده می کنیم . من یا ایرانی هستم (1) یا ایرانی نیستم (0) ، البته در دنیای دیجیتال درباره صِفَت ها چیزی در میان نیست و فقط باید درباره مقادیر صحبت کنیم . اُپراتور های شرطی ، اُپراتور هایی هستن که شرط موردنظر کاربر رو بررسی میکنند ، اگه برقرار بود 1 رو به عنوان منطق برمیگردونن و اگه شرط مورد نظر برقرار نبود ، 0 رو به عنوان منطق برمیگردونن . به کد زیر دقت کنید :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17-
module Test( input [7:0] X ); if (X == 13) { } if (X > 13) { } endmodule
در کُد بالا عبارتِ == ، اُپراتور برابری هست و در صورت برابر بودن دو مقدار ، منطق 1 رو به if برمیگردونه و if متوجه میشه باید دستورات درون { } رو اجرا کنه . در خط بعدی عبارت < اُپراتور بزرگتری هست و در صورت بزرگتر بودن ، منطق 1 رو به if برمیگردونه و if دستورات مورد نظر رو اجرا میکنه. از دیگر اُپراتور های شرطی میشه به اُپراتور نابرابری =! ، اُپراتور بزرگتر مساوی =< ، اُپراتور کوچکتر مساوی => اشاره کرد .
اُپراتور های بعدی که قراره باهاشون آشنا بشیم ، اُپراتور های منطقی هستن ، این اُپراتور ها وظیفه ترکیبِ منطق هارو به عهده دارن ، با اُپراتور && میتونین دو یا چند منطق رو باهم اَند کنید ، با اُپراتور || میتونین دو یا چند منطق رو باهم اُر کنید و با اُپراتور ! میتونین یه منطق رو معکوس کنین. به مثال زیر دقت کنید :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18-
module Test( input [7:0] X, input [7:0] Y ); if (X < 10 && Y > 4 && (X+Y)==20) { } if (X > 13 || Y > 13) { } endmodule
در خط 6 ، سه منطق باهم اَند میشن و اگه هر سه 1 باشن ، حاصل اَند هم یک میشه و if اجرا میشه ، یعنی شرط تنها وقتی اجرا میشه که هم X از ده کوچیکتر باشه ، هم Y از چهار بزرگتر باشه و هم جمع این دوعبارت برابر با 20 باشه . در خط 12 ، دو منطق با هم اُر میشن و فقط کافیه حداقل یکی از شرط ها برقرار باشه ، حاصل اُر یک میشه و if اجرا میشه ، یعنی یا باید X بزرگتر از 13 باشه و یا Y بزرگتر از 13 باشه و یا اینکه هردوشون بزرگتر از 13 باشن . خب یه خبر بد واستون دارم ! ما اجازه نداریم در ساختار assign از if استفاده کنیم ، عبارت if رو فقط میشه در ساختار always استفاده کرد که در فصل بعدی مطرح میشه . در ساختار assign بجای عبارت if باید از عبارت ?( ) استفاده کرد، بجای عبارت elseif از عبارت ?( ): استفاده میکنیم و بجای عبارت else از دو نقطه : استفاده میکنیم . به مثال های زیر دقت کنید :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12-
module Test( input [7:0] X, output [7:0] F ); assign F=(X>8'd18)? 8'd12 : 8'd5; assign F=(X>18)? 12 : 5; assign F=(X>18)? 12 :(X>10)? 6 :(X>5)? 4 : 20; endmodule
خط 6 گفتیم ، اگه X از 18 بزرگتر بود F=12 بشه در غیر اینصورت F=5 بشه . در این خط مقداردهی اعداد را با فُرمت دهی انجام داده ایم . اما در خط بعدی این فُرمت دهی را کنار گذاشته ایم . خط 8 گفتیم ، اگه X از 18 بزرگتر بود F=12 بشه و اگر از 18 بزرگتر نبود F=5 بشه . در نهایت خط 10 گفتیم که اگه X بزرگتر از 18 بود F=12 بشه ، در غیر اینصورت اگه از 18 بزرگتر نبود بلکه از 10 بزرگتر بود F=6 بشه ، در غیر اینصورت اگه X از 18 و 10 بزرگتر نبود و از 5 بزرگتر بود F=4 بشه و در غیر اینصورت اگر X از 18و10و5 بزرگتر نبود، F=20 بشه. نکته : توی کُد بالا ، ما برای اعداد فُرمت مشخص نکردیم ، وقتی برای اعداد فرمت مشخص نکنید ، وریلاگ بصورت پیش فرض ، فرمت رو دسیمال در نظر میگیره (دسیمال همون سیستم دَهدهی روزمره خودمونه ) ، اگه میخواستیم فُرمت رو رعایت کنیم برای X>18 باید می نوشتیم X>8’d18 (یعنی هشت بیت داده با فرمت دهدهی و مقدار 18) .
شکل بالا یه مالتی پلکسر 4 به 1 هست که قراره کُد شو بنویسیم ، فقط توجه داشته باشید که سیگنال S2 و S1 مانند سیگنال های X ورودی هستند و سیگنال واسطه ای نیستن ، رنگ آبی شون گمراه تون نکنه . همچنین این سیگنال ها همگی تک بیتی هستن ، بُرداری یا چند بیتی نیستن ، اگه چند بیتی بودن ، بجای S1 و S2 میزدم: S[1] و S[2] . اگه احساس میکنید گیج میشید اسم اون دو بیت رو بذارید S و G ، من دوست داشتم اسم شون رو بذارم S1 و S2 ، اصلا دوست دارم اسم شون رو بذارم S56 و S77 ، مشکلیه ؟ خب بریم سراغ کد :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14-
module Multiplexer( input X1, input X2, input X3, input X4, input S1, input S2, output Y ); assign Y = (S1==0 && S2==0)? X1 :(S1==0 && S2==1)? X2 :(S1==1 && S2==0)? X3 :(S1==1 && S2==1)? X4 :0; endmodule
طبق کُد بالا ، اگه ورودی S1 و S2 هردو صفر بودن ، خروجی ماژول برابر است با مقداری که ورودی X1 دارد (Y=X1) ، در غیر اینصورت اگر تنها S2 یک بود ، خروجی من برابر است با مقداری که ورودی X2 دارد و به همین ترتیب رفتیم تا انتهای خط (البته کل کُد مون توی یه خط جا نشد ادامه اش رفت خط بعدی) .
نکته مهم : در این ساختار حتما باید انتهای عبارت شرطی ما به دو نقطه ":" ختم بشه . بنابراین اگه میتونید شرط تون رو طوری بنویسید که با ":" تموم بشه ولی اگه نشد یا نخواستید باید بصورت اجباری این دو نقطه رو بذارید و بگید در غیراینصورت مقدار خروجی تون چی بشه که معمولا میگیم صفر بشه یا HighZ بشه که من در مثال های این جلسه میگم صفر بشه پس انتهای عبارت های شرطی از 0 : استفاده میکنم .
حالا فرض کنید طبق شکل بالا ورودی های ما تک بیتی نبودن ، بلکه چندبیتی بودن، در اینصورت داریم :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10-
module Multiplexer( input [3:0] X, input [1:0] S, output Y ); assign Y=(S==0)? X[0] :(S==1)? X[1] :(S==2)? X[2] :(S==3)? X[3] :0; endmodule
اگه خسته نشدید ، بیاین یه حالت دیگه رو هم بررسی کنیم ، ایندفعه یه مالتی پلکسر 4 به 1 داریم که قراره بین چهار ورودی 8 بیتی ، یکی از اونهارو ببره به خروجی :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13-
module Multiplexer( input [7:0] X1, input [7:0] X2, input [7:0] X3, input [7:0] X4, input [1:0] S, output [7:0] Y ); assign Y=(S==0)? X1 :(S==1)? X2 :(S==2)? X3 :(S==3)? X4 :0; endmodule
به عنوان آخرین مثال جلسه هفتم ، قصد داریم یه دیکُدر رو پیاده سازی کنیم ، عملکرد دیکُدر در جدول زیر اومده :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11-
module DeCoder( input [1:0]X, input en, output [3:0] Y ); assign Y = (en==0)? 4'b0000 : (X==2'b00)? 4'b0001 : (X==2'b01)? 4'b0010 : (X==2'b10)? 4'b0100 : (X==2'b11)? 4'b1000 :0; endmodule
در اینجا من ورودی و خروجی هارو چند بیتی در نظر گرفتم و برای نوشتن اعداد هم بجای فُرمت دهدهی ، از فُرمت باینری استفاده کردم تا نحوه نوشتن شو آشنا بشید . ببینید توی تصویر سیگنال ها چند بیتی نبودن ، بلکه تک بیتی بودن با اسم های متفاوت اما من تصمیم گرفتم چند بیتی تعریف شون کنم تا حجم کُد کمتری رو داشته باشم ، بنابراین اینکه سیگنال هارو چند بیتی بگیریم یا نگیریم کاملا دل بخواهی هست . این جلسه خیلی طولانی شد ، بنابراین دو مبحث موند تحت عنوان "اُپراتور های منطقی در عبارات" و "الحاق سیگنال ها" که این دو بخش بسیار کاربردی هستند و حتما باید بلد باشید که من توی ویدئو کامل توضیح دادم می تونید دانلود کنید یا اینکه "تمرین (2)" میتونید بخونید. دانلود فیلم جلسه
رفتن به جلسه بعد ...