Menu
flag Ar iconالعربيةdown icon

حلقات For في Verilog: مُنشَرة في وقت الترجمة

كيف تختلف حلقات for في Verilog عن نظيراتها في البرمجيات - يتم نشرها بواسطة أداة التركيب إلى عتاد متوازٍ، لا تُنفَّذ تكراريًا في وقت التشغيل.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

المظهر الشبيه بالبرمجيات

حلقة for في Verilog نسخة من حلقة C:

for (i = 0; i < 8; i = i + 1) begin
    // body
end

نفس الأجزاء الثلاثة: المُهيِّئ، الشرط، الزيادة. الجسم يعيد التشغيل طالما الشرط صحيح.

في testbench، يتصرف هذا تمامًا كما تتوقع من البرمجيات. يمر المحاكي بكل تكرار بدوره:

أربعة تكرارات، أربعة سطور خرج. بلا مفاجآت.

تأتي المفاجأة عندما تضع حلقة for داخل شيفرة قابلة للتركيب.

النشر (Unroll)

حلقة for في كتلة always قابلة للتركيب لا تصبح حلقة وقت تشغيل في العتاد. تنشرها أداة التركيب في وقت elaboration - توسّعها إلى N نسخة من الجسم، حيث N هو عدد التكرارات:

تلك تبدو كحلقة. في المحاكاة، يمر المحاكي فعلًا بثمانية تكرارات. في التركيب، تُنشر الحلقة إلى ثمانية فحوصات متوازية لـ data[0] حتى data[7]، كلها تحدث في نفس الوقت. ترى أداة التركيب:

count = 0;
if (data[0]) count = count + 1;
if (data[1]) count = count + 1;
if (data[2]) count = count + 1;
...
if (data[7]) count = count + 1;

…ثم تحوّل التسلسل إلى شجرة جامعات. سلوك وقت التشغيل هو "انظر إلى كل البتات الثماني في وقت واحد واحسب كم منها يساوي 1"، في مسح توافقي واحد.

التضمين: حلقة for في Verilog القابل للتركيب ليست مجانية. حلقة بـ 64 تكرارًا تصبح 64 نسخة من الجسم في العتاد. إن كان الجسم معقدًا، فقد بنيت كتلة توافقية كبيرة. استخدم الحلقات عندما يكون N صغيرًا (حفنة إلى عشرات قليلة). للأعداد الأكبر، تريد عادةً عدّادًا متزامنًا مع clock وآلة حالة.

حدود ثابتة مطلوبة

يمكن لأداة التركيب نشر الحلقة فقط إن عرفت N في وقت elaboration. هذا يعني أن حدود الحلقة يجب أن تكون ثوابتًا:

// Works - bound is constant
for (i = 0; i < 8; i = i + 1) ...

// Works - bound is a parameter
for (i = 0; i < WIDTH; i = i + 1) ...

// Doesn't synthesize - bound depends on a runtime signal
for (i = 0; i < dynamic_count; i = i + 1) ...

الشكل الأخير قد يعمل في المحاكاة، لكن أداة التركيب سترفضه. إن احتجت فعلًا حلقة معدودة في وقت التشغيل، فابنِها بآلة حالة متزامنة مع clock وregister عدّاد - العتاد ليس له حلقات بعدد تكرار متغير كما في البرمجيات.

generate for مقابل for الإجرائية

بناء منفصل لكن مرتبط هو generate for، الذي يستخدم genvar ويعيش خارج كتل always:

genvar i;
generate
    for (i = 0; i < 8; i = i + 1) begin : g
        bit_inverter inv(.x(in[i]), .y(out[i]));
    end
endgenerate

ذلك يطبع 8 نسخ من bit_inverter (مُغطّى في Module Instantiation). إنه هيكلي - تقول "اصنع 8 نسخ من هذا sub-module" - لا سلوكي.

تمييز سريع:

  • for إجرائية (داخل always) - تنشر الجمل داخل كتلة سلوكية واحدة.
  • for للتوليد (خارج always) - تُكرّر بناءات هيكلية كاملة: instances، جمل assign، كتل مُسماة.

استخدم ما يطابق ما تكرره.

متى تتألق for: عمليات Vector

الحلقات في أفضل حالاتها عندما تقوم بنفس العملية لكل بت في vector. عدّ السكان، parity، عكس البايتات، توليد جدول البحث:

