1 - سطح گیت
جلسه اول (ماژول ها) جلسه دوم (گیت ها) جلسه سوم (نوع سیگنال) جلسه چهارم (پایان فصل)2 - مقداردهی مداوم
جلسه پنجم (اُپراتور ها) جلسه ششم (آرایه ها) جلسه هفتم (شرط ها) جلسه هشتم (فراخوانی ماژول) جلسه نهم (تست بنچ) جلسه دهم (نگاشت حافظه)3 - سطح رفتاری (ترکیبی)
جلسه یازدهم (بلاک Always) جلسه دوازدهم (ابزار ها) جلسه سیزدهم (نوع پردازش) جلسه چهاردهم (نکات تکمیلی) جلسه پانزدهم (پایان فصل)4 - سطح رفتاری (ترتیبی)
جلسه شانزدهم (لبه ها) جلسه هفدهم (تست بنچ 2) جلسه هجدهم (شمارنده ها) جلسه نوزدهم (ضرب و شیفت) جلسه بیستم (استیت ماشین) جلسه بیست و یکم (کشف رشته) جلسه بیست و دوم (فرکانس) جلسه بیست و سوم (نان بلاک) جلسه بیست و چهارم (پایان)5 - جلسات تمرینی
جلسه تمرین اول (تاخیر ها) جلسه تمرین دوم (الحاق-منطق) جلسه تمرین سوم (شیفت ها) جلسه تمرین چهارم (استیت)6 - مثال های پروژه محور
پروژه طراحی پردازنده RTL پروژه پردازنده Maano پروژه پردازنده MIPS7 - ارتباط و گفتگو
ارتباط با نویسنده گروه تلگرام تبلیغات و آگهیآموزش وریلاگ آموزش Verilog
این جلسه میخام به شمارنده ها بپردازم . شمارنده هارو هم میشه سطح گیت نوشت و هم سطح رفتاری ، که برای سطح گیت حتما باید دانش مدار منطقی داشته باشید . چون باید جدول حالت و کارنو رو تشکیل بدین و روی کاغذ شماتیک مدار شمارنده رو بدست بیارید و بعدش از روی شماتیک ، کد توصیف وریلاگ رو بنویسید . مثلا شکل زیر شماتیک یه شمارنده است که از 0 تا 15 میشماره و با استفاده از فلیپ فلاپ نوع T ساخته شده .
برای توصیف این مدار ابتدا ماژول فلیپ فلاپ T رو کدنویسی میکنیم بعدش توی یه ماژول اصلی ، چهار بار فراخوانیش میکنیم . فلیپ فلاپ T کارش اینه که وقتی لبه کلاک اومد به ورودی T خودش نگاه میکنه اگه T صفر بود به خروجی دست نمیزنه (همون مقدار قبلی خودش) ولی اگه T یک بود ، مقدار خروجی رو معکوس یا نات میکنه :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21- 22- 23- 24-
module TFF( input Clk, input Rst, input T, output reg Q, output Qp ); assign Qp=~Q; always @(posedge Clk or negedge Rst) begin if (Rst==0) Q=0; else begin if (T==0) Q=Q; else if (T==1) Q=~Q; end end endmodule
خب این از کد فلیپ فلاپ که مشابه جلسات قبلی بود . حالا یه ماژول اصلی داریم که ورودیش فقط کلاک و ریست هست و خروجی هم سیگنال 4 بیتی F هستش . نکته اینکه توی تصویر هرچیزی که به رنگ آبی میبینید ورودی هست ، هرچیزی که صورتی هست خروجیه و تمام سیگنال های بنفش سیگنال های واسطه ای هستند .
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18-
module Counter4( input Clk, input Rst, output [3:0] F ); wire [3:0] Qp; wire w1,w2; and(w1,F[0],F[1]); and(w2,w1,F[2]); TFF U0(.Clk(Clk),.Rst(Rst),.T(1'b1),.Q(F[0]),.Qp(Qp[0])); TFF U1(.Clk(Clk),.Rst(Rst),.T(F[0]),.Q(F[1]),.Qp(Qp[1])); TFF U2(.Clk(Clk),.Rst(Rst),.T(w1),.Q(F[2]),.Qp(Qp[2])); TFF U3(.Clk(Clk),.Rst(Rst),.T(w2),.Q(F[3]),.Qp(Qp[3])); endmodule
خب حالا طبق کد بالا ، دوتا گیت اَند که داشتیم رو تعریف کردیم و چهار بار هم فراخوانی فلیپ فلاپ T رو انجام دادیم . توی فلیپ فلاپ اول بجای ورودی T عدد 1 منطقی رو دادیم که معادل همون 5 وُلت توی تصویر هست . برای ورودی T بعدی سیگنال F[0] رو طبق تصویر دادیم و ورودی های بعدی هم w1 و w2 هستند که همون خروجی های گیت های اَند ما هستند. خروجی فلیپ فلاپ ها هم روی F[0] تا F[3] ریخته میشه . نکته اینکه در اینجا از سیگنال های Qp استفاده چندانی نشد فقط توی فراخوانی مقدار شون رو دریافت کردیم و ریختیم روی wire های Qp و بلااستفاده موند.
شکل بالا همون شمارنده بخش قبلی هست که قراره بصورت سطح رفتاری بنویسیم . یعنی یه شمارنده 4 بیتی که قراره 0 تا 15 بشماره :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15-
module Counter4( input Clk, input Rst, output reg [3:0] F ); always @(posedge Clk or negedge Rst) begin if (Rst==0) F=0; else F=F+1; //F=F-1; , F=F+2; end endmodule
خیلی راحت اگه مدار ریست بود مقدار F=0 بشه و اگه مدار ریست نبود یدونه به F اضافه بشه به همین راحتی . حالا اگه خواستید یه شمارنده نزولی بسازید فقط کافیه بجای F+1 بنویسید F-1 تا هروقت لبه کلاک میاد یدونه از F کم بشه ، یا اگه خواستین دوتا دوتا بشمارین کافیه بنویسید F+2 .
خب حالا بیاین یه شمارنده بسازیم که یه ورودی X داره ، هر وقت این ورودی X مقدارش صفر بود ، شمارنده صعودی بشماره و هروقت ورودی X مقدارش یک شد ، شمارنده ما نزولی بشماره :
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20- 21-
module UpDownCounter( input Clk, input Rst, input X, output reg [3:0] F ); always @(posedge Clk or negedge Rst) begin if (Rst==0) F=0; else begin if (~X) F=F+1; else if (X) F=F-1; end end endmodule
مثل کد قبلی فقط یه شرط به کد مون اضافه میکنیم که اگه X صفر بود F=F+1 بشه در غیر اینصورت F=F-1 بشه و شمارنده مون نزولی بشه . می بینید سطح رفتاری چقد آسونه ؟ حالا اگه سطح گیت بود باید کلی جدول و کارنو میزدیم تا به شماتیک مدار برسیم و بعدش تازه شروع کنیم به توصیف اون قطعات . حالا یه شمارنده میخایم توصیف کنیم که از 3 بشماره تا 120 برای اینکار خروجی ما حتما باید 7 بیت یا بیشتر باشه که من کاملا دلبخواهی 8 بیتی در نظر گرفتم .
1- 2- 3- 4- 5- 6- 7- 8- 9- 10- 11- 12- 13- 14- 15- 16- 17- 18- 19- 20-
module Counter( input Clk, input Rst, output reg [7:0] F ); always @(posedge Clk or negedge Rst) begin if (Rst==0) F=3; else begin if (F < 120) F=F+1; else if (F >= 120) F=3; end end endmodule
خب حالا کافیه بگیم توی لحظه ریست بجای اینکه خروجی 0 بشه ، خروجی ما 3 باشه تا شمارش از 3 شروع بشه و با اومدن کلاک هر دفعه یدونه به خروجی اضافه بشه ، البته با این شرط که خروجی به 120 نرسیده باشه ، اگه به 120 رسیده بود خروجی مجددا 3 بشه . حالا فرض کنید بما گفتن شمارنده ای بسازید که دنباله اعداد 13 و 15 و 17 و 17 و 45 رو بشماره و مدام هم تکرار بشه . یه راهش اینه جدول حالت رسم کنیم و کلی کارنو بزنیم تا به شماتیک مدار برسیم و بعدش مدار رو توصیف کنیم اما میشه به روش سطح رفتاری عمل کرد :
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-
module Counter( input Clk, input Rst, output reg [7:0] F ); reg [7:0] MEM [0:4]; reg [2:0] i; always @(posedge Clk or negedge Rst) begin if (Rst==0) begin i=0; MEM[0]=13; MEM[1]=15; MEM[2]=17; MEM[3]=17; MEM[4]=45; end else begin if (i < 4) i=i+1; else if (i >= 4) i=0; end F=MEM[i]; end endmodule
راهی که به ذهن من رسید اینه که 5 تا متغییر تعریف کنم که همشون از یک بردار دوبعدی باشن ، چیزی شبیه به خونه های یک حافظه . وقتی مدار ریست بود یعنی در لحظه اولیه ، مقادیر این خونه هارو بذارم 13 و 15 و 17 و17 و 45 و یه متغییر i تعریف میکنم که هر بار کلاک میاد یدونه بهش اضافه بشه . خروجی شمارنده رو هم برابر i اُمین عددِ حافظه قرار میدم . یعنی ابتدا i من صفر خواهد بود خروجی من MEM[0] یعنی 13 خواهد بود ، بعدش هر بار یدونه به i اضافه میشه و خروجی شمارنده من میشه MEM[1] و MEM[2] و ... تا زمانی که i به 4 برسه ، چون MEM[5] نداریم وقتی که i چهار شد دفعه بعدی i رو صفر میکنیم تا مجددا از اول خونه های حافظه رو توی خروجی نمایش بده . دانلود فیلم جلسه
رفتن به جلسه بعد ...امیرحسین
سلام تو این سوال اخری مقدار i رو داخل ارایش با صفر تا چهار میزاشتید چون الان ای تا دو بیشتر پلاس پلاس نمیشه و خروجیمون 17 دومی و 45 رو نشون نمیده
سید محسن
متغییر i که سه بیتی تعریف شده یدونه یدونه اضافه میشه ، از مقدار صفر تا مقدار چهار اضافه میشه بعد ریست میشه .