FPGA, آموزش, توصیه شده, مقاله

آموزش FPGA قسمت دهم: ساختار شرطی if (بخش دوم)

در قسمت نهم از مجموعه آموزشی FPGA ساختار شرطی if را تشریح کردیم و با استفاده از توصیف مالتی‌پلکسر، با بعضی از قابلیت‌های این ساختار آشنا شدیم.

در این قسمت قصد داریم با ساختار شرطی if بیشتر آشنا شویم و قابلیت‌های دیگر این ساختار را با استفاده از توصیف انکودر اولویت‌دار شناسایی کنیم. پس با سیسوگ همراه باشید.

انکودر

انکودر مداری شناخته شده در دیجیتال می‌باشد و به احتمال زیاد شما هم به عنوان یک مهندس الکترونیک، که در حال خواندن این مقاله هستید با ماهیت انکودر آشنا هستید. پس به توضیح این مدار نخواهیم پرداخت و فقط برای یادآوری، جدول صحت یک انکودر ۲*۴ را در زیر برای شما خواهیم آورد. در ادامه همین جدول صحت را با استفاده از زبان VHDL توصیف خوهیم کرد.

در جدول صحت بالا مشاهده می‌کنید که در هر لحظه فقط یکی از ورودی‌ها می‌تواند مقدار ‘۱’ را داشته باشد. به بیان دیگر انکودر انتظار دارد در هر لحظه فقط یکی از ورودی‌هایش مقدار ‘۱’ را داشته باشد چون در غیر این‌صورت مقدار خروجی مدار، آن مقدار موردانتظار ما نخواهد بود و یک خروجی غیرصحیح خواهیم داشت. و همانطور که در قسمت قبل ذکر کردیم در چنین مداراتی یا سازندگان تراشه‌ها، این موارد را پیش‌بینی و تمهیداتی برای این موارد در نظر می‌گیرند یا اینکه ما باید حواسمان باشد و ورودی ناشناخته‌ای به مدار اعمال نکنیم.

ما قصد داریم در این قسمت کد انکودر را به نحوی بنویسیم که اگر ورودی ناشناخته‌ای به انکودر اعمال شد، به نحوی طبق خواسته‌ی ما ورودی تصحیح شود. اما چگونه؟

انکودر اولویت‌دار

یک انکودر انتظار دارد که از بین همه‌ی ورودی‌هایش، در هر لحظه فقط یکی از ورودی‌ها مقدارش ‘۱’ و مقدار بقیه ورودی‌ها ‘۰’ باشد.
حال اگر برحسب اشتباه حالتی به غیر از حالت بیان شده به ورودی‌ها اعمال شود، باید تصحیح صورت گیرد. ما این روند تصحیح شدن را با استفاده از اولویت در بیت‌های ورودی هموار می‌کنیم. این اولویت می‌تواند سنگین‌‌ترین بیت، یا سبک‌ترین بیتِ ورودی باشد. ما در این آموزش قصد داریم مبنای اولویت را بیتِ سنگین قرار بدهیم. روند به این صورت است که از بیت سنگین به بیت سبک مقدار بیت‌ها بررسی می‌شود تا به اولین بیتی برسیم که مقدارش ‘۱’ باشد. به مجرد اینکه به اولین بیتی رسیدم که مقدارش ‘۱’ است، بقیه بیت‌ها دیگر بررسی نمی‌‌شوند و فرض می‌شود که به جز بیت موردنظر بقیه بیت‌ها مقدارشان ‘۰’ است و این روند معادل حالتی است که در هر لحظه فقط یک بیت مقدارش ‘۱’ است. به مداری که به واسطه عملیات بالا در زبان VHDL توصیف می‌شود انکودر اولویت‌دار می‌گویند.

مدار انکودر اولویت‌دار را با استفاده از ساختار شرطی if در زبان VHDL توصیف می‌کنیم. نحوه‌ی توصیف به این صورت است که اولویت بیت‌ها را با استفاده از اولویتی که در ذات ساختار شرطی if وجود دارد هموار می‌کنیم.

