دوران لنفس الرمز
& و| و^ وأشقاؤها المعكوسة تظهر بشكلين متمايزين:
- شكل ثنائي (معاملان):
a & b- عملية bitwise بين vectors متساوية العرض. - شكل unary (معامل واحد):
&a- reduction عبر كل بتاتaإلى بت واحدة.
المترجم يميز بينهما بعدّ المعاملات. عرف التسمية المستخدم هو "عوامل bitwise" للشكل الثنائي و"عوامل reduction" للشكل unary.
Bitwise: بت واحدة في كل مرة
المجموعة الكاملة:
| العامل | الاسم | بت الخرج في الموضع N |
|---|---|---|
a & b | AND | a[N] AND b[N] |
a | b | OR | a[N] OR b[N] |
a ^ b | XOR | a[N] XOR b[N] |
a ~& b | NAND | NOT (a[N] AND b[N]) |
a ~| b | NOR | NOT (a[N] OR b[N]) |
a ~^ b | XNOR | NOT (a[N] XOR b[N]) |
~a | NOT | NOT a[N] |
لاحظ أن ~& و~| و~^ تُكتب بـ tilde أولًا والعامل ثانيًا. إنها رمز واحد؛ لا توجد مسافة بينهما.
عندما يكون للمعاملين عروض مختلفة، يُمدّد الأضيق بالأصفار يسارًا للمطابقة. إن أردت تمديد الإشارة، استخدم معاملات signed صراحةً مع $signed().
Reduction: من بتات كثيرة إلى واحدة
الأشكال unary لنفس العوامل تختصر vector إلى بت واحدة:
ماذا يعني كل واحد:
&dataيُرجع1إن كانت كل بتاتdataتساوي 1، وإلا0. مفيد لفحوصات "هل كل البتات واحد؟".|dataيُرجع1إن كانت أي بت منdataتساوي 1، وإلا0. مفيد لفحوصات "هل هذا غير صفر؟".^dataيُرجع parity - XOR لكل البتات.1إن كان عدد فردي من 1's،0إن زوجي.~&dataو~|dataو~^dataهي معاكسات لما سبق.
ستراها في كل مكان في الشيفرة الحقيقية:
wire empty = ~|fifo_count; // empty iff count is zero
wire all_ones = &mask; // all bits set
wire parity_bit = ^data; // parity of a byte
wire any_request = |request_vector; // is anything requested?
أشكال reduction موجزة وتُركّب إلى أشجار بوابات واضحة: & يختصر إلى بوابة AND متعددة المداخل، | إلى OR متعددة المداخل، ^ إلى شجرة XOR (وهي أيضًا مولّد parity في العتاد).
أنماط شائعة
ضبط ومسح البتات
wire [7:0] data;
wire [7:0] mask = 8'b0000_1000;
wire [7:0] set = data | mask; // forces bit 3 to 1
wire [7:0] cleared = data & ~mask; // forces bit 3 to 0
wire [7:0] toggled = data ^ mask; // flips bit 3
wire [7:0] tested = data & mask; // zero if bit 3 was 0, non-zero otherwise
هذه نفس اصطلاحات معالجة البتات التي ستستخدمها في C. تُركَّب إلى عمليات بوابة واحدة.
فحص ما إذا كانت قيمة تساوي كل واحدات
wire is_max = &counter; // 1 if every bit of counter is 1
reduction AND ببوابة واحدة، مقابل كتابة counter == 8'hFF (التي ستعمل أيضًا؛ تُنتج أدوات التركيب عادةً نفس العتاد).
توليد بت parity
اكتشاف أي إشارة نشطة
wire any_pending = |request_vector;
إن كان request_vector واسعًا (لنقل 64 طلبًا)، reduction OR يختصر إلى إشارة واحدة يمكنك تغذيتها إلى مُشفِّر أولوية أو محكِّم.
عوامل الإزاحة
ما دمنا في العوامل على مستوى البتات، الإزاحات:
a << Nيزيحaلليسار بمواضعNبت، يملأ بأصفار من اليمين.a >> Nيزيحaلليمين بمواضعNبت، يملأ بأصفار من اليسار.a <<< Nإزاحة حسابية لليسار (مثل<<لـ unsigned).a >>> Nإزاحة حسابية لليمين - يملأ ببت الإشارة عندما يكونasigned.
الإزاحات بقيمة ثابتة قوة 2 مجانية في العتاد (مجرد إعادة توصيل). الإزاحات بمتغير وقت تشغيل تُنتج barrel shifter، وهو أكبر لكنه ما زال رخيصًا.
ماذا بعد
شاهدت الآن كل عامل يُرجع قيمة واحدة. المستند التالي - Concatenation وReplication - يغطّي صياغة {} و{N{...}} التي تبني vectors أوسع من قطع، والتي ستستخدمها باستمرار عند الربط بين modules بعروض مختلفة.
الأسئلة الشائعة
ما هي عوامل bitwise في Verilog؟
عوامل bitwise تجمع vectors متساوية العرض موضعًا بموضع. a & b تطبق AND على البت 0 من a مع البت 0 من b، والبت 1 مع البت 1، وهكذا، فتُنتج vector بنفس عرض المدخلات. المجموعة الكاملة هي & (AND)، | (OR)، ^ (XOR)، ~ (NOT)، وأشكال العكس ~&، ~|، ~^ (NAND، NOR، XNOR).
ما هو عامل reduction في Verilog؟
عامل reduction هو شكل unary لعامل bitwise يختصر vector كاملًا إلى بت واحدة. &data يُرجع 1 فقط إن كانت كل بت من data تساوي 1. |data يُرجع 1 إن كانت أي بت تساوي 1. ^data يُرجع XOR لكل البتات - parity. أشكال reduction ليس لها معامل على اليسار، فقط على اليمين.
ما الفرق بين & و&& في Verilog؟
& هو AND على مستوى البتات - يطابق البتات موضعًا بموضع والنتيجة بنفس عرض المعاملات. && هو AND منطقي - يعامل كل معامل كـ boolean (صفر مقابل غير صفر) ويُرجع نتيجة بت واحدة. 4'b1100 & 4'b0011 هو 4'b0000؛ 4'b1100 && 4'b0011 هو 1.
كيف تحسب parity في Verilog؟
استخدم عامل reduction XOR: parity = ^data. يعمل XOR على كل بت في data مع غيرها. لـ vector 8 بت هذا هو data[7] ^ data[6] ^ ... ^ data[0]. النتيجة 1 إن كان عدد فردي من البتات مضبوطًا، 0 إن كان زوجيًا. العكس بـ ~^ يعطي even-parity.
ماذا تفعل ~ في Verilog؟
~ هي NOT على مستوى البتات - تعكس كل بت من معاملها. ~4'b1100 هو 4'b0011. لا تخلط بينها وبين ! (NOT منطقي)، التي تختصر المعامل إلى boolean بت واحدة وتعكس ذلك. !4'b1100 هو 1'b0 (المعامل غير صفر، عكس قيمة الحقيقة يعطي 0).