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

Timescale وDelays في Verilog: التحكم في زمن المحاكاة

كيف يضبط توجيه timescale وحدة #delay`، قواعد دمج وحدات مختلفة عبر الملفات، وكيف تتفاعل delays مع المنطق المتزامن مع clock.

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

ماذا يعني "الزمن" في Verilog

ليس لـ Verilog مفهوم مدمج للثواني. يُقدّم المحاكي "وحدات زمن" - ticks أعداد صحيحة عشوائية - وتستخدم شيفرتك #N لانتظار N منها. توجيه `timescale هو ما يربط تلك ticks بالزمن الحقيقي.

`timescale 1ns / 1ps

module test;
    initial begin
        $display("t = %0t", $time);   // 0
        #5;
        $display("t = %0t", $time);   // 5 ns
        #1.5;
        $display("t = %0t", $time);   // 6500 ps (or 6.5 ns)
        $finish;
    end
endmodule

معاملان:

  • الوحدة (الرقم الأول): ماذا يعني #1. 1ns يقول tick واحد هو نانوثانية واحدة.
  • الدقة (الرقم الثاني): كم بدقة تتعقّب المحاكاة الزمن داخل تلك الوحدة. 1ps يقول تُقرّب delays الكسرية إلى البيكوثانية.

الدقة لا يمكن أن تكون أخشن من الوحدة (1ps / 1ns غير شرعي). اختيارات شائعة:

  • 1ns / 1ps - المعيار الفعلي. كل شيء بالنانوثانية، دقة sub-nanosecond لأي تأخيرات بوابات.
  • 1ps / 1ps - عند نمذجة دارات سريعة جدًا أو عندما يكون كل تأخير sub-nanosecond.
  • 1us / 1ns - للمحاكيات البطيئة بمقياس مُضمَّن (أزمنة بايت UART، بروتوكولات بطيئة).

أين تضعه

`timescale هو توجيه مترجم، لا بناء على مستوى module. يذهب على قمة الملف بالضبط، قبل أي module:

`timescale 1ns / 1ps

module foo(...);
    // ...
endmodule

نطاقه "من هذه النقطة فصاعدًا في ترتيب الترجمة، حتى `timescale التالي أو نهاية الترجمة". هذا له تضمين دقيق: ملف بلا `timescale صريح يرث ما أعلنه الملف المُترجم سابقًا، الذي يعتمد على ترتيب قراءة المترجم للملفات. تجنّب المفاجأة: ضع `timescale على قمة كل ملف.

محرر المتصفح في هذه المستندات يضبط timescale افتراضيًا لك (عادةً 1ns / 1ps)، ولهذا عملت الأمثلة في المستندات السابقة دون إعلان واحد. في مشروع حقيقي ستكون صريحًا.

#delay في الممارسة

بعد `timescale 1ns / 1ps:

#5            // wait 5 ns
#100          // wait 100 ns
#1.5          // wait 1.5 ns (precision allows it)
#0.001        // wait 1 ps (just barely above precision)
#0            // zero-delay; useful for ordering events at the same time

داخل كتلة initial أو always، #N يحجب التدفق الإجرائي لـ N وحدة زمن. يوقف المحاكي هذه الكتلة مؤقتًا (الكتل المتزامنة الأخرى تستمر) ويستأنف بعد التأخير.

يمكنك إسباق إسناد بتأخير:

#10 a = 1;        // wait 10 ns, then assign
data <= #2 new_value;   // schedule the non-blocking assignment 2 ns from now

الشكل الأول هو دعامة testbench. الشكل الثاني (non-blocking متأخر) يُستخدم في محاكاة مستوى البوابة لنمذجة تأخير الانتشار.

توليد Clock

النمط الكلاسيكي:

`timescale 1ns / 1ps

module test;
    reg clk = 0;
    always #5 clk = ~clk;
    // ...
endmodule

مع timescale 1ns / 1ps، #5 هو 5 ns. يتقلب clock كل 5 ns، فتعطي فترة 10 ns - clock 100 MHz. لتغيير التردد، غيّر التأخير:

نصف الفترةالفترةالتردد
#12 ns500 MHz
#2.55 ns200 MHz
#510 ns100 MHz
#1020 ns50 MHz
#2550 ns20 MHz
#50100 ns10 MHz