32 تكرارًا، كل واحد يفعل إسناد بت واحدة - أكثر قابلية للقراءة بكثير من كتابة 32 إسناد wire يدويًا. تنشرها أداة التركيب بنظافة.

while وrepeat وforever

بعد for، لـ Verilog ثلاث بناءات حلقة أخرى - في الغالب لـ testbenches:

// Run until a condition fails
while (~done) begin
    @(posedge clk);
    cycles = cycles + 1;
end

// Run N times - simpler than for when you don't need a counter
repeat (8) @(posedge clk);

// Run forever - clock generators, monitoring loops
always #5 clk = ~clk;
forever begin
    @(posedge clk);
    $display("count=%0d", count);
end

while وrepeat وforever قابلة للتركيب فقط في حالات ضيقة (لا سيما repeat بعدد ثابت وجسم متزامن مع clock). في testbenches أدوات مفيدة؛ في RTL القابل للتركيب فضّل for معدودة إضافة إلى آلة حالة صريحة.

for إجرائية في testbenches

في testbench، تتصرف حلقات for كما تفعل البرمجيات. استخدمها بحرية:

حلقات متداخلة تمسح كل تركيب من دخلين 2-بت. يشغّل المحاكي التكرارات تتابعيًا. لا قلق بشأن النشر - testbenches لا تُركَّب.

أخطاء شائعة

استخدام حلقة for في شيفرة قابلة للتركيب بحدّ غير ثابت. سترفضها أداة التركيب. إن كان الحد وقت تشغيل، ابنِ عدّادًا وآلة حالة.

نسيان أن جسم الحلقة يصبح عتادًا متوازيًا. حلقة بـ 64 تكرارًا بضرّاب في الجسم هي 64 ضرابًا متوازيًا - على الأرجح ليس ما تريد. لـ datapaths واسعة، ابنِ ضرابًا واحدًا وغذّه تتابعيًا.

خلط integer i وreg اسمه i. الاثنان نطاقان مختلفان؛ الـ integer يفوز داخل الحلقة. اختر أسماء واضحة لتفادي الالتباس.

ماذا بعد

لديك الآن كل بناء إجرائي يقدمه Verilog. الفصل التالي يجمع كل ذلك في الأنماط التي يشحنها مصممو الرقمي فعلًا: المنطق المتزامن مع clock - flip-flops، registers، وpipelines - وآلات الحالة المنتهية - الاصطلاح القياسي لأي متحكم بأوضاع تشغيل متعددة.

الأسئلة الشائعة

كيف تعمل حلقات for في Verilog؟

صياغيًا تبدو مثل C: for (i = 0; i < N; i = i + 1) statement;. لكن للشيفرة القابلة للتركيب، يتم نشر الحلقة في وقت elaboration - تُوسّعها أداة التركيب إلى N نسخة من الجسم. لا يوجد عدّاد حلقة في وقت التشغيل ولا حلقات في العتاد. لـ testbenches، تتصرف حلقات for مثل نظيراتها البرمجية لأن المحاكي يستطيع المرور بها تتابعيًا.

هل حلقة for قابلة للتركيب في Verilog؟

نعم، لكن فقط عندما تكون حدود الحلقة ثوابتًا معروفة في وقت elaboration. تنشر أداة التركيب الحلقة إلى N نسخة متوازية من الجسم. إن اعتمدت الحدود على إشارة وقت تشغيل، فالحلقة غير قابلة للتركيب - عليك تحويلها إلى تصميم تسلسلي متزامن مع clock.

ما الفرق بين for وgenerate for في Verilog؟

حلقة for داخل كتلة always بناء إجرائي يُركَّب بالنشر. حلقة generate for (مع genvar) بناء صريح لوقت elaboration ينتج عتادًا هيكليًا - عدة instances من modules، عدة wires، عدة جمل assign. استخدم for داخل الكتل الإجرائية؛ استخدم generate for خارجها لتكرار الهيكل.

هل لـ Verilog حلقة while؟

نعم - while (condition) statement;. قابلة للتركيب فقط عندما تستطيع أداة التركيب إثبات أن الحلقة تنتهي بعدد محدود من التكرارات. عمليًا هذا نادر، لذا تظهر while غالبًا في testbenches والشيفرة للمحاكاة فقط. للتكرار القابل للتركيب، استخدم حلقة for معدودة بدلًا من ذلك.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن