Menu

Verilog Concatenation ve Replication: {} Operatörleri

Sinyalleri {} ile birleştirme ve {N{...}} ile bir kalıbı N kez kopyalama - parçalardan daha geniş bus'lar kurmak için vazgeçilmez Verilog operatörleri.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Hak Ettiklerini Kazanan İki Küçük Operatör

Verilog'un iki {} şekli vardır:

  1. Concatenation - {a, b, c} - birden çok sinyali daha geniş bir tanesine yapıştırır.
  2. Replication - {N{pattern}} - bir kalıbı N kez kopyalar.

İkisini de sürekli kullanacaksın. Bir bus bölünmesi, birleştirilmesi, doldurulması veya sign ile genişletilmesi gerektiğinde, cevap bu iki operatörden biridir.

Concatenation: {a, b, c}

En basit durum: iki sinyali bir tanede üst üste yığ:

Soldan sağa okuma: a yüksek yarım, b alçak yarımdır. {} içindeki ilk operand en anlamlıdır. Sonucun genişliği operand genişliklerinin toplamıdır.

Herhangi bir sayıda operand'ı concatenate edebilirsin:

wire [31:0] word = {byte3, byte2, byte1, byte0};

Ve operandlar farklı genişlikte olabilir:

wire [11:0] frame = {start_bit, data_byte, parity, stop_bit};
//                    1 bit      8 bit      1 bit   2 bit  = 12

Yaygın bir kural: bir concatenation'un tüm operandlarının açık bir genişliği olmalıdır. Boyutsuz literaller (1'b1 yerine 1) hatalara neden olur çünkü parser kaç bit ayıracağını bilmez. Her zaman 1'b0, 1'b1, 4'd0 yaz; {} içinde asla çıplak 0 veya 1 yazma.

Sol Tarafta Concatenation

Bir atamanın LHS'inde concatenation, geniş bir sinyali parçalarına böler:

Bu kanonik adder-with-carry kalıbıdır. {carry_out, sum_bits} atamanın solunda tek bir 9 bitlik hedeftir ve bitler dağıtılır: üst bit carry_out'a, alt 8 bit sum_bits'e.

LHS concatenation assign'de ve prosedürel bloklarda çalışır:

always @(posedge clk) begin
    {high_byte, low_byte} <= incoming_word;
end

Replication: {N{pattern}}

Replication operatörü, sabit bir sayıda bir kalıbı kopyalar. Şekli {N{pattern}} - bir sayı, sonra kendi parantez çiftinde kalıp:

N bir sabit olmalıdır - derleyicinin elaboration sırasında sonuç genişliğini bilmesi gerekir. Kalıp bir literal, parametre veya genişliği bilinen herhangi bir ifade olabilir.

İç parantezleri unutma. {8 1'b1} bir sözdizimi hatasıdır; {8{1'b1}} doğrudur. Dış {} operatördür; iç {...} tekrarlanan kalıbı sarmalar.

İkisini Birleştirme: Sign ve Zero Extension

İki operatör daha geniş değerler kurmak için doğal olarak birleşir:

{ {8{a_negative[7]}}, a_negative } standart sign-extension kalıbıdır. Şöyle oku: sign bitini sekiz kez tekrarla, sonra orijinal 8 biti ekle. Net sonuç: aynı sayının 16 bitlik iki'nin tümleyeni gösterimi.

Unsigned genişletme için atamaya güvenebilirsin - hedef daha geniş olduğunda Verilog otomatik olarak zero-extend yapar:

wire [15:0] zext_auto = a_unsigned;   // çalışır, üst 8 bit 0

Ama operand ve hedefin ikisi de signed olarak tanımlanmadıkça signed genişletme örtük olarak hiç olmaz. Açık replication deyimi daha güvenlidir.

Faydalı Kalıplar

N Bir'lik Bir Mask Kurma

