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

Verilog wire مقابل reg: متى تستخدم أيهما (مع أمثلة)

النوعان الرئيسيان للبيانات في Verilog - wire للوصلات المستمرة وreg للتخزين الإجرائي - والقاعدة التي تختار بها بينهما في كل مرة.

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

اسمان، وظيفة واحدة

كل إشارة في Verilog لها نوع. النوعان الأولان اللذان ستلتقي بهما هما wire وreg. كلاهما يمكن أن يحمل قيمة. كلاهما يمكن أن يكون بت واحدة أو متعدد البت. الفرق ليس عن ماهية الإشارة - بل عن من يقودها.

  • إشارات wire تُقاد خارج الكتل الإجرائية - بجمل assign، أو بمخارج sub-modules، أو بمنافذ دخل module.
  • إشارات reg تُقاد داخل الكتل الإجرائية - initial أو always.

هذه القاعدة بالكامل. الأسماء غريبة لأنها سبقت الطريقة الحديثة لكتابة Verilog. reg لا يصبح دائمًا register في العتاد. تابع القراءة لمعرفة السبب.

wire: الوصلة المستمرة

wire هو سلك كهربائي. يحمل ما يُنتجه قائده، باستمرار. طريقتان لقيادة wire:

ثلاث ملاحظات:

  • y وz مُعلنان wire في module وwire مرة أخرى في testbench.
  • يُقادان بـ assign - هذا شكل continuous-assignment. يُعاد حساب الطرف الأيمن كلما تغيّرت أي إشارة فيه.
  • لا يمكننا كتابة y = a & b داخل كتلة always مع إبقاء y كـ wire. سيرفضها المترجم.

إن نسيت كلمة wire، فإن Verilog يُعلن عن الإشارة ضمنيًا على أنها wire بت واحدة - وهو أحيانًا ملائم وأحيانًا خطأ صامت. معظم الفرق تُفعّل خيار أداة يُخطئ عند الأسلاك الضمنية. كن صريحًا وتجنب الفخ.

reg: تخزين داخل كتلة إجرائية

reg هو إشارة تُسند إليها داخل initial أو always. الاسم بقايا من أيام اللغة الأولى عندما كان "reg" يشبه "register"؛ في الاستخدام الحديث، reg هو فقط نوع أي إشارة تكتب إليها شيفرة إجرائية.

count هو reg داخل module (لأن كتلة always تكتب إليه) وwire في testbench (لأن منفذ خرج DUT يقوده). نفس الإشارة، أدوار مختلفة، أنواع مختلفة في كل نطاق.

لماذا لا يعني "reg" دائمًا "register"

إليك أكثر فخ شيوعًا للمبتدئين. هذا module يُعلن عن y كـ reg - لكن العتاد المُركَّب لا يحوي flip-flop:

كتلة always @(*) حساسة لـ أي تغيّر في الدخل. إنها توافقية. أداة تركيب ترى هذا النمط وتُنتج بوابة AND - لا flip-flop، لا ساعة، فقط منطق. كلمة reg متطلب نحوي بحت لأن y مُسند داخل always.

للحصول على flip-flop فعلي، يجب أن تكون كتلة always حساسة لحافة ساعة:

always @(posedge clk) begin
    q <= d;
end

هذا هو النمط "أداة التركيب رجاءً اصنعي flip-flop": قائمة حساسية متزامنة مع clock، non-blocking assignment. نفس كلمة reg، عتاد مختلف تمامًا. نغطّي التمييز في كتلة Always وBlocking مقابل Non-blocking.

القرار في الممارسة

في كل مرة تُعلن إشارة، اسأل: كيف سأقودها؟

  • ستقود بـ assign؟ → wire.
  • توصيل بمنفذ خرج sub-module؟ → wire.
  • منفذ دخل module؟ → wire. (المداخل دائمًا wire.)
  • ستقود من initial أو always؟ → reg.
  • منفذ خرج module تقوده شيفرة إجرائية؟ → output reg.
  • منفذ خرج module يقوده assign؟ → output wire. (أو فقط output - الاتجاه وحده يفترض wire.)

شجرة القرار هذه تغطّي كل وضع ستلتقي به في Verilog العادي.

تنازع القائدين

