1 - سطح گیت
جلسه اول (ماژول ها) جلسه دوم (گیت ها) جلسه سوم (نوع سیگنال) جلسه چهارم (پایان فصل)2 - مقداردهی مداوم
جلسه پنجم (اُپراتور ها) جلسه ششم (آرایه ها) جلسه هفتم (شرط ها) جلسه هشتم (فراخوانی ماژول) جلسه نهم (تست بنچ) جلسه دهم (نگاشت حافظه)3 - سطح رفتاری (ترکیبی)
جلسه یازدهم (بلاک Always) جلسه دوازدهم (ابزار ها) جلسه سیزدهم (نوع پردازش) جلسه چهاردهم (نکات تکمیلی) جلسه پانزدهم (پایان فصل)4 - سطح رفتاری (ترتیبی)
جلسه شانزدهم (لبه ها) جلسه هفدهم (تست بنچ 2) جلسه هجدهم (شمارنده ها) جلسه نوزدهم (ضرب و شیفت) جلسه بیستم (استیت ماشین) جلسه بیست و یکم (کشف رشته) جلسه بیست و دوم (فرکانس) جلسه بیست و سوم (نان بلاک) جلسه بیست و چهارم (پایان)5 - جلسات تمرینی
جلسه تمرین اول (تاخیر ها) جلسه تمرین دوم (الحاق-منطق) جلسه تمرین سوم (شیفت ها) جلسه تمرین چهارم (استیت)6 - مثال های پروژه محور
پروژه طراحی پردازنده RTL پروژه پردازنده Maano پروژه پردازنده MIPS7 - ارتباط و گفتگو
ارتباط با نویسنده گروه تلگرام تبلیغات و آگهیآموزش وریلاگ آموزش Verilog
این جلسه به بررسی استیت ماشین ها خواهیم پرداخت . ایشالا که میدونید استیت ماشین یا دیاگرام حالت چیه ؟ اگه نمیدونید لطف کنید برید از روی کتاب یا اینترنت بخونید و بعد بیاید سراغ این جلسه . فارغ از اینکه استیت ماشین چیه ، باید به این نکته دقت کنید که ما توی وریلاگ از قضیه استیت ماشین دو جا استفاده میکنیم . اول جاهایی که بما شماتیک یه استیت ماشین رو دادن گفتن کد وریلاگ شو بنویس ، یعنی دقیقا چیزی که این جلسه قراره بهش بپردازیم . اما جای دیگه ای که از استیت ماشین استفاده میشه بحث استراتژی هست ، ما میتونیم مسائل مختلف رو با استراتژی استیت ماشین ها حل کنیم ، یعنی خود مسئله رو بما میدن میگن کد برنامه فلان رو بنویس ، ما خودمون میایم مسئله رو به یه استیت ماشین تبدیل میکنیم و حلش میکنیم . که توی جلسه تمرین 4 یه ضرب کننده رو با استراتژی استیت ماشین حل میکنیم .
خب شکل بالا یه استیت ماشین میلی بدون ورودی هست ، توی هر استیت که هستیم وقتی کلاک بیاد به استیت بعدی میریم و مشخص میکنیم مقدار خروجی چند باشه (اگه خروجی داشته باشیم که توی شکل بالا داریم ) . شکل بالا میگه وقتی توی استیت 0 هستی ، وقتی کلاک اومد خروجی رو صفر کن و برو به استیت 1 ، وقتی توی استیت 1 بودی و لبه کلاک اومد خروجی رو یک کن و برو به استیت 2 و اگه توی استیت 2 بودی با مشاهده لبه کلاک ، خروجی رو صفر کن و برو به استیت 0 و این کار رو مدام تکرار کن .
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24- 25- 26- 27-
module ModeL1( input Clk, input Rst, output reg y ); reg [1:0] State; always @(posedge Clk or negedge Rst) begin if (~Rst) begin State=0; y=0; end else begin case(State) 0 : begin State=1; y=0; end 1 : begin State=2; y=1; end 2 : begin State=0; y=0; end endcase end end endmodule
یه متغییر نیاز داریم که مشخص کنه توی کدوم استیت هستیم ، استیت 0 یا 1 یا 2 که برای اینکار سیگنال دو بیتی کافی هست که در خط 7 تعریف شد . حالا توی ریست برنامه مقادیر اولیه رو میدیم که در ابتدا توی استیت 0 هستیم و خروجی هم صفر هست . با اومدن لبه کلاک و ریست نبودنِ برنامه ، روی استیت یه کیس میزنیم و با توجه به مقدار فعلی استیت مشخص میکنیم خروجی چند بشه و به کدوم استیت بریم ، به همین راحتی .
شکل بالا یه استیت ماشین مور بدون ورودی هست ، توی این نوع استیت ماشین با اومدن لبه کلاک فقط باید مشخص کنی استیت بعدی کدوم استیت هست . مقدار خروجی رو هم درون خود استیت ها مقدار دهی میکنیم ، یعنی فقط نگاه میکنیم الان توی چه استیتی هستیم و خروجی باید چه مقدار باشه . اینکه چه فرقی با قبلی کرد رو بی خیال بشید ، یه مریضی اومده استیت ماشین رو به دو نوع تقسیم بندی کرده ما هم مجبوریم کد وریلاگ شو بنویسیم دیگه :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24- 25- 26- 27- 28- 29- 30- 31- 32- 33- 34- 35-
module ModeL2( input Clk, input Rst, output reg y ); reg [1:0] State; always @(posedge Clk or negedge Rst) begin if (~Rst) begin State=0; end else begin case(State) 0 : State=1; 1 : State=2; 2 : State=0; endcase end end always @(*) begin case(State) 0 : y=0; 1 : y=0; 2 : y=1; endcase end endmodule
مدار رو به دو بخش ترتیبی و ترکیبی تقسیم میکنیم ، توی بخش ترتیبی مشخص میکنیم با اومدن لبه کلاک ، باتوجه به اینکه توی چه استیتی بوده ایم ، مقدار استیت اکنون چند بشود . توی بخش ترکیبی هم در خط 26 مشخص کردیم با توجه به اینکه توی چه استیتی هستیم ، مقدار خروجی چند باشه . خب ببینید ، استیت ماشین مور رو یه جور دیگه هم میشه توصیف کرد که خوشگلتره ، توی کد زیر میان دوتا متغییر تعریف میکنن به اسم استیت فعلی و استیت بعدی ، توی قسمت ترتیبی میگن با هر بار اومدن لبه کلاک ، استیت فعلی بره به استیت بعدی (مساوی بشه با استیت بعدی). حالا اینکه استیت بعدی چیه رو همون جایی مشخص میکنن که مقدار خروجی رو مشخص میکردن ، یعنی توی بخش ترکیبی کد مون ( ایشالا میدونین منظور از ترتیبی و ترکیبی که میگم چیه ؟ من به بلاک هایی که کلاک پالس توش باشه میگم ترتیبی ، بلاک هایی که کلاک پالس نداره رو میگم ترکیبی ، یعنی کد زیر خط 18) .
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24- 25- 26- 27-
module ModeL3( input Clk, input Rst, output reg y ); reg [1:0] State; reg [1:0] Next_State; always @(posedge Clk or negedge Rst) begin if (~Rst) State=0; else State=Next_State; end always @(*) begin case(State) 0 : begin y=0; Next_State=1; end 1 : begin y=0; Next_State=2; end 2 : begin y=1; Next_State=0; end endcase end endmodule
اگه سردر نمیارید هیچ عیبی نداره ، شما اصلا نباید سردر بیارید ، شما باید این سبک کد نویسی هارو حفظ کنین که اگه یجایی استیت ماشین بهتون دادن دقیقا به این سبک عمل کنید . البته استیت ماشین هارو میشه به هزاران ریخت و شمایل توصیف کرد ولی من همین دو مدل رو بلدم که گفتم .
شکل بالا دقیقا همون استیت ماشین قبلی هست ، فقط بجای اینکه بگیم استیت 0 اومدیم یه اسم واسش گذاشتیم IDLE و برای بقیه استیت ها هم یه اسم هایی گذاشتیم . درواقع فقط یکم جنگولک بازی درآوردیم که اگه یه زمانی بجای اینکه بگیم استیت 0 یا 1 یا 2 ، خواستیم برای استیت هامون اسم بذاریم چطور باید عمل کنیم :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24- 25- 26- 27- 28- 29- 30- 31-
module ModeL4( input Clk, input Rst, output reg y ); reg [1:0] State; reg [1:0] Next_State; parameter IDLE = 2'b00; parameter Pre = 2'b01; parameter Final = 2'b10; always @(posedge Clk or negedge Rst) begin if (~Rst) State=IDLE; else State=Next_State; end always @(*) begin case(State) IDLE : begin y=0; Next_State=Pre; end Pre : begin y=0; Next_State=Final; end Final: begin y=1; Next_State=IDLE; end endcase end endmodule
میایم یه کلک میزنیم ، سه تا پارامتر تعریف میکنیم ، میگیم IDLE همون 0 هست ، Pre همون یک هست و Final همون 2 هست . بنابراین شما هرجا توی کدتون بنویسید IDLE کامپایلر میره بجاش 0 میذاره یا هرجا بنویسید Final کامپایلر خودش میره بجاش 2 میذاره . حالا کد وریلاگ بخش قبلی رو کپی کنین فقط هر جا نوشته بودید 0 یا 1 یا 2 بجاش از کلمه IDLE و Pre و Final استفاده کنید . بدین صورت این جنگولک بازی پیاده سازی گردید.
شکل بالا یه استیت ماشین مور با یک ورودی هست . توی استیت ماشین های مور با ورودی ، استیت بعدی با دو شرط مشخص میشه ، اولا الان توی چه استیتی هستیم ؟ ثانیا ورودی ما چقدره ؟ این دوتا شرط باهم تعیین میکنن که استیت بعدی چی هست . اما مقدار خروجی ما همچنان به ورودی هیچ ربطی نداره و فقط به استیت فعلی بستگی داره ، یعنی توی هر استیتی که باشیم مقدار خروجی تعیین میشه .
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24- 25- 26- 27- 28- 29- 30- 31- 32- 33- 34- 35- 36-
module ModeL5( input Clk, input Rst, input x, output reg y ); reg [1:0] State; reg [1:0] Next_State; always @(posedge Clk or negedge Rst) begin if (~Rst) State=0; else State=Next_State; end always @(*) begin case(State) 0 : begin y=0; if(~x) Next_State=0; else Next_State=1; end 1 : begin y=0; if(~x) Next_State=0; else Next_State=2; end 2 : begin y=1; if(~x) Next_State=1; else Next_State=0; end endcase end endmodule
بنابراین بخش ترتیبی کد هیچ تغییری نمیکنه ، اما توی بخش ترکیبی روی استیت یه کیس میزنیم و توی هر بخش همون ابتدا تکلیف خروجی (y) رو مشخص میکنیم که مقدارش چنده . بعدش با استفاده از شرط ها مقدار ورودی رو بررسی میکنیم و باتوجه به اینکه ورودی ما چنده ، استیت بعدی رو مشخص میکنیم . نکته ساختار مور چیه ؟ ورودی هیچ دخالتی توی تعیین مقدار خروجی نداره ، بلکه فقط استیت بعدی رو مشخص میکنه .
حالا بریم سراغ شکل بالا که استیت ماشین میلی با ورودی هست ، توی این استیت ماشین ، ورودی نقش تعیین کننده در تعیین استیت بعدی و تعیین مقدار خروجی داره . یعنی مقدار خروجی ما و مقدار استیت بعدی ما ، هر دو به کمک مقدار ورودی و استیت فعلی مشخص میشه .
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24- 25- 26- 27- 28- 29- 30- 31- 32- 33- 34- 35- 36-
module ModeL6( input Clk, input Rst, input x, output reg y ); reg [1:0] State; always @(posedge Clk or negedge Rst) begin if (~Rst) begin State=0; y=0; end else begin case(State) 0 : begin if(~x) begin State=0; y=0; end else begin State=1; y=0; end end 1 : begin if(~x) begin State=0; y=0; end else begin State=2; y=1; end end 2 : begin if(~x) begin State=1; y=0; end else begin State=0; y=0; end end endcase end end endmodule
که نحوه توصیف وریلاگ این استیت ماشین بصورت بالا میشه ، یه کیس میزنیم روی استیت و توی هر بخش شرط میذاریم که ورودی چنده ؟ و با توجه به مقدار ورودی هم استیت بعدی رو مشخص میکنیم و هم مقدار خروجی رو تعیین میکنیم . اگه این جلسه واستون سنگین بود باید خدمت تون عرض کنم توهُم زدین ، این مباحث خیلی خیلی ساده است فقط دو شرط داره ، اولا حتما قبلش برید بخونید استیت ماشین چی هست اصلا ، دوما دنبال این نباشید این کد هارو درک و کشف کنید ، اینها فقط یه سری مدل های پیشنهادی هستن که باید حفظ شون کنیم و ازشون الگو بگیریم . خب این جلسه تموم شد و تمام چیزایی که یاد گرفتیم درباره پیاده سازی استیت ماشین بود ، اما اگه دوس دارید ببینید چطور میشه مسائل مختلف رو با استراتژی استیت ماشین حل کرد یا اونها رو تبدیل به استیت ماشین کرد ، بهتره به جلسه "تمرین (4)" مراجعه کنید . توی این جلسه تمرینی ، ما ضرب کننده جلسه قبل رو به روش استراتژی استیت ماشین حل کردیم و بهتون توضیح دادیم که تمام مسائل دنیا رو میشه با استراتژی استیت ماشین حل کرد . نکته پایانی اینکه یه مبحثی هست تحت عنوان نان بلاکینگ که میان به جای = از => استفاده میکنند ، مخصوصا توی استیت ماشین ها که فعلا شما بی خیالش بشید توی جلسه 23 بهش میپردازیم . دانلود فیلم جلسه
رفتن به جلسه بعد ...