parameter N = 5;
wire [31:0] mask = { {32-N{1'b0}}, {N{1'b1}} };
// örneğin N=5 ile, mask = 32'h0000_001F

Bir Vektörü Ters Çevirme

Verilog'da yerleşik bir ters çevirme yoktur, ama concatenation ile inline bir tane yazabilirsin:

wire [3:0] forward  = 4'b1010;
wire [3:0] reversed = {forward[0], forward[1], forward[2], forward[3]};
// reversed = 4'b0101

Daha geniş vektörler için bir generate döngüsü veya bir function daha temizdir.

Flag'leri Bir Status Byte'ına Paketleme

wire [7:0] status = {
    error_flag,    // [7]
    overflow,      // [6]
    underflow,     // [5]
    ready,         // [4]
    busy,          // [3]
    1'b0,          // [2] reserved
    1'b0,          // [1] reserved
    valid          // [0]
};

1 bitlik reserved slot'ların açık genişliği var - asla {} içinde çıplak 0 yok.

Yaygın Hatalar

{} içinde boyutsuz literaller. {a, 0} bir sözdizimi hatası veya 32 bit genişliğinde bir sıfırdır. Her zaman boyutlandır: {a, 1'b0}.

Replication'da iç parantezleri unutmak. {8 1'b1} parse edilmez; {8{1'b1}} parse edilir.

Sırayı karıştırmak. {a, b}, a'yı yüksek tarafa, b'yi alçak tarafa koyar. Varsayımı tersine çevir ve bir yerde ters bir byte sırası alacaksın.

Sıfır kez replicate etmek. {0{...}}, standart Verilog'da yasadışıdır. SystemVerilog buna izin verir (ve sıfır genişlikte bir sonuç üretir). Düz Verilog reddeder.

Sırada Ne Var

Artık her Verilog operatörünü gördün. Bir sonraki bölüm vites değiştirir ve yapıya dalar - modüllerin birbirine nasıl bağlandığı, port kuralları ve daha büyük tasarımlar kurmak için alt modülleri instantiate etme sözdizimi.

Sıkça Sorulan Sorular

Verilog'da sinyaller nasıl concatenate edilir?

Süslü parantez kullan: {a, b, c}, operandları soldan sağa yapıştırarak tek geniş bir vektör üretir. a'nın MSB'si sonucun MSB'si olur; c'nin LSB'si sonucun LSB'si olur. Sonucun genişliği operand genişliklerinin toplamıdır. Concatenation hem bir atamanın sağında (bir değer kurmak için) hem de solunda (bir değeri bölmek için) çalışır.

Verilog'da {N{pattern}} ne anlama gelir?

Replication operatörüdür: pattern'in N kopyasını concatenate ederek üretir. {8{1'b1}}, 8 bitlik tamamen birler değeridir (8'hFF). {4{2'b10}}, 8 bitlik 8'b10101010 değeridir. Replication, sıfır ile genişletmenin, sign ile genişletmenin veya herhangi bir tekrarlayan bit kalıbını elle yazmadan kurmanın yoludur.

Verilog'da bir sinyali nasıl sign-extend edersin?

Sign bitini tekrarlamak için replication kullan: { {24{a[7]}}, a }, 8 bitlik a'yı bit 7'yi (sign bit) 24 kez tekrarlayıp orijinali ekleyerek 32 bite genişletir. Unsigned zero-extension için, 1'b0'ı tekrarla veya hedef daha geniş olduğunda atamanın bunu örtük olarak yapmasına izin ver.

Concatenation'ı bir atamanın sol tarafında kullanabilir misin?

Evet - tek geniş bir kaynaktan birden çok hedefe nasıl atama yaparsın budur. {carry, sum} = a + b;, toplamanın sonucunu tek bir ifadede carry'ye (yüksek bit) ve sum'a (geri kalanı) koyar. Her hedef genişliğini korur; parser sağ tarafın bitlerini buna göre dağıtır.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA