زبان VHDL یک زبان توصیف سخت افزار بسیار مشهور می باشد. این زبان برای برنامه نویسی آی سی هایی با نام FPGA می باشد و نیز در طراحی ASIC نیز زبان های توصیف سخت افزار استفاده می شود.
VHDL مخفف کلمه ی VHSIC Hardware Description Language است که خود VHSIC مخفف Very High Speed Integrated Circuit است و این زبان برای توصیف سخت افزار با سرعت بسیار بالا می باشد.
در زیر لینک ویدیوهای آموزشی FPGA مربوط به سایت Altera و Xillinx قرار داده شده است. این ویدیوهای شامل آموزش VHDL و بخشهای مختلف سخت افزار و نکات مهم هنگام برنامه نویسی می باشد
http://www.xilinx.com/training/free-video-courses.htm#FPGA
http://www.altera.com/education/training/curriculum/fpga/trn-fpga.html
برخی نمونه برنامه های VHDL که تدریس شده است، به صورت زیر می باشند
(در دوره ی FPGA برنامه VHDL به مراتب بیشتر از این برنامه ها نوشته می شود و این فقط بخشی از آن ها می باشد)
برنامه VHDL که هر یک ثانیه یک بار یک LED را خاموش و روشن می کند به زبان VHDL
در این برنامه فرکانس کلاک برابر 3200 هرتز است و دوره ی تناوب کلاک 312.5 میکروثانیه می شود و اگر پالس ورودی هر 156.25 میکرو ثانیه معکوس شود، این فرکانس ساخته می شود. شکل بالا شبیه سازی برنامه ی فوق است.
برنامه VHDL شمارنده ی 0 تا 9999 بر روی سون سگمنت به زبان VHDL
در این برنامه یک شمارنده ی 0 تا 9999 ساخته شده است. در این برنامه فرکانس کلاک ورودی FPGA برابر 3200 هرتز است. در این برنامه جهت تازه سازی 4 سون سگمنت باید 3200 را بر 4 تقسیم کنیم که می شود 800 و اگر هر سگمنتی 50 بار در ثانیه خاموش و روشن شود می شود 16. در این برنامه در پروسس دوم با دریافت هر 16 کلاک ورودی یک سگمنت انتخاب شده و کد مخصوص آن نمایش داده می شود.
برنامه VHDL فرکانس متر با FPGA
در تصویر بالا فرکانس ورودی 500 هرتز است. تا لود شدن کامل این تصویر صبر نمایید.
در این برنامه نیز فرکانس ورودی برابر 3200 هرتز است. در این برنامه سه پراسس نوشته شده است. در پراسس دوم با دریافت هر لبه ی بالا رونده ی فرکانس مورد اندازه گیری بستگی به مقدار سیگنال r یا شمانده ی فرکانس را صفر می کنیم یا فرکانس را می خوانیم و یا فرکانس را یک واحد اضافه می کنیم. در پراسس اول با دریافت هر 16 کلاک ورودی به c یک واحد اضافه می شود و وقتی c برابر 3 شد، q یک واحد افزایش پیدا می کند. وقتی q برابر 51 شد (این عدد را در 4 و 16 ضرب کنبد تا 3200 هرتز شود) متغیر r برابر 2 می شود تا در پراسس دوم فرکانس خوانده شود و وقتی q برابر 52 شد، r یک می شود تا فرکانس مجددا صفر شود.
در پراسس سوم رقم های یکان، دهگان، صدگان و هزارگان فرکانس شمارش شده جدا می شود و چون ما در این برنامه فقط چهار سون سگمنت داریم می توان تا فرکانس 9999 هرتز را اندازه گرفت.
برنامه VHDL استفاده از حافظه ی FIFO
در این برنامه از یک حافظه ی FIFO داخل FPGA استفاده شده است که با ابزار Core Generator ساخته شده است. حافظه های FIFO به معنی First In First Out نوعی RAM هستند که برای ذخیره سازی اطلاعات بکار می روند. این حافظه ها در پروتکل های مختلفی مانند UART، USB و PCI-Express بکار می روند.
در این برنامه din و dout به ترتیب داده های ورودی و خروجی، ren و wen به ترتیب فعال ساز خواندن و نوشتن، wclk و rclk به ترتیب کلاک نوشتن و خواندن، full مشخص کننده ی پر بودن FIFO و Empty مشخص کننده ی خالی بودن FIFO می باشد.
برنامه VHDL مبدل UART به پارالل
در این برنامه اطلاعات از طریق رابط UART دریافت می شود و سپس به صورت 8 بیتی در خروجی آماده می شود.
پروتکل UART به این صورت است که در حالت بیکاری ولتاژ خط برابر 5 ولت است. هنگام دریافت داده این ولتاژ 0 می شود و پس از گذر زمان مشخصی ارسال داده شروع می شود و پس از ارسال 8 بیتی داده یک بیت توقف که 5 ولت است دریافت می شود و خط مجددا به حالت بیکاری می رود (یا ارسال جدیدی آغاز می شود). در این برنامه نرخ ارسال داده ها 9600 است یعنی در هر ثانیه 9600 بیت ارسال می شود یعنی هر بیت حدود 104 میکروثانیه ارسال می شود. اگر فرکانس کلاک ورودی را 50 مگاهرتز فرض نماییم، اگر شمارنده ای تا 5200 شمارش نماید، زمان 104 میکروثانیه را ایجاد می نماید. در این برنامه از یک ماشین حالت استفاده شده است که حالت های w، Stop، Data، start و Idle را دارد که بستگی به پالس ورودی به یکی از این حالت ها می رود.
البته ولتاژ 5 ولت در ارتباط UART می تواند 3.3 ولت نیز باشد.
برنامه VHDL مبدل UART به پارالل به همراه حافظه ی FIFO
در این برنامه دو قسمت وجود دارد. یکی برنامه ی بالا است که با نام مبدل سریال به پارالل (S2P_Bridge) نام گذاری شده است و دیگری یک حافظه ی FIFO است که به صورت Core از آن استفاده شده است. عملکرد برنامه به این صورت است که داده هایی خروجی مبدل UART به پارالل درون FIFO ذخیره می شوند و هرگاه که بخواهیم، آنها را می خوانیم. در این صورت هیچکدام از داده های دریافتی هدر نمی رود.
Pattern Recognization
در این برنامه می توان یک الگوی بیتی را (که مثلا می تواند به عنوان رمز باشد) پردازش نمود (تشخیص الگو). اگر در ورودی پالسی به مدت 3 میلی ثانیه یک باشد و سپس 1 میلی ثانیه صفر باشد و سپس 2 میلی ثانیه یک باشد و سپس صفر شود، دریافت شود، خروجی به مدت 1 ثانیه یک شود و اگر قبل از اتمام این 1 ثانیه مجددا این پالس دریافت شود، خروجی به مدت یک ثانیه ی دیگر فعال باقی بماند. در این برنامه فرکانس برد 50 مگاهرتز در نظر گرفته شده است. این برنامه از سه قسمت مهم تشکیل شده است که آنها را در شکل زیر مشاهده می کنید.
در شکل بالا قسمت Build_1ms از روی کلاک اصلی 1 میلی ثانیه تاخیر برای قسمت Build_1s ایجاد می کند تا پالس دریافتی همانطور که در دو شکل بالا تر پیداست، بعد از گذر 1 میلی ثانیه خروجی را یک کند. قسمت recognize_pulse نیز وظیفه ی تشخیص پالس ورودی را دارد و با دریافت پالس ورودی یک خروجی به قسمت Build_1s می فرستد تا این قسمت خروجی خودش را High نماید.
تقسیم کننده ی فرکانسی بدون استفاده از ماژول DCM
در این برنامه فرکانس ورودی 50 مگاهرتز بر اعداد 2، 4، 8، 16، 32، 64، 128 و 256 تقسیم می شود و بستگی به دیپ سوییچ موجود در مدار یکی از این فرکانس ها به خروجی انتقال پیدا می کند.
ساخت موج PWM
فر کانس روی برد در این برنامه 50 مگاهرتز است.
این برنامه از دو پراسس تشکیل شده است. در پراسس اول وقتی شمارنده به ک میلیون رسید (یک پنجاهم فرکانس) مقدار کلید ها بررسی می شود و در صورت فشرده شدن آنها میزان صفر یا یک بودن موج PWM که به عهده ی سیگنال Count2 و count3 است افزایش یا کاهش می یابد و در پراسس بعدی با توجه به مقدار این دو سیگنال در مورد تولید موج pwm تصمیم گیری خواهد شد.
دیفرانسیلی کردن پایه خروجی (یا پایه ی ورودی)
پروتکل های جدید مانند USB، اترنت، CAN یا RS485 همگی دیفرانسیلی هستند. دلیل دیفرانسیلی شدن کاهش نویز و افزایش برد انتقال اطلاعات خواهد بود. تقریبا تمامی پایه های FPGA این قابلیت را دارند که به صورت دیفرانسیلی کار کنند. برای این کار شما باید کتابخانه ی unisim را به برنامه اضافه نموده و با استفاده از Port Map در فایل پیوست پایه های ورودی و خروجی را وصل نمایید. در این برنامه پایه ی دیفرانسیلی به صورت ورودی است یعنی دو سیگنال را گرفته و در خروجی اش به ما یک سیگنال می دهد. پایه های دیفرانسیلی خروجی هم وجود دارند (OBUF) که ما به آنها یک ورودی می دهیم و آنها اطلاعات را به صورت دو پایه ی دیفرانسیلی خروجی ارسال می کنند. ما در برنامه تمامی سیگنال ها را به صورت معمولی بکار می بریم اما در نهایت در فایل top آنها را به پایه های دیفرانسیلی وصل می کنیم.
اتصال ال سی دی کاراکتری به FPGA و نمایش عدد صفر بر روی آن
این برنامه از چند ماشین حالت ساخته شده است.
1) بعد از اجرای هر یک از حالت های زیر ابتدا به حالت Busy رفته و صبر می کنیم تا ال سی دی دستور ما را اجرا نماید و سپس به حالت بعدی می رویم 2) init در این حالت عدد 38h (تعیین مد 8 بیتی برای ال سی دی) به LCD ارسال می شود. 3) ond: در این حالت نمایشگر روشن می شود (با ارسال عدد 0Fh به نمایشگر). 4) cls: در این حالت با ارسال عدد 01h نمایشگر پاک می شود 5) sd: در این حالت عدد صفر بر روی نمایشگر چاپ می شود (کد اسکی عدد صفر 30h است)
برنامه VHDL دریافت اطلاعات از UART و نمایش بر روی LCD
در این برنامه فرکانس کلاک برابر 50 مگاهرتز است و UART با نرخ ارسال 9600 کار می کند که عکس آن 104 میکرو ثانیه می شود و با 5208 کلاک به زمان 104 میکرو ثانیه خواهیم رسید (همانطور که در چند برنامه ی قبل گفته شد). کافی است که داده را دریافت کنیم و پس از دریافت پرچم rdy را یک کنیم تا lcd داده ی دریافتی را بر روی نمایشگر نشان دهد. در این برنامه همزمان با دریافت توسط دو فایل tx_time و uart_t مقدار زمان برای کامپیوتر ارسال می شود که هیچ ربطی به UART گیرنده و LCD ندارد. در واقع FPGA دو برنامه را به صورت همزمان و جدای از هم اجرا می کند. ماشین حالت lcd دو حالت بیشتر دارد که یکی برای رفتن به سطردوم از نمایشگر و یکی برای پاک کردن نمایشگر و بازگرداندن مکا نما به سطر اول است.
عملکرد گیرنده به این صورت است که 32 بایت را دریافت کرده (پس از دریافت 1 بایت به سطر دوم می رود) و بر روی خانه های نمایشگر نشان می دهد و پس از آن به دلیل پر شدن خانه های نمایشگر، باید آن را پاک کنیم.
اسکن صفحه کلید کامپیوتر و نمایش آن بر روی نمایشگر
پایه های صفحه کلید کامپیوتر از دید کانکتور مادگی (پشت کامپیوتر) به صورت شکل زیر می باشد:
کلید ها ی صفحه کلید کامپیوتر کد هایی شبیه به شکل زیر دارد.
(کد کلید های صفحه کلید کامپیوتر که چند کلید کدشان به اشتباه نوشته شده است)
اسکن صفحه کلید کامپیوتر مشابه ارتباط UART است و شکلی شبیه به شکل زیر دارد
با زدن هر کلید صفحه کلید خروجی شده و برای ما کلاک و داده ارسال می کند و ما باید در لبه ی پایین رونده ی کلاک داده ها را بخوانیم. به دلیل اینکه در حالت عدم ارسال FPGA و صفحه کلید هر دو ورودی هستند، قرار داد یک مقاومت Pull Up در پایه های صفحه کلید الزامی است. اگر FPGA پایه ی Clock را صفر کند، صفحه کلید تمامی کلید های فشرده شده را در FIFO ی داخلیش نگه داری کرده و پس از یک شدن این پایه آنها را به FPGA ارسال می کند.
مشکل اینجاست که کد های ارسالی از طرف صفحه کلید غیر قابل نمایش بر روی ال سی دی هستند و باید به کد اسکی تبدیل شوند تا قابل نمایش روی ال سی دی باشند. در فایل rd_kbd.vhd ثابت 256 عضوی k_code_l وظیفه ی تبدیل کد های صفحه کلید به کد اسکی را دارد و فقط برای حروف کوچک کار می کند (وقتی که کلید Shitf را نگه نداشته باشیم). در واقع این ثابت با استفاده از Lock Up Table ها پیاده سازی می شود. در این فایل یک ماشین حالت وجود دارد:
1) free: تا هنگامی که خط آزاد نیست (یعنی پایه های کلاک و داده صفر هستند) صبر می کند 2)wpk: این حالت حالت بیکاری است و آنقدر در این حالت می مانیم تا پایه ی کلاک صفر شود 3) cl: تا وقتی پایه ی کلاک صفر است در این حالت میمانیم 4) ch: تا وقتی پایه ی کلاک یک است در این حالت میمانیم 5) rd: این حالت وقتی اجرا می شود که کلاک صفر شود یعنی لبه ی پایین رونده ایجاد شود در این حالت اگر 8 بیت داده را دریافت نکرده ایم داده را ذخیره کرده و به حالت 3 باز میگردیم تا لبه ی پایین رونده ی بعدی بیاید. در غیر این صورت بستگی به کد دریافت شده کد را به اسکی تبدیل می کنیم. (با فشردن کلید ESC ال سی دی پاک خواهد شد) و پس از آن سیگنال RDY را یک کرده تا ال سی دی داده را بر دارد و نمایش دهد.
حرکت یک مستطیل در صفحه ی RGB
نمایش یک مستطیل رنگی در صفحه
در این برنامه فرکانس کلاک برابر 50 مگا هرتز است که با بلوک DCM به 110 مگاهرتز می رسد تا بتواند یک تصویر 1440 در 900 پیکسل را 80 فریم در ثانیه نشان دهد. یعنی داریم:
1440*900*80=106MHz
که با بلوک DCM فرکانس 110 مگا هرتز را می توان ساخت یعنی حدود 85 فریم در ثانیه می توان تصویر را نشان داد. در این برنامه به کمک دو کلید می توان یک مستطیل رنگی را در صفحه ی نمایش حرکت داد.
عملکرد سیگنال RGB (که برای مانیتور های CRT طراحی شده است و مانیتور های ال سی دی آن را به فرمت خودشان تبدیل می کنند) به این صورت است که نمایشگر از 1440 ستون و 900 سطر تشکیل می شود. در ابتدا Hsync یک و Vsync صفر می شود تا اشعه به سمت راست حرکت کند و سطر اول را اسکن نماید. سپس Hsync صفر می شود تا اشعه به ستون صفر برگردد (برای بازگشت زمان لازم است) سپس Hsync یک می شود و به همین ترتیب اشعه 900 سطر را طی می کند و در انتها Vsync یک شده تا اشعه به سطر اول برگردد که زمان برگشت هم زمان لازم دارد. باید این کار در ثانیه 80 بار انجام شود. پس با محاسبه ی زمان بازگشت اشعه باید Hsync تا 1903 و Vsync تا 931 شمارش نمایند ولی وقتی Hsync به 1440 و Vsync به 900 رسید باید اشعه خاموش شود.
در این برنامه دو پایه برای رنگ آبی و قرمز و سه پایه برای رنگ سبز استفاده شده است که 4 حالت قرمز و 4 حالت آبی و 8 حالت سبز را ایجاد می کنند یعنی 128 رنگ مختلف را می توان ایجاد نمود. کانکتور RGB که 15 پایه دارد که سه تای آن برای RGB و دو تا برای Vsync و Hsync و بقیه یا زمین هستند یا بی استفاده. برای تبدیل سیگنال آبی یا قرمز یا سبز به یک سیگنال باید از مقاومت هایی به شکل زیر استفاده شود. مثلا برای سیگنال آبی:
در شکل بالا مقاومت R2 نصف مقاومت R1 است
بدیهی است که هرچه مقدار پایه های Blue بیشتر باشد (مثلا 8 پایه باشد) می توان رنگ های بیشتری ایجاد نمود. مانند شکل زیر:
مقدار این مقاومت ها به ترتیب از R1 به R8 باید نصف شوند یعنی اگر R1 برابر 20K است، R2 باید 10K باشد و R3 برابر 5 کیلو باشد و به همین ترتیب.
در واقع مقاومت های بالا نوعی مبدل DAC یا همان مبدل دیجیتال به آنالوگ هستند که برای خروجی هایی با بیت کم استفاده می شوند.
ادغام همه ی برنامه های بالا
برای نمایش موازی بودن عملکرد FPGA برنامه ی حرکت مستطیل رنگی با کمک دو کلید بر روی پورت VGA و همچنین دریافت کد از UART و صفحه کلید کامپیوتر و نیز ارسال زمان از طریق UART به کامپیوتر و نیز تولید موج PWM همگی با هم در این برنامه قرار دارند و مستقل از هم اجرا می شوند.
برنامه ی FIFO بدون استفاده از Core
در این برنامه دو شمارنده لازم است یکی wr_index و دیگری rd_index است. که rd_index به خانه ای اشاره می کند که قرار است از آن خانه اطلاعات خوانده شود و wr_index به خانه ای اشاره می کند که قرار است در آن نوشته شود. با هر بار نوشتن در FIFO مقدار count زیاد می شود و هرگاه count به مقدار max برسد (در این برنامه FIFO حجمی برابر 16 بایت دارد که بیشتر هم می تواند بشود) یعنی FIFO پر شده است و آن را از طریق پایه ی Full اعلام می کند. با هر بار خواندن از FIFO نیز count کم می شود و هرگاه به صفر رسید پایه ی Empty یک می شود که نشان می دهد FIFO خالی است. هدف از نوشتن این برنامه درک کامل عملکرد FIFO است.
توصیف یک RAM با VHDL بدون استفاده از Core
RAM به دو صورت است: تکی و دوبل. در مدل اول یا می توان از RAM خواند یا در آن نوشتن ولی در مدل دوم در حین خواندن از RAM می توان نوشتن هم انجام داد و به آنها Single Ram و Dual RAM می گویند. توصیف RAM در این برنامه به صورت Single Port RAM است. در صورتی که پایه ی DIR یک باشد، اطلاعات از RAM می خواند و در غیر این صورت اطلاعات در RAM قرار می دهد مشروط بر اینکه پایه ی EN یک باشد و در غیر این صورت باس RAM به حالت Hi-Z خواهد رفت
مرتب کردن چهار عدد 8 بیتی در 3 کلاک
در این برنامه از ماشین حالت استفاده شده است و در سه کلاک این کار را انجام می دهد. در کلاک اول ورودی ها را دو به دو با هم مقایسه می کند و بزرگتر ها (برنده ها) انتخاب شده و در کلاک دوم برنده ها دو به دو با هم و بازنده ها دو به دو با هم مقایسه می شوند. درکلاک سوم نتیجه ی نهایی بدست خواهد آمد.
استفاده از Core ضرب کننده و شبیه سازی آن با ابزار textio
ضرب کننده ی داخلی FPGA می تواند 18 بیت را در 18 بیت ضرب کند و یک خروجی 36 بیتی به ما بدهد. برای تست این ضرب کننده باید یک سری عدد به ورودی های آن داده و خروجی را نگاه کنیم. می توان ورودی های ضرب کننده را در فایل هایی ذخیره کرد و خروجی ضرب کننده را نیز در فایل ذخیره کنیم. برای این منظور از ابزار textio استفاده می شود.
استفاده از تابع، کتابخانه و پکیج
ممکن است برنامه نویس VHDL مجبور شود تا از دستوراتی در همه ی برنامه ها استفاده نماید که این دستورات به کرار بکار در این برنامه ها استفاده می شود. با تابع کردن آنها دیگر نیازی به هر بار نوشتن آنها نیست.
ساخت FIR Filter و بدست آوردن ضرایب آن با FDA Tool در نرم افزار MATLAB
برای ساخت فیلتر FIR با استفاده از Core آماده ضرایبی برای فیلتر لازم است که این ضرایب را از نرم افزار MATLAB بدست می آوریم. کافی است که این نرم افزار را باز کرده و در آن بنویسیم FDA Tool تا ابزار لازم نمایش بیابد.
ممنون از سایت فوق العادتون
سلام استاد عزیز… می دونم ک حدود 5 سال از نشر مطالبتون می گذره اما واقعا کارتون عالیه. ممنون بابت زحماتتون. ای کاش کدهای جدید و کاربردی دیگری رو هم اگه میشه، اضافه کنید… تشکر فراوان
سلام لطفا درمورد برنامه ی فرکانس متر توضیحات بیشتری بدید بنظرم توضیحاتتون کم هست و کد به نسبت برنامه های دیگه یه مقدار نامفهومه.سپاس گزارم
فرکانس متر یعنی اندازه گیری تعداد لبه های پالس در یک ثانیه. با دانستن این مفهمو می توان کد را متوجه شد.
دو شمارنده می خواهیم یکی شمارش زمان 1 ثانیه و دیگری شمارش تعداد لبه های کلاک.
سلام خسته نباشید
تشکر فراوان بابت مطالبه مفیدتون!
یه سوالی داشتم اینکه برنامه شمارنده 0 تا 9999 با استفاده از سون سگمنت رو طبق کدوم مدار نوشتین؟
مدارشو لازم دارم!!!
طبق برد آموزشی
درود بر شما درود بر شما درود بر شما
میشه این سوالو جواب بدین خواهش !!!!!!!!
در صورت یک بودن بیت start (یک بیتی) ،( input (8 bit را گرفته و در 8 clk بعدی بیت های input را به ترتیب از سمت راستترین بیت یکی یکی به output (یک بیتی ) انتساب دهید .
gxth …
کد UART را مطالعه کنید شبیه به همین عمل می کند
واقعا مرسی ممنون عالی بود …:)
بسیار عالی بود.با سپاس از شما استاد
بسیار مفید بود . دست مریزاد…..
با سلام
خسته نباشید.
در ابتدا جا داره از ارائه این همه مطالب با ارزش آموزشی تشکر فراوان داشته باشم.
می خواستم ببینم اگر در مورد کدهای VHDL بالا سئوالی داشتم کجا میتونم مطرح کنم.
یا اینکه شما آموزش یا مشاوره از راه دور هم دارید.
منتظر پاسخ هستم.
با تشکر
سوال خود را ایمیل کنید
در صورتی که وقت زیادی لازم نداشته باشد پاسخ گو هستم
امکان مشاوره از راه دور وجود ندارد