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

آموزش FPGA قسمت سیزدهم: توصیف عناصر حافظه (بخش دوم)

آموزش FPGA و زبان VHDL
در قسمت دوازدهم از مجموعه آموزشی FPGA مفصلا در رابطه با عناصر حافظه در سیستم‌های دیجیتال صحبت کردیم و به تشریح جزئیات آن‌ها پرداختیم، در ادامه بیان کرده بودیم که این عناصر به دو دسته کلی با نام‌های لچ و فلیپ‌فلاپ تقسیم می‌شوند. نهایتا به شما توصیه کرده بودیم که در تمامی پیاده‌سازی‌ها از فلیپ‌فلاپ به جای لچ استفاده کنید و همچنین برای اولین بار مدارات ترتیبی در محیط Sequential را پیاده‌سازی کردیم. در این قسمت قصد داریم بحث توصیف عناصر حافظه با فلیپ‌فلاپ را که در قسمت قبل نا تمام گذاشتیم، از سر گرفته و توضیح بدهیم که چگونه کدی که در همان قسمت قبل نوشتیم در درون FPGA تبدیل به یک فلیپ‌فلاپ شد. اگر به خاطر داشته باشید، در قسمت‌های اولیه آموزش FPGA گفته بودیم که سیگنال‌ها تحت شرایطی درون FPGA تبدیل به سیم و تحت شرایط دیگری تبدیل به رجیستر می‌شوند، و به شما قول داده بودیم که بعدا در این مورد به طور کامل صحبت کنیم. پس با دقت به توضیحات زیر توجه کنید تا یک بار برای همیشه متوجه شوید که سیگنال‌ها چه موقع تبدیل به سیم و چه موقع تبدیل به رجیستر می‌شوند. در قسمت‌های قبل، سیگنال را تعریف کردیم و همچنین در مثالی از کاربرد آن بهره بردیم، پس شما الان به خوبی می‌دانید که سیگنال چیست و در کجا می‌توایم از آن استفاده کنیم. اما نکته‌ای که هنوز نمی‌دانید این است که سیگنال چه موقع تبدیل به سیم و چه موقع تبدیل به رجیستر می‌شود!
اگر در محیط Concurrent، به سیگنالی ارجاع داده شود، آن سیگنال تبدیل به سیم، و اگر در محیط Sequential، به سیگنالی ارجاع داده شود، آن سیگنال تبدیل به رجیستر می‌شود. به عبارتی دیگر اگر در محیط ترتیبی و درون process به سیگنالی ارجاع داده شود، آن سیگنال تبدیل به رجیستر، در غیر این‌صورت تبدیل به سیم می‌شود.
اجازه بدهید در ابتدا کد قسمت قبل را دوباره بازنویسی کنیم و توضیحاتی را در رابطه با این کد بیان کنیم، و نهایتا با نشان دادن مدار پیاده‌سازی شده در FPGA، ادعای خود مبنی بر اینکه اگر در محیط ترتیبی به سیگنالی ارجاع داده شود، آن سیگنال تبدیل به رجیستر می‌شود را ثابت کنیم. با دقت به کد زیر توجه کنید: در کد بالا ما یک پورت ورودی تک بیتی برای کلاک تعریف کردیم تا با تغییر آن process فعال شود، همچنین یک پورت ورودی تک بیتی و یک پورت خروجی تک بیتی نیز تعریف کردیم تا درون process و در محیط ترتیبی، پورت ورودی را به پورت خروجی ارجاع بدهیم، که ما این کار را در خط 19 ام کد انجام دادیم. اکنون وقت آن رسیده است تا مشاهده کنیم که کد نوشته شده، در FPGA تبدیل به چه سخت‌افزاری شده است. برای این کار ابتدا باید بر روی گزینه‌ی View RTL Schematic دابل کلیک کرده و سپس بقیه مراحل را طبق همان مراحلی که در قسمت سوم بیان کردیم پیش بروید تا به مدار زیر برسید.

Flip_Flop

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

Flip_Flop

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

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

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

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

دیدگاهتان را بنویسید

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