إن أردت نصف فترة كسري (#2.5)، تحتاج دقتك لدعمه - دقة 1ps تتعامل مع أي شيء حتى 0.001 ns، فأي تردد معقول جيد.

مزج Timescales عبر الملفات

تصميم حقيقي له ملفات كثيرة، ويمكنها إعلان timescales مختلفة. يستخدم المحاكي timescale كل ملف لتفسير delays في ذلك الملف. إن قال module_a.v `timescale 1ns / 1ps واستخدم #5، فهي 5 ns. إن قال module_b.v `timescale 1us / 1ns واستخدم #5، فهي 5 us.

هذا غير مرئي في الغالب لأن المحاكي يُقدّم محور زمن عالمي بصرف النظر - لكن يعني أن نفس #N في ملفين قد يعني أشياء مختلفة بشكل صارخ. الحل: اختر timescale واحد (المعيار الصناعي هو 1ns / 1ps) وضعه على قمة كل ملف. لا تخلط.

Delays غير قابلة للتركيب

نقطة حاسمة: #delay موجودة فقط للمحاكاة. أداة التركيب تقرأ:

// In synthesizable RTL - WRONG
always @(posedge clk) begin
    out <= #2 in;
end

…وإما تتجاهل #2 (معظم الأدوات) أو ترفض البناء (linters أكثر صرامة). توقيت العتاد الحقيقي يُحدَّد بـ clock وبتأخير انتشار البوابات - كلاهما غير مرئي للشيفرة المصدر.

القاعدة: استخدم # فقط في testbenches. RTL القابل للتركيب ليس له # delays. إن وجدت نفسك تريد تأخيرًا في شيفرة قابلة للتركيب، فأنت في الحقيقة تريد عدّادًا يتقلص على clock - هكذا "ينتظر" العتاد الحقيقي.

$time مقابل $realtime

طريقتان لقراءة زمن المحاكاة الحالي:

  • $time تُرجع عدد صحيح 64 بت بوحدات وحدة timescale الحالي.
  • $realtime تُرجع real بوحدات وحدة timescale الحالي، لكن بدقة كاملة.

لتسجيل testbench، $time تقريبًا دائمًا كافية. ألجأ إلى $realtime فقط عندما تحتاج دقة sub-tick في جمل الطباعة.

نصائح عملية

  • أعلن `timescale دائمًا على قمة كل ملف. 1ns / 1ps هو الافتراضي الآمن.
  • استخدم #delay فقط في testbenches. عامل غيابه في الشيفرة القابلة للتركيب كقاعدة ثابتة.
  • طابق فترات clock مع التردد المستهدف. إن كنت تُحاكي تصميم 50 MHz، استخدم فترة clock 20 ns - الفترات غير المتطابقة قد تُخفي أخطاء حساسة للتوقيت.
  • للتحفيز المعدود بالدورات، استخدم @(posedge clk) بدلًا من #. قوي ضد التغييرات في فترة clock.

ماذا بعد

شاهدت الآن كل مستند في هذه الدروس عن Verilog. من أساسيات اللغة (wire مقابل reg، modules، عوامل)، عبر الكتل الإجرائية والتحكم في التدفق، إلى التصميم المتزامن وآلات الحالة، وأخيرًا أدوات testbench التي تُثبت أن كل ذلك يعمل. حان وقت بناء شيء - playground بجوار هذه المستندات هو نفس المحاكي الذي استخدمناه طوال الوقت، جاهز لأي module ترسمه.

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

ماذا يعني `timescale 1ns / 1ps في Verilog؟

يخبر المحاكي: 'وحدة زمن واحدة في هذا الملف هي نانوثانية واحدة، والأزمنة تُتعقّب بدقة بيكوثانية.' بعد ذلك التوجيه، #5 ينتظر 5 ns، #1.5 ينتظر 1.5 ns (مقرّب إلى البيكوثانية)، و$time يُبلَّغ بالنانوثانية. الرقم الأول هو الوحدة؛ والثاني هو الدقة.

هل أحتاج `timescale في كل ملف Verilog؟

أفضل ممارسة: نعم. نطاق التوجيه ينتهي عند \timescaleالتالي أو نهاية الترجمة، فالملفات بلا توجيه ترث ما أعلنه الملف المُترجم سابقًا. هذا يجعل التوقيت غير حتمي عبر البناءات. ضع`timescale 1ns / 1ps` على قمة كل ملف مصدر - هذا الاصطلاح الأكثر شيوعًا - ولن تحصل على مفاجأة.

ماذا تعني #5 في Verilog؟

#5 يُقدّم زمن المحاكاة بـ 5 وحدات زمن. الوحدة تأتي من توجيه \timescaleالنشط. مع`timescale 1ns / 1ps، #5هو 5 نانوثوانٍ. مع`timescale 1us / 1ns، #5هو 5 ميكروثوانٍ. الرقم يمكن أن يكون كسريًا -#1.5` يعمل إن كانت دقتك أدق من الوحدة.

هل #delay قابل للتركيب في Verilog؟

لا. #delay يؤثر فقط على المحاكاة - أداة التركيب تتجاهله أو ترفضه. توقيت العتاد الحقيقي يأتي من إشارة clock وتأخير انتشار البوابات، لا من جمل #. استخدم # بحرية في testbenches؛ لا تكتبها أبدًا في RTL القابل للتركيب.

Coddy programming languages illustration

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

ابدأ الآن