در زبان توصیف سخت‌افزار Verilog، دو نوع عملگر برای تخصیص مقادیر به سیگنال‌ها در بلوک‌های رفتاری (always) وجود دارد: تخصیص مسدودکننده (Blocking Assignment) با نماد = و تخصیص غیرمسدودکننده (Non-Blocking Assignment) با نماد <=. درک تمایز بین این دو برای سنتز موفقیت‌آمیز در FPGA (Field-Programmable Gate Array) بسیار حیاتی است، زیرا هر کدام به ساختارهای سخت‌افزاری کاملاً متفاوتی نگاشت می‌شوند و انتخاب نادرست می‌تواند منجر به رفتارهای غیرمنتظره در سخت‌افزار نهایی شود.

ویژگی تخصیص مسدودکننده (Blocking) - = تخصیص غیرمسدودکننده (Non-Blocking) - <=
نماد علامت مساوی (=) علامت کوچک‌تر مساوی (<=)
نگاشت سخت‌افزاری متداول منطق ترکیبی (Combinational Logic) منطق ترتیبی (Sequential Logic) و فلیپ‌فلاپ‌ها
نحوه اجرا (در شبیه‌سازی) دستورات به صورت ترتیبی اجرا می‌شوند؛ دستور بعدی تا پایان اجرای دستور قبلی مسدود می‌ماند. دستورات به صورت موازی اجرا می‌شوند؛ ارزیابی مقادیر سمت راست در ابتدا و به‌روزرسانی نهایی متغیرها تا انتهای بلوک (یا لبه ساعت) به تعویق می‌افتد.
زمان به‌روزرسانی (در شبیه‌سازی) متغیر بلافاصله به‌روز می‌شود و این مقدار جدید می‌تواند در همان بلوک برای تخصیص‌های بعدی استفاده شود. مقدار جدید متغیر تا پایان اجرای بلوک always، یا دقیق‌تر، تا لبه ساعت بعدی (در بلوک‌های ترتیبی)، به‌روزرسانی نخواهد شد.
کاربرد استاندارد بلوک‌های always @* یا always_comb برای توصیف مدارهای ترکیبی (مانند مولتی‌پلکسرها یا دیکودرها). بلوک‌های always @(posedge clk) برای توصیف مدارهای ترتیبی و رجیسترها (مانند فلیپ‌فلاپ‌ها، شمارنده‌ها، شیفت رجیسترها).
ریسک اصلی استفاده نادرست ریسک بالا در ایجاد تله‌های رقابتی (Race Conditions) و عدم تطابق رفتار بین شبیه‌سازی و سخت‌افزار سنتز شده. استفاده نادرست در منطق ترکیبی می‌تواند منجر به سنتز فلیپ‌فلاپ‌های ناخواسته شود.

تخصیص مسدودکننده (=) – مدل‌سازی منطق ترکیبی

عملگر تخصیص مسدودکننده (=) در Verilog، یک عملیات شبیه به زبان‌های برنامه‌نویسی نرم‌افزاری سنتی را مدل می‌کند.

مفهوم اجرا:

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

نگاشت سخت‌افزاری:

این نوع تخصیص برای توصیف منطق ترکیبی (Combinational Logic) ایده‌آل است. اگر از آن در یک بلوک always @* یا always_comb استفاده کنید (که به تمام ورودی‌ها حساس است)، ابزارهای سنتز آن را به شبکه‌ای از گیت‌های منطقی (مانند LUTها در FPGA) که هیچ عنصر ذخیره‌سازی (فلیپ‌فلاپ) ندارند، تبدیل می‌کنند. این شبکه‌ها بدون وابستگی به لبه ساعت، صرفاً بر اساس ورودی‌های فعلی، خروجی را تولید می‌کنند.

خطر بزرگ:

استفاده از تخصیص مسدودکننده (=) در منطق ترتیبی (به خصوص در بلوک‌های کلاک‌شده always @(posedge clk)) به شدت توصیه نمی‌شود. این کار می‌تواند منجر به ایجاد تله‌های رقابتی (Race Conditions) شود، زیرا ترتیب اجرای تخصیص‌ها در شبیه‌سازی ممکن است با ساختار موازی نهایی در سخت‌افزار واقعی FPGA که توسط فلیپ‌فلاپ‌ها پیاده‌سازی می‌شود، متفاوت باشد. این تفاوت رفتاری می‌تواند منجر به نتایج اشتباه و اشکال‌زدایی دشوار شود.

تخصیص غیرمسدودکننده (<=) – مدل‌سازی منطق ترتیبی

عملگر تخصیص غیرمسدودکننده (<=) کلید طراحی منطق ترتیبی (Sequential Logic) در Verilog است و رفتار موازی عناصر سخت‌افزاری مانند فلیپ‌فلاپ‌ها را به درستی مدل می‌کند.

مفهوم اجرا:

وقتی چندین تخصیص غیرمسدودکننده در یک بلوک always وجود دارد، تمام تخصیص‌های سمت راست (یعنی مقادیر جدیدی که باید به متغیرها اختصاص یابد) در ابتدای اجرای بلوک ارزیابی می‌شوند. اما به‌روزرسانی واقعی متغیرهای سمت چپ، تا انتهای بلوک به تعویق می‌افتد. در بلوک‌های کلاک‌شده، این به‌روزرسانی تا وقوع لبه بعدی ساعت به تعویق می‌افتد.

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

نگاشت سخت‌افزاری:

این نوع تخصیص به طور استاندارد برای توصیف منطق ترتیبی و عناصر حافظه‌ای مانند فلیپ‌فلاپ‌ها (Flip-Flops) و رجیسترها استفاده می‌شود. هر سیگنالی که با <= در یک بلوک کلاک‌شده (always @(posedge clk)) مقداردهی شود، به یک فلیپ‌فلاپ (یا مجموعه‌ای از فلیپ‌فلاپ‌ها برای سیگنال‌های چندبیتی) در FPGA سنتز می‌شود.

مزیت بزرگ:

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

قانون طلایی در طراحی FPGA با Verilog

برای جلوگیری از سردرگمی، خطاها و عدم تطابق رفتاری بین شبیه‌سازی و سخت‌افزار سنتز شده، پیروی از این “قانون طلایی” در طراحی FPGA با Verilog ضروری است:

  1. برای توصیف منطق ترتیبی (Sequential Logic): همیشه از بلوک‌های کلاک‌شده (always @(posedge clk) یا always @(posedge clk or negedge rst)) استفاده کنید و همیشه از عملگر غیرمسدودکننده (<=) استفاده نمایید. این مدل‌سازی دقیق فلیپ‌فلاپ‌ها و رجیسترها را تضمین می‌کند.
  2. برای توصیف منطق ترکیبی (Combinational Logic): از بلوک‌های حساس به تمام ورودی‌ها (always @* یا always_comb در Verilog-2001 به بعد) استفاده کنید و همیشه از عملگر مسدودکننده (=) استفاده نمایید. این مدل‌سازی دقیق شبکه‌ای از گیت‌های منطقی (LUTs) را بدون عناصر حافظه‌ای تضمین می‌کند.

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

کلیدواژه ها : Verilog-Blocking-Non-Blocking-تخصیص مسدودکننده-تخصیص غیرمسدودکننده-FPGA-سنتز سخت‌افزار-Synthesis-منطق ترتیبی-Sequential Logic-منطق ترکیبی-Combinational Logic-فلیپ‌فلاپ-Flip-Flop-رجیستر-Register-تله‌های رقابتی-Race Conditions-HDL-always_comb-always block-LUTs-طراحی دیجیتال