إشارات wire يمكن نظريًا أن يكون لها قائدون متعددون - هكذا تعمل tri-state buses، حيث يمكن لعدة modules قيادة نفس السلك وتذهب الخاملة إلى المعاوقة العالية (z). للمنطق العادي، جملتا assign تكتبان لنفس السلك تُنتجان سلوكًا غير معرَّف:

assign y = a;
assign y = b;   // BAD - y has two drivers

قد يختار المحاكي إحداها، أو يُخرج الإشارة X، حسب الأداة. على أي حال، إنه خطأ. قائد واحد لكل سلك ما لم تكن تبني bus صراحةً.

إشارات reg يمكن أن تُقاد فقط من كتلة إجرائية واحدة. كتلتا always تُسندان لنفس reg خطأ تركيب وغريب في المحاكاة. نفس القاعدة: قائد واحد.

تحديث SystemVerilog: logic

SystemVerilog (المجموعة الفائقة التي تطور Verilog إليها) تضيف كلمة مفتاحية واحدة تحلّ محل الاثنين: logic. يمكن أن تُقاد إشارة logic بـ assign أو بكتلة إجرائية - لكن ليس كليهما - والمترجم يمنعك من إعداد خطأ قائد متعدد بالخطأ.

module modern(input logic a, input logic b, output logic y);
    assign y = a ^ b;
endmodule

إن كنت تبدأ مشروعًا من الصفر وأداتك تدعم SystemVerilog (وهو ما يفعله المحرر في هذه الصفحة، مع -g2012)، فاستخدام logic في كل مكان يُبسّط القواعد. ملفات .v العادية ما زالت تحتاج إلى تقسيم wire/reg، وسترى كلا الأسلوبين في البرية إلى الأبد.

ماذا بعد

المستند التالي - Vectors and Arrays - يأخذ نفس النوعين ويُظهر كيف تجعلهما متعددي البت. عروض الـ buses، النطاقات، packed dimensions، الفرق بين vector من البتات وarray من vectors. كل ما تحتاجه قبل أن تستطيع بناء أي شيء أكبر من جامع بت واحدة.

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

ما الفرق بين wire وreg في Verilog؟

wire وreg كلاهما يحمل قيمة إشارة في كل لحظة في المحاكاة، لكنك تختار بينهما بناءً على من يقود الإشارة. wire يُقاد من خارج كتلة إجرائية - بـ assign أو خرج sub-module. reg يُقاد من داخل كتلة initial أو always. الأسماء تاريخية ومُضلّلة؛ reg لا يعني دائمًا 'register'.

هل reg في Verilog يعني flip-flop؟

ليس بالضرورة. reg يُركَّب إلى flip-flop فقط عندما تكون كتلة always الخاصة به حساسة لحافة ساعة وتستخدم non-blocking assignment. reg مُسند داخل كتلة توافقية always @(*) يُركَّب إلى منطق توافقي عادي. الكلمة المفتاحية تختار نوع بيانات Verilog، لا العتاد.

متى أستخدم wire مقابل reg؟

قاعدة عامة: إن كنت ستقود الإشارة بـ assign أو ستصلها بمنفذ خرج sub-module، استخدم wire. إن كنت ستُسند إليها داخل كتلة always أو initial، استخدم reg. مدخلات module دائمًا wire. المخارج هي wire إن قادها assign وreg إن قادتها كتلة إجرائية.

هل يمكن الإسناد إلى wire داخل كتلة always؟

لا - هذا خطأ صياغة. إشارات wire يمكن أن تُقاد فقط بـ continuous assignments (assign) أو بتوصيلها كخرج نسخة sub-module. أي شيء داخل initial أو always يجب أن يستهدف reg (أو في SystemVerilog، logic). سيلتقطه المترجم ويشكو من 'left-hand side type mismatch'.

ما هو logic في SystemVerilog؟

logic هو توحيد SystemVerilog لـ wire وreg. يمكن أن يُقاد إما بـ continuous assignment أو بكتلة إجرائية (لكن ليس كليهما في وقت واحد). الشيفرة الحديثة تتجه أكثر فأكثر إلى استخدام logic في كل مكان ونسيان تمييز wire/reg. ملفات Verilog العادية ما زال عليها الاختيار.

Coddy programming languages illustration

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

ابدأ الآن