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

منافذ Module في Verilog: input وoutput وinout مشروحة

كيف تعلن عن منافذ module - input وoutput وinout - أسلوب ANSI لقائمة المنافذ، ومتى يكون output من نوع wire أو reg.

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

واجهة Module

قائمة منافذ module هي واجهته - كل ما يستطيع العالم الخارجي رؤيته ولمسه. داخل module، يحسب الجسم المخارج من المداخل. المنافذ هي الأسلاك التي تعبر الحدود.

إعلان ANSI الحديث يضع الاتجاه والنوع والعرض كلها في القائمة:

module my_module(
    input  wire        clk,
    input  wire        reset,
    input  wire [7:0]  data_in,
    output reg  [7:0]  data_out,
    output wire        valid
);
    // الجسم
endmodule

هذا هو الشكل كاملًا. لكل منفذ:

  • اتجاه: input أو output أو inout.
  • نوع: wire أو reg (أو logic في SystemVerilog).
  • عرض: نطاق مثل [7:0]، أو بت واحدة إن حُذف.
  • اسم: المُعرّف الذي ستستخدمه داخل الجسم.

الاتجاهات الثلاثة

input - يُقاد من الخارج

المداخل دائمًا wire. القائد خارج module - إما إشارة من module أعلى، أو reg من testbench. داخل module، يمكنك قراءة المداخل في تعابير لكن لا يمكنك أبدًا الإسناد إليها:

module reader(input wire [7:0] data);
    initial $display("data = %h", data);
endmodule

كتابة data = ... داخل module ستكون خطأ.

output - يُقاد من الداخل

المخارج تُقاد بشيء داخل هذا module. يمكن أن تكون إما wire (مَقُودة بـ assign أو خرج sub-module) أو reg (مَقُودة من always/initial).

module driver(
    input  wire       a,
    input  wire       b,
    input  wire       clk,
    output wire       y,    // wire - مَقُودة بـ assign
    output reg        q     // reg  - مَقُودة بـ always
);
    assign y = a & b;       // ok لأن y هو wire

    always @(posedge clk)
        q <= a;             // ok لأن q هو reg
endmodule

محاولة الإسناد إلى y داخل كتلة always، أو قيادة q بـ assign، ستكون خطأ ترجمة. اختيار الكلمة المفتاحية يجب أن يطابق نوع القائد.

inout - ثنائي الاتجاه

منافذ inout أسلاك يمكن أن يقودها module أو ما يتصل خارجيًا، بالتناوب. تظهر عند حدود الشريحة - خطوط SDA في I²C، وأرجل GPIO ثنائية الاتجاه، وباصات بيانات مشتركة. داخل module، تتحكم بالاتجاه عبر نمط tri-state:

module bidir_pin(
    input  wire data_out,
    input  wire output_enable,
    output wire data_in,
    inout  wire pin
);
    assign pin     = output_enable ? data_out : 1'bz;
    assign data_in = pin;
endmodule

pin هو السلك المشترك. عندما يكون output_enable مرتفعًا، يقود module pin إلى data_out. وعندما يكون منخفضًا، يُحرّر pin إلى المعاوقة العالية (z)، فيدع قائدًا خارجيًا يستخدمه. data_in يراقب دائمًا ما هو موجود على pin حاليًا.

inout نادر في المنطق الداخلي البحت. إن كنت تبني متحكم ذاكرة أو نواة CPU أو خط معالجة صور، فقد لا تحتاجها أبدًا. إنها ميزة لحلقة I/O عند حدود الشريحة.

منافذ بت واحدة مقابل متعددة البت

نطاق العرض اختياري - احذفه لمنفذ بت واحدة:

input wire valid,         // 1 bit
input wire [7:0] data,    // 8 bits
input wire [31:0] addr,   // 32 bits

يمكنك استخدام parameters للعرض، وهكذا تعمل modules ذات parameters:

module bus #(
    parameter WIDTH = 32
)(
    input  wire [WIDTH-1:0] in,
    output wire [WIDTH-1:0] out
);
    assign out = in;
endmodule

أسلوب ANSI مقابل Verilog-1995

سترى أحيانًا شيفرة قديمة تُقسّم قائمة المنافذ والإعلانات:

// أسلوب Verilog-1995 القديم - لا تفعل هذا في شيفرة جديدة
module foo(clk, data_in, data_out);
    input clk;
    input [7:0] data_in;
    output reg [7:0] data_out;
    // ...
endmodule

قائمة المنافذ تحوي الأسماء فقط؛ ثم يُعلن عن كل منفذ منفصلًا داخل الجسم. مُسهب، وعرضة لأخطاء "مذكور في قائمة المنافذ لكن غير مُعلن"، ويتطلب ضعف الكتابة. أسلوب ANSI-2001 (المُعتمد في هذه المستندات) يُغني عن الاثنين:

module foo(
    input  wire       clk,
    input  wire [7:0] data_in,
    output reg  [7:0] data_out
);
    // ...
endmodule

استخدم أسلوب ANSI. الأدوات تدعمه منذ 2001.

مثال كامل

هذا module واحد يحوي:

  • parameter (WIDTH).
  • مداخل للساعة وreset وتفعيل التحميل والبيانات وتفعيل الإزاحة.
  • خرج reg (data_out) مَقُود داخل كتلة always.
  • خرج wire (msb_out) مَقُود بـ continuous assignment.
  • إعلان كامل بأسلوب ANSI يُدرج اتجاه ونوع وعرض كل منفذ في القائمة.

هذا تقريبًا شكل كل module قابل للتركيب ستكتبه.

ماذا بعد

المستند التالي - Module Instantiation - يُظهر كيف تأخذ هذا module وتستخدمه داخل تصميم أكبر. الـ shifter الذي كتبته للتو ليس مفيدًا بمفرده؛ يكتسب قيمته عندما يأخذ شيء نسخة منه ويصله بنظام.

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

ما اتجاهات المنافذ الثلاثة في Verilog؟

input وoutput وinout. input يُقاد من الخارج. output يُقاد من داخل module. inout ثنائي الاتجاه - مفيد لباصات tri-state حيث يقود module ويقرأ نفس الـ pin. الغالبية العظمى من المنافذ الداخلية هي input أو output؛ ولا تظهر inout إلا عند pins الشريحة.

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

output wire يعني أن الخرج مَقُود بـ continuous assignment أو بمنفذ خرج sub-module - أي شيء خارج كتلة always. output reg يعني أنه مَقُود من كتلة إجرائية (initial أو always). الكلمة المفتاحية تتحكم بإمكانية استهداف الإشارة من داخل always، لا بما إذا كان العتاد المُركّب يحوي flip-flop.

ما هو أسلوب ANSI لمنافذ Verilog؟

أسلوب ANSI يُعلن عن اتجاه كل منفذ ونوعه في قائمة المنافذ مباشرةً: module foo(input wire [7:0] data, output reg [7:0] result);. الأسلوب الأقدم Verilog-1995 يُدرج الأسماء فقط في قائمة المنافذ ثم يُعيد إعلانها داخل module. استخدم دائمًا أسلوب ANSI في الشيفرة الجديدة - أقصر وأقل عرضة للأخطاء وقياسي في كل الأدوات الحديثة.

هل يمكن أن يكون لـ Verilog module عدة inputs وoutputs؟

نعم - يمكن أن يكون لـ module أي عدد من المنافذ في أي مزيج من الاتجاهات. افصل بينها بفواصل في قائمة المنافذ. ترتيب قائمة المنافذ يُحدّد ترتيب الوصل الموضعي عند الـ instantiation، لكنك في الغالب تستخدم وصلات مُسماة (.port(signal)) لتفادي الاعتماد على الترتيب.

Coddy programming languages illustration

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

ابدأ الآن