قبل از توضیحات بیشتر ابتدا به کد زیر توجه کنید:

در جلسه قبل ساختار if به طور کامل توضیح داده نشد و قول دادیم که در قسمت بعد، که این قسمت باشد ساختار if را به طور کامل و مفصل توضیح بدهیم، اکنون در کد بالا سینتکس و الگوی کلی این ساختار را به طور کامل مشاهده می‌کنید و عملکرد بدین گونه است که زمانی که process فعال می‌شود، شرط‌ها با اولویت از بالا به پایین بررسی می‌شوند تا زمانی که به اولین شرط صحیح برسیم. پس از اینکه به اولین شرط صحیح رسیدیم، بقیه شرط‌ها دیگر بررسی نمی‌شوند و در نتیجه نهایتا یکی از این ارجاعات انجام خواهد گرفت.

اگر خاطرتان باشد در قسمت نهم ذکر کردیم که اگر در محیط ترتیبی دو یا چندین ارجاع داشته باشیم که در سمت چپ آن‌ها یک سیگنال واحد باشد، فقط آخرین ارجاع در نظر گرفته می‌شود و بقیه‌ی ارجاعات قبل از مرحله سنتز حذف می‌شوند. حال شاید از خودتان بپرسید چرا در کد بالا که سمت چپ همه‌ی ارجاعات سیگنال Q قرار دارد، همه‌ی ارجاعات به جز ارجاع آخر، قبل از مرحله سنتز  حذف نشده‌اند؟ در پاسخ باید بگوییم که اینجا ارجاعات با شروط خاصی انجام می‌گیرند و موضوع خیلی متفاوت خواهد بود با زمانی که چندین ارجاع به یک سیگنال را در محیط ترتیبی بدون هیچ شرطی بنویسیم.

توجه کنید که در ساختار شرطی if، کلمه کلیدی elsif قرار دارد نه elseif. اگر با زبان‌های مختلف کد می‌نویسید این سینتکس‌ها در اوایل کار شاید کمی شما را اذیت کنند، مثلا در زبان C می‌نویسیم else if، در زبان پایتون می‌نویسیم elif و علی‌القاعده در زبان VHDL هم که می‌نویسیم elsif. اگر شما زبان‌های دیگری می‌شناسید که این عبارت به نحو دیگری نوشته می‌شود، خوشحال می‌شویم که این زبان‌ها را به ما نیز معرفی کنید.

در این قسمت نیز ما همانند سایر قسمت‌ها در وهله‌ی اول کدی به صورت مقدماتی نوشتیم، اما اکنون قصد داریم همین کد را کمی بهتر بنویسیم و تغییراتی در کد اولیه ایجاد کنیم.

اولین چیزی که در کد بالا توجه شما را جلب می‌کند اولویت‌های نوشتن خطوط ارجاع است، در کد دوم ظاهرا به نظر می‌رسد که اولویت‎‌ها را برعکس کردیم. خیر اینگونه نیست، کد اول و کد دوم از لحاظ عملکرد دقیقا یکی هستند. برای درک بیشتر موضوع با دقت به توضیحات زیر توجه کنید.

در ساختار if_then_else (کد اول) شرط‌ها از بالا به پایین بررسی می‌شوند و هر زمانی که شرطی برقرار شد، شرط‌های زیرین دیگر بررسی نمی‌شوند و همانطور که حدس می‌زنید اولویت از بالا به پایین است. در نهایت تنها یک ارجاع بیرون آمده از این شرط‌ها وجود دارد. اما در ساختار if_then (کد دوم) شرط‌ها موازی باهم بررسی می‌شوند (برخلاف کد اول، همه‌ی شرط‌ها بررسی می‌شوند) و هیچ اولویتی وجود ندارد. در نهایت ممکن است چندین ارجاع مختلف بیرون آمده از شرط‌ها داشته باشیم.

فرض کنید در کد دوم، دو تا از شرط‌ها برقرار باشند، حال دو ارجاع مختلف بیرون آمده از دل این شرط‌ها داریم. هر دوتای این ارجاعات، ارجاع به سیگنال Q هستند، شبیه به این می‌ماند که دو ارجاع به یک سیگنال یکسان، بدون هیچ شرطی در محیط ترتیبی داشته باشیم. و همانطور که از گذشته می‌دانید آخرین ارجاع انجام خواهد گرفت و ارجاع دیگر بی‌اثر خواهد بود. پس ما همیشه بالاترین اولویتمان را در آخرین شرط قرار خواهیم داد تا زمانی که قرار است آخرین ارجاع انجام بگیرد، هیچ مشکلی در رعایت اولویت‌ها نباشد و در نهایت انکودر اولویت‌دار به خوبی توصیف شود.

ساختار شرطی if را به طور کامل بررسی کردیم و هرآنچه نیاز بود شما از کلیات این ساختار بدانید بیان شد. در قسمت یازدهم ساختار شرطی case را بررسی خواهیم کرد، پس با سیسوگ همراه باشید.

 


انتشار مطالب با ذکر نام و آدرس وب سایت سیسوگ، بلامانع است.

شما نیز میتوانید یکی از نویسندگان سیسوگ باشید.  همکاری با سیسوگ

 

نوشته های مشابه

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

4 دیدگاه در “آموزش FPGA قسمت دهم: ساختار شرطی if (بخش دوم)

  1. NICKE گفت:

    با سلام و خسته نباشید.
    سوالم درمورد ساختار شرطی if هست….
    منظورتان از موازی بودن در این جمله چیه ؟{اما در ساختار if_then (کد دوم) شرط‌ها موازی باهم بررسی می‌شوند (برخلاف کد اول، همه‌ی شرط‌ها بررسی می‌شوند) و هیچ اولویتی وجود ندارد.}
    این کلمه “موازی” در این جمله کمی غلط اندازه
    این شرط ها به صورت موازی بررسی نمی شوند . بلکه از بالا به پایین تک تک شرط ها چک می شوند ولی چون درون شرط ها عبارت ارجاع داریم(signal assignment) همه انها در انتهای پروسس مقدار می گیرند و چون در اینجا تمام ارجاعات به سیگنال Q هست مقدار درون شرط اخر به Q منتقل می شه.مثلا فرض کنیم درون همه شرط ها (کد دوم ) علاوه بر سیگنال , متغیر هم داشته باشیم در اینصورت شرط ها از بالا به پایین چک می شوند ولی عبارات ارجاع درون انها در انتهای پروسس با هم مقدار می گیرند

    1. سلام دوست نازنینم. اول از هر چیزی خوشحالم از اینکه عمیقا توجه کرده‌اید که کد نوشته شده به چه نحوی قرار است پیاده‌سازی شود و نظر خودتان را با ما به اشتراک گذاشتید.

      اگرچه بخشی از نظرات شما در این رابطه صحیح می‌باشد ولی خب بخشی دیگر از نظرات شما به طور کامل اشتباه هستند که در ادامه با دلیل برایتان توضیح می‌دهم.

      شاید اشتباه شما از اینجا ناشی می‌شود که چون اسم محیط ترتیبی می‌آید، فکر می‌کنید که باید به صورت ترتیبی و پشت سر هم شرط‌ها یا ارجاعات انجام شوند. اما اصلا همچین چیزی وجود ندارد، شما هرکدام از شرط‌ها را می‌توانید مالتی‌پلکسری در نظر بگیرید که با توجه به خط فرمانش شرط صحیح را به خروجی خود انتقال می‌دهد، پس هیچ ترتیبی اینجا وجود ندارد و همه این شرط‌ها همزمان و باهم بررسی می‌شوند. تازه اگر قرار بود ترتیبی وجود می‌داشت و یکی پس از دیگری بررسی می‌شدند پس چرا اصلا ما سراغ FPGA می‌آییم، این که همان عملکرد پردازنده یا CPU می‌باشد که به صورت ترتیبی و پشت سرهم کدها را اجرا می‌کند.

      از جنبه‌ای دیگر اگر بخواهم این موضوع را برای شما تفهیم کنم این است که در FPGA مانند میکرو چیزی به اسم برنامه وجود ندارد و کد سنتز شده تبدیل به یک سخت‌افزار می‌شود که هیچ ترتیبی در آن وجود ندارد و با هر کلاک ورودی هر رجیستر به خروجی آن رجیستر منتقل می‌شود و به همین ترتیب ادامه دارد.

      این بحث‌هایی که کردیم هم برای سیگنال صادق است و هم متغیر، اما دوباره بعضی افراد فکر می‌کنند چون متغیر بر خلاف سیگنال، قبل از تمام شدن ارجاع مقدار می‌گیرد پس ترتیبی وجود دارد. این مورد نیز اشتباه است و باید بگویم که همزمان است. و دلیل اینکه متغیر قبل از تمام شدن ارجاع مقدار می‌گیرد برمی‌گردد به اینکه متغیر تبدیل به سیم می‌شود نه مانند سیگنال که تبدیل به رجیستر می‌شود، و قبل از تمام شدن ارجاع مقدارش عوض می‌شود.

      اما شاید بهتر بود که می‌گفتید که به کار بردن سری برای ساختار if_then_else غلط انداز چون واقعا این سری که من به کار بردم به معنای ترتیبی نیست، بلکه به این معناست که مثلا مالتی‌پلکسرهایی که وظیفه بررسی شرط را بر عهده دارند به صورت متوالی و پشت سرهم قرار می‌گیرند و این باعث تاخیر و طولانی شدن مسیر ترکیبی می‌شود نه اینکه واقعا ترتیبی وجود داشته باشد.

      سعی کردم به خوبی این موضوع را برایتان توضیح بدهم که دلیل اشتباهی که فکر می‌کنید را بدانید اما خب شاید باز مسئله برایتان گنگ باشد، پس اگر دوباره ابهامی وجود داشت با ما در میان بگذارید.

      1. NICKE گفت:

        منظور من از ترتیبی بودن محیط پروسس همانطور که حتما خودتان می دانید به معنای مفهومی که در CPU ها وجود دارد نیست . ( در پروسس دستورات به صورت ترتیبی از بالا به پایین چک می شوند اما در یک زمان اپسیلون ( ۱ کلاک ) . درحالیکه در CPU ها هم دستورات به صورت ترتیبی چک می شوند اما هر کدام از دستورات برای مثال ۱ کلاک زمان می برند.)
        شما می گویید اگر به جای اینکه شرط ها را تودرتو بنویسیم ( کد ۱ ) برای هر شرط IF_THEN جداگانه بنویسیم (کد ۲ ) رفتارمان مثل عملکرد CASE در پروسس می شود و شرط ها دیگر اولویتی نسبت به هم ندارند و هرکدام از شرط ها که صحیح باشد اجرا می شود . ولی من فکر می کنم که ( البته ممکن اشتباه باشه) در اینجا شرط ها مثل کد اول از بالا به پایین چک می شوند. فرض کنیم به جای سیگنال Q , متغیر Q داشته باشیم و هر سه شرط کد ۲ true باشند. اگر فرض کنیم که شرط ها اولویتی نسبت به هم ندارند و هر سه با هم اجرا شوند انوقت تکلیف مقدار درون Q چی می شه ؟ سه مقدار که نمی تونه همزمان وارد Q شوند ؟ (در اینجا اگه بگوییم مقدار شرط اخر درون Q ریخته می شود به معنای این است که شرط ها از بالا به پایین چک می شوند )
        البته ممکنه که طرز فکرم در مورد این قضیه اشتباه باشه . خوشحال می شم نظرتون را در این مورد بهم بگید

        1. !خب اجازه بدبد به ترتیب از بالا به پایین جواب سوالاتون را بدم تا یحتمل اینبار قضیه به خوبی تفهیم بشه، ولی خب اگه دوباره سوالی بود همینجا بپرسید.

          در کل چیزی به اسم دستور وجود ندارد و گفتن دستور اشتباه است، چرا؟ چون که اصلا قرار نیست چیزی اجرا بشود که دستوری وجود داشته باشه و اصلا چیزی به اسم بالا به پایین نداریم. همین که بپذیریم و البته درک کنیم که نه دستوری وجود دارد، نه کدی اجرا می‌شود و نه از بالا به پایین داریم (بالا به پایینی فقط هنگام نوشتن کد وجود دارد که گاهی اوقات قبل از مرحله سنتز بخشی از کد توسط نرم‌افزار در نظر گرفته نمی‌شود و بخشی هم مربوط به ساختارهای شرطی که معنی بالا به پایین مانند اجرا در پردازنده را نمی‌دهد)خود درک درستی نسبت به FPGA به ما می‌دهد.

          ما شرط‌ها را تودرتو ننوشتیم چون تودرتو نوشتن با اینکه از else استفاده کنی بسیار متفاوت است و در پیاده‌سازی هم فرق دارد و به دو صورت مجزا پیاده می‌شود.

          وقتی ما در کد دوم از if_then استفاده کردیم دقیقا معادل با case است و هیچ تفاوتی ایجاد نمی‌کند و شرط‌ها به موازات هم چک می‌شوند. حال ممکن است از خود بپرسید فرق این با case در چیست؟ تفاوت اینجاست که ما در ساختار if انعطاف بسیار بیشتر داریم و می‌توانیم هر شرطی را قرار بدهیم اما در این کدی که ما نوشتیم می‌توانستیم از case هم استفاده کنیم چون فقط در شرط از حالت مساوی بودن استفاده شده است.

          حال اینکه به موازات هم بررسی می‌شوند وظیفه ماست که کدام ارجاع را در کدام شرط قرار بدهیم و اگر توجه کرده باشید ما به همین دلیل ارجاعات را در کد دوم ترتیبشان (دوباره توجه کنید که منظور از ترتیب این نیست که ترتیبی شرط‌ها بررسی می‌شوند، بلکه منظور این است که وقتی تمامی شرط‌ها همزمان بررسی شدند و همه نیز درست بودند حال اولویت با کدام ارجاع است که در ادامه بهش می‌پردازیم)را عوض کردیم تا عملکرد به درستی صورت گیرد.

          چون متغیر یکم نیاز به مقدمات داره که شاید شما این مقدمات را ندانید پس بیایید با همین سیگنال بریم جلو و توضیحات را دنبال کنیم اما کلیت ثضیه برای متغیر هم صادق.

          و قسمت آخر سوالاتتون، فرض کنید که طبق گفته شما هر سه شرط درست هستند و طبق گفته ما هم چون ترتیبی بررسی نمی‌شوند و همزمان بررسی صورت می‌گیرد، پس منطقا باید هر سه ارجاع همزمان باهم انجام بگیرد، حال سه ارجاع متفاوت داریم و باید به یک سیگنال واحد ارجاع داده شوند، اما چنین چیزی امکان‌پذیر نیست! ساده‌ترین دلیلش هم اینه که این سه ارجاع طبق جبر بول حداکثر می‌توانند ۲ مقدار منطقی متفاوت داشته باشند و این دو مقدار متفاوت نمی‌توانند به هیچ وجه به یک سیگنال ارجاع پیدا کنند، پس تکلیف چیست؟ برای جواب به این سوال به خوبی به ادامه توضیحات توجه کن.

          فرض کن که این سه شرط در سه مالتی پلکسر که به موازات هم قرار دارند مورد بررسی قرار می‌گیرند و این مالتی پلکسرها متناسب با شرط موردنظر، یکی از ورودی ها را به خروجی خود انتقال می‌دهند. حال سه خروجی داریم و یک سیگنال که قسمت گنگ مسئله برای شما همینجاست. اینجا هر سه خروجی به یک مالتی پلکسر دیگر دیگر می‌روند و در نهایت این مالتی پلکسر با توجه به خط فرمانش یکی از ارجاعات ما را که همان آخرین ارجاع در محیط پراسس می‌باشد را به خروجی یا همان سیگنالی که مدنظر ماست انتقال می‌دهد.

          امیدوارم که توضیحات کامل بوده باشه و توانسته باشم منظورم را منتقل کرده باشم.