الإسناد غير الحاجب
جزء من قسم الأساسيات في رحلة Verilog على Coddy — الدرس 50 من 90.
في الدرس السابق، قمنا بتغطية التعيين الحاصر (=)، والذي يُنفّذ خطوة بخطوة. الآن سنقوم بتغطية التعيين غير الحاصر (<=)، والذي يُنفّذ دفعة واحدة — بالتوازي.
يستخدم التعيين غير الحاجز (non-blocking assignment) المشغّل <=. ويُطلق عليه اسم "غير حاجز" (non-blocking) لأنه لا يحجب تنفيذ العبارة التالية. تنفذ جميع التعيينات غير الحاجزة في كتلة معينة في الوقت نفسه.
الصياغة:
variable <= expression;متى نستخدم الإسناد غير الحاجب (Non-Blocking Assignment)
يُستخدم الإسناد غير الحاجب (<=) لـ المنطق التتابعي (sequential logic) — الدوائر التي تستخدم ساعة (clock) ولديها ذاكرة. تتغير المخرجات فقط عند حافة الساعة (عادةً حافة الصعود).
أمثلة على المنطق التتابعي (sequential logic):
- القالبات (Flip-flops)
- مسجلات البيانات (Registers)
- العدادات (Counters)
- آلات الحالة (State machines)
- مسجلات الإزاحة (Shift registers)
مثال Verilog:
initial begin
a <= 5; // مجدول، لكن لم يُنفَّذ بعد
b <= a + 2; // مجدول، يستخدم القيمة القديمة لـ a
c <= b * 3; // مجدول، يستخدم القيمة القديمة لـ b
endتحدث جميع التعيينات الثلاثة في نفس الوقت باستخدام القيم القديمة (OLD). في نهاية الخطوة الزمنية (Step)، تحدث جميع التحديثات معًا.
Non-blocking في كتل Always (المنطق التتابعي)
يُستخدم non-blocking لـ المنطق التتابعي — الدوائر التي تستخدم clock وتحتوي على ذاكرة (قلابات flip-flops، ومسجلات registers، وعدادات counters).
always @(posedge clk) begin
q <= d; // q يحصل على d عند حافة الساعة
count <= count + 1; // count يتزايد عند حافة الساعة
endيحدث كلا التعيينين في الوقت نفسه، باستخدام values من قبل clock edge.
الملخص
| القاعدة | الشرح |
|---|---|
استخدم <= مع logic التتابعي (sequential) | always @(posedge clk) |
استخدم = مع logic التجميعي (combinational) | always @(*) |
| يتم تنفيذ non-blocking بالتوازي | تحدث جميع التعيينات (assignments) في وقت واحد |
| تتحدث الـ values في end كل Step زمني | ليس فوراً |
التحدي
أكمل التعيين غير الحاجز (Non-Blocking Assignment)
أضف التعيينات غير الحاجزة الناقصة ليعمل مسجل الإزاحة (shift register) ذو الـ 2-bit بشكل صحيح.
كيف يعمل:
- عند كل حافة clock، يحصل
q1علىd - يحصل
q2على القيمة القديمة لـq1
ما يجب القيام به:
- قم بـ Assign لـ
dإلىq1(غير حاجز) - قم بـ Assign لـ
q1إلىq2(غير حاجز)
جرّب بنفسك
module shift_register (
input clk,
input reset,
input d,
output reg q1,
output reg q2
);
always @(posedge clk or posedge reset) begin
if (reset) begin
q1 <= 0;
q2 <= 0;
end else begin
// TODO: أضف منطق الإزاحة
// الخطوة 1: عيّن d إلى q1 (غير حاجز)
// الخطوة 2: عيّن q1 إلى q2 (غير حاجز)
end
end
endmoduleيتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس الأساسيات
4المعاملات - الجزء الأول
المعاملات الحسابيةمعامل باقي القسمة (Modulo)معاملات المقارنةملخص - رياضيات بسيطةمعاملات Bitwise7التعيين والبوابات المنطقية
التعيين المستمرالتعيين باستخدام العملياتالبوابات الأساسية المدمجةبوابات AND و OR و NOTبوابات XOR و XNORمراجعة - دارة البوابات المنطقية5المعاملات - الجزء الثاني
المعاملات المنطقيةمعاملات الاختزالمعاملات الإزاحةمعامل الدمجالمعامل الشرطيمراجعة - تحدي المعاملات3أنظمة العد
التمثيل الثنائيالأعداد محددة الحجمالأعداد غير محددة الحجمالأعداد السالبةالقيم الخاصة X و Zمراجعة - تنسيقات الأعداد6الوحدات
هيكل الوحدةمنافذ الإدخال والإخراجمنافذ Inoutاستدعاء الوحداتربط المنافذ بالاسمربط المنافذ بالترتيبمراجعة - بناء وحدة9الكتل الإجرائية
كتلة Alwaysكتلة Initialقائمة التحسسالإسناد الحاجبالإسناد غير الحاجبمراجعة - Always مقابل Initial