7 دیدگاه در “آموزش FPGA قسمت سیزدهم: توصیف عناصر حافظه (بخش دوم)

  1. MORPHO 110 MORPHO110 گفت:

    با سلام . اگر به یک سیگنال در محیط Sequential ارجاعی داده شود آن سیگنال تبدیل به رجیستر می شود. در بعضی از کد ها این اتفاق رخ نمی دهد . برای مثال در کد زیر دو ورودی A و B درون رجیستر ریخته می شوند(البته در این جا منظورم رجیستر کردن پورتهای ورودی/خروجی یا همان پایپ لاین کردن است ) و سپس روی این دو ورودی عملیات جمع و ضرب انجام می دهیم. ولی موقعی که قسمت view technology schematic را بررسی می کنیم ورودی های AوB درون رجیستر ریخته نمی شوند. دلیل اینکه این رجیسترها پیاده نمی شوند چیست ؟
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;

    entity mac is
    Port (
    CLOCK : in STD_LOGIC;
    A : in SIGNED(7 DOWNTO 0);
    B : in SIGNED(7 DOWNTO 0);
    ACC : out SIGNED(15 DOWNTO 0));
    end mac;

    architecture Behavioral of mac is
    signal ACC_INT : SIGNED(15 DOWNTO 0);
    signal A_INT : SIGNED(7 DOWNTO 0);
    signal B_INT : SIGNED(7 DOWNTO 0);
    begin
    ACC <= ACC_INT ;

    process(CLOCK)
    begin
    if rising_edge ( CLOCK ) then
    A_INT <= A ;
    B_INT <= B ;
    ACC_INT <= ACC_INT + A_INT*B_INT ;

    end if ;
    end process;
    end Behavioral;

    1. سلام دوست نازنین.

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

      حال شما بگویید دانسته این کار را کرده‌اید یا به صورت اتفاقی؟

      اگر به صورت اتفاقی بوده است در کامنت بعدی پاسخ را به صورت کامل خدمتتان ارائه خواهم داد.

      1. MORPHO 110 MORPHO110 گفت:

        با سلام .چند وقتی بود این کد ذهنم را درگیر کرده بود و متوجه نمی شدم به چه دلیل ورودی ها داخل یک رجیستر ریخته نمی شوند ؟ طبق کد بالا اول باید ورودی ها به یک فلیپ فلاپ متصل شوند و بعد خروجی این فلیپ فلاپ ها به ورودی DSP48 متصل شود. ولی موقعی که قسمت view technology schematic را بررسی می کنیم ورودی ها مستقیم به DSP48 متصل شده اند . دلیل این موضوع را متوجه نمی شوم ؟؟ و اگر بخواهیم ورودی ها اول داخل یک فلیپ فلاپ ریخته شوند وبعد وارد منبع اختصاصیمان یعنی DSP48 بشوند باید چکار کنیم ؟

        1. با توجه به کدی که نوشتید باید همین روندی که می‌فرمائید طی شود، اما دلیلش چیست که متفاوت است؟

          ابتدا به تصویر زیر به خوبی دقت کنید:
          https://sisoog.com/wp-content/uploads/2020/02/DSP48.png

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

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

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

          امیدوارم که متوجه شده باشید که چرا تمامی کد شما با استفاده از یک DSP48 انجام می‌شود.

          البته جزئیات DSP48 بسیار فراتر از تصویری هست که در بالا دیده‌اید و امکانات متنوع و همچنین منعطفی را در اختیار شما قرار می‌دهد.

          1. MORPHO 110 MORPHO110 گفت:

            خیلی ممنون از توضیحاتتون . یک سوال دیگه داشتم . اگر ACC_INT <= ACC_INT + A_INT*B_INT از محیط پروسس به محیط Concurrent انتقال دهیم وقتی قسمت view technology schematic را بررسی می کنیم در نگاه اول, پیاده سازی که انجام شده با کد قبلی یکی است ولی وقتی جزییات پین های ورودی DSP48 را بررسی می کنیم یکی از پایه ها به نام( C(47:0 به پین خروجی DSP48 متصل شده در صورتیکه در کد قبلی به این پین چیزی متصل نشده است. تفاوت این کد با کد قبلی در چیه ؟